This commit is contained in:
tmoschou 2026-08-02 18:48:10 +09:30 committed by GitHub
commit c28e6618b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 699 additions and 17 deletions

View File

@ -35,6 +35,7 @@
* Safely regain ranges and delete retired command stores (CASSANDRA-21212)
* Reduce memory allocations in miscellaneous places along read path (CASSANDRA-21360)
* Avoid ByteBuffer wrapping in cql3.selection.Selector.InputRow to reduce memory allocation rate (CASSANDRA-21362)
* Add blob type support to SAI (CASSANDRA-20012)
* Reduce cost to calculate BTreeRow.minDeletionTime (CASSANDRA-21414)
* Implement custom CassandraThread to keep direct references to frequently used thread local objects (CASSANDRA-21020)
* Avoid megamorphic call overhead at RandomAccessReader#current (CASSANDRA-21399)

View File

@ -2705,6 +2705,10 @@ max_security_label_length: 48
# sai_string_term_size_warn_threshold: 1KiB
# sai_string_term_size_fail_threshold: 8KiB
# Guardrail specifying warn/fail thresholds for the size of blob terms written to an SAI index
# sai_blob_term_size_warn_threshold: 1KiB
# sai_blob_term_size_fail_threshold: 8KiB
# Guardrail specifying warn/fail thresholds for the size of frozen terms written to an SAI index
# sai_frozen_term_size_warn_threshold: 1KiB
# sai_frozen_term_size_fail_threshold: 8KiB

View File

@ -2473,6 +2473,22 @@ drop_compact_storage_enabled: false
# before emitting a failure (defaults to -1 to disable)
#sai_sstable_indexes_per_query_fail_threshold: -1
# Guardrail specifying warn/fail thresholds for the size of string terms written to an SAI index
# sai_string_term_size_warn_threshold: 1KiB
# sai_string_term_size_fail_threshold: 8KiB
# Guardrail specifying warn/fail thresholds for the size of blob terms written to an SAI index
# sai_blob_term_size_warn_threshold: 1KiB
# sai_blob_term_size_fail_threshold: 8KiB
# Guardrail specifying warn/fail thresholds for the size of frozen terms written to an SAI index
# sai_frozen_term_size_warn_threshold: 1KiB
# sai_frozen_term_size_fail_threshold: 8KiB
# Guardrail specifying warn/fail thresholds for the size of vector terms written to an SAI index
# sai_vector_term_size_warn_threshold: 16KiB
# sai_vector_term_size_fail_threshold: 32KiB
# The default secondary index implementation when CREATE INDEX does not specify one via USING.
# ex. "legacy_local_table" - (default) legacy secondary index, implemented as a hidden table
# ex. "sai" - "storage-attched" index, implemented via optimized SSTable/Memtable-attached indexes

View File

@ -20,11 +20,11 @@ SAI adds column-level indexes to any CQL table column of almost any CQL data typ
SAI enables queries that filter based on:
* vector embeddings
* AND/OR logic for numeric and text types
* IN logic (use an array of values) for numeric and text types
* AND/OR logic for numeric, text, and blob types
* IN logic (use an array of values) for numeric, text, and blob types
* numeric range
* non-variable length numeric types
* text type equality
* text and blob type equality
* CONTAINs logic (for collections)
* tokenized data
* row-aware query path

View File

@ -140,10 +140,11 @@ See xref:developing/cql/indexing/sai/sai-read-write-paths.adoc[SAI write path an
SAI supports two on-disk index formats, optimized for:
* Equality and non-exact matching on *strings*.
** Strings are indexed on-disk using the https://en.wikipedia.org/wiki/Trie[trie] data structure, in conjunction with postings (term/row pairs) lists.
The trie is heap friendly, providing string prefix compression for terms, and can match any query that can be expressed as a deterministic finite automaton.
* Equality and non-exact matching on *strings, blobs, and booleans*.
** These literal types are indexed on-disk using the https://en.wikipedia.org/wiki/Trie[trie] data structure, in conjunction with postings (term/row pairs) lists.
The trie is heap friendly, providing prefix compression for terms, and can match any query that can be expressed as a deterministic finite automaton.
The feature minimizes on-disk footprint and supports simple token skipping.
Note that `BLOB` and `BOOLEAN` types support equality queries only.
* Equality and range queries on *numeric and non-literal types*.
** Numeric values and the other non-literal CQL types (`timestamp`, `date`, `UUID`) are indexed on-disk using https://en.wikipedia.org/wiki/K-d_tree[k-dimensional tree], a balanced structure that provides fast lookups across one or more dimensions, and compression for both values and postings.
@ -156,12 +157,11 @@ The SAI disk usage is largely dependent on the underlying data model and the num
== What are the supported column data types for SAI indexing?
The supported types are: `ASCII, BIGINT, DATE, DECIMAL, DOUBLE, FLOAT, INET, INT, SMALLINT, TEXT, TIME, TIMESTAMP, TIMEUUID, TINYINT, UUID, VARCHAR, VARINT`.
The supported types are: `ASCII, BIGINT, BLOB, BOOLEAN, DATE, DECIMAL, DOUBLE, FLOAT, INET, INT, SMALLINT, TEXT, TIME, TIMESTAMP, TIMEUUID, TINYINT, UUID, VARCHAR, VARINT`.
[NOTE]
====
* `INET` support for IPv4 and IPv6 was new starting with Cassandra ???.
* The `DECIMAL` and `VARINT` support was new starting with Cassandra ???.
* The `BLOB` support was new starting with Cassandra 6.0.
* SAI also supports collections -- see the xref:#saiCollectionColumnFaq[next FAQ].
====

View File

@ -1068,6 +1068,8 @@ public class Config
public volatile int sai_sstable_indexes_per_query_fail_threshold = -1;
public volatile DataStorageSpec.LongBytesBound sai_string_term_size_warn_threshold = new DataStorageSpec.LongBytesBound("1KiB");
public volatile DataStorageSpec.LongBytesBound sai_string_term_size_fail_threshold = new DataStorageSpec.LongBytesBound("8KiB");
public volatile DataStorageSpec.LongBytesBound sai_blob_term_size_warn_threshold = new DataStorageSpec.LongBytesBound("1KiB");
public volatile DataStorageSpec.LongBytesBound sai_blob_term_size_fail_threshold = new DataStorageSpec.LongBytesBound("8KiB");
public volatile DataStorageSpec.LongBytesBound sai_frozen_term_size_warn_threshold = new DataStorageSpec.LongBytesBound("1KiB");
public volatile DataStorageSpec.LongBytesBound sai_frozen_term_size_fail_threshold = new DataStorageSpec.LongBytesBound("8KiB");
public volatile DataStorageSpec.LongBytesBound sai_vector_term_size_warn_threshold = new DataStorageSpec.LongBytesBound("16KiB");

View File

@ -1260,6 +1260,34 @@ public class GuardrailsOptions implements GuardrailsConfig
x -> config.sai_string_term_size_fail_threshold = x);
}
@Override
@Nullable
public DataStorageSpec.LongBytesBound getSaiBlobTermSizeWarnThreshold()
{
return config.sai_blob_term_size_warn_threshold;
}
@Override
@Nullable
public DataStorageSpec.LongBytesBound getSaiBlobTermSizeFailThreshold()
{
return config.sai_blob_term_size_fail_threshold;
}
@Override
public void setSaiBlobTermSizeThreshold(@Nullable DataStorageSpec.LongBytesBound warn, @Nullable DataStorageSpec.LongBytesBound fail)
{
validateSizeThreshold(warn, fail, false, "sai_blob_term_size");
updatePropertyWithLogging("sai_blob_term_size_warn_threshold",
warn,
() -> config.sai_blob_term_size_warn_threshold,
x -> config.sai_blob_term_size_warn_threshold = x);
updatePropertyWithLogging("sai_blob_term_size_fail_threshold",
fail,
() -> config.sai_blob_term_size_fail_threshold,
x -> config.sai_blob_term_size_fail_threshold = x);
}
@Override
@Nullable
public DataStorageSpec.LongBytesBound getSaiFrozenTermSizeWarnThreshold()

View File

@ -666,6 +666,18 @@ public final class Guardrails implements GuardrailsMBean
format("Value of column '%s' has size %s, this exceeds the %s threshold of %s.",
what, value, isWarning ? "warning" : "failure", threshold));
/**
* Guardrail on the size of a blob term written to SAI index.
*/
public static final MaxThreshold saiBlobTermSize =
new MaxThreshold("sai_blob_term_size",
null,
state -> sizeToBytes(CONFIG_PROVIDER.getOrCreate(state).getSaiBlobTermSizeWarnThreshold()),
state -> sizeToBytes(CONFIG_PROVIDER.getOrCreate(state).getSaiBlobTermSizeFailThreshold()),
(isWarning, what, value, threshold) ->
format("Value of column '%s' has size %s, this exceeds the %s threshold of %s.",
what, value, isWarning ? "warning" : "failure", threshold));
/**
* Guardrail on the size of a frozen term written to SAI index.
*/
@ -1765,6 +1777,26 @@ public final class Guardrails implements GuardrailsMBean
DEFAULT_CONFIG.setSaiStringTermSizeThreshold(sizeFromString(warnSize), sizeFromString(failSize));
}
@Override
@Nullable
public String getSaiBlobTermSizeWarnThreshold()
{
return sizeToString(DEFAULT_CONFIG.getSaiBlobTermSizeWarnThreshold());
}
@Override
@Nullable
public String getSaiBlobTermSizeFailThreshold()
{
return sizeToString(DEFAULT_CONFIG.getSaiBlobTermSizeFailThreshold());
}
@Override
public void setSaiBlobTermSizeThreshold(@Nullable String warnSize, @Nullable String failSize)
{
DEFAULT_CONFIG.setSaiBlobTermSizeThreshold(sizeFromString(warnSize), sizeFromString(failSize));
}
@Override
@Nullable
public String getSaiFrozenTermSizeWarnThreshold()

View File

@ -605,6 +605,24 @@ public interface GuardrailsConfig
*/
void setSaiStringTermSizeThreshold(@Nullable DataStorageSpec.LongBytesBound warn, @Nullable DataStorageSpec.LongBytesBound fail);
/**
* @return the warning threshold for the size of blob terms written to an SAI index
*/
DataStorageSpec.LongBytesBound getSaiBlobTermSizeWarnThreshold();
/**
* @return the failure threshold for the size of blob terms written to an SAI index
*/
DataStorageSpec.LongBytesBound getSaiBlobTermSizeFailThreshold();
/**
* Sets warning and failure thresholds for the size of blob terms written to an SAI index
*
* @param warn value to set for warn threshold
* @param fail value to set for fail threshold
*/
void setSaiBlobTermSizeThreshold(@Nullable DataStorageSpec.LongBytesBound warn, @Nullable DataStorageSpec.LongBytesBound fail);
/**
* @return the warning threshold for the size of frozen terms written to an SAI index
*/

View File

@ -1057,6 +1057,30 @@ public interface GuardrailsMBean
*/
void setSaiStringTermSizeThreshold(@Nullable String warnSize, @Nullable String failSize);
/**
* @return The warning threshold for blob terms written to an SAI index, as a human-readable string.
* (ex. {@code 10GiB}, {@code 20MiB}, {@code 30KiB} or {@code 40B}) A {@code null} value means disabled.
*/
@Nullable
String getSaiBlobTermSizeWarnThreshold();
/**
* @return The failure threshold for blob terms written to an SAI index, as a human-readable string.
* (ex. {@code 10GiB}, {@code 20MiB}, {@code 30KiB} or {@code 40B}) A {@code null} value means disabled.
*/
@Nullable
String getSaiBlobTermSizeFailThreshold();
/**
* @param warnSize The warning threshold for blob terms written to an SAI index, as a human-readable string.
* (ex. {@code 10GiB}, {@code 20MiB}, {@code 30KiB} or {@code 40B})
* A {@code null} value means disabled.
* @param failSize The failure threshold for blob terms written to an SAI index, as a human-readable string.
* (ex. {@code 10GiB}, {@code 20MiB}, {@code 30KiB} or {@code 40B})
* A {@code null} value means disabled.
*/
void setSaiBlobTermSizeThreshold(@Nullable String warnSize, @Nullable String failSize);
/**
* @return The warning threshold for frozen terms written to an SAI index, as a human-readable string.
* (ex. {@code 10GiB}, {@code 20MiB}, {@code 30KiB} or {@code 40B}) A {@code null} value means disabled.

View File

@ -166,7 +166,8 @@ public class StorageAttachedIndex implements Index
CQL3Type.Native.SMALLINT, CQL3Type.Native.TEXT, CQL3Type.Native.TIME,
CQL3Type.Native.TIMESTAMP, CQL3Type.Native.TIMEUUID, CQL3Type.Native.TINYINT,
CQL3Type.Native.UUID, CQL3Type.Native.VARCHAR, CQL3Type.Native.INET,
CQL3Type.Native.VARINT, CQL3Type.Native.DECIMAL, CQL3Type.Native.BOOLEAN);
CQL3Type.Native.VARINT, CQL3Type.Native.DECIMAL, CQL3Type.Native.BOOLEAN,
CQL3Type.Native.BLOB);
private static final Set<Class<? extends IPartitioner>> ILLEGAL_PARTITIONERS =
ImmutableSet.of(OrderPreservingPartitioner.class, LocalPartitioner.class, ByteOrderedPartitioner.class, RandomPartitioner.class);
@ -206,10 +207,14 @@ public class StorageAttachedIndex implements Index
analyzerFactory = AbstractAnalyzer.fromOptions(indexTermType, indexMetadata.options);
memtableIndexManager = new MemtableIndexManager(this);
indexMetrics = new IndexMetrics(this, memtableIndexManager);
maxTermSizeGuardrail = indexTermType.isVector()
? Guardrails.saiVectorTermSize
: (indexTermType.isFrozen() ? Guardrails.saiFrozenTermSize
: Guardrails.saiStringTermSize);
if (indexTermType.isVector())
maxTermSizeGuardrail = Guardrails.saiVectorTermSize;
else if (indexTermType.isFrozen())
maxTermSizeGuardrail = Guardrails.saiFrozenTermSize;
else if (indexTermType.isBytes())
maxTermSizeGuardrail = Guardrails.saiBlobTermSize;
else
maxTermSizeGuardrail = Guardrails.saiStringTermSize;
}
/**

View File

@ -49,6 +49,7 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.AsciiType;
import org.apache.cassandra.db.marshal.BooleanType;
import org.apache.cassandra.db.marshal.ByteBufferAccessor;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.db.marshal.DecimalType;
@ -80,7 +81,8 @@ public class IndexTermType
private static final Set<AbstractType<?>> EQ_ONLY_TYPES = ImmutableSet.of(UTF8Type.instance,
AsciiType.instance,
BooleanType.instance,
UUIDType.instance);
UUIDType.instance,
BytesType.instance);
private static final byte[] IPV4_PREFIX = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1 };
@ -104,6 +106,7 @@ public class IndexTermType
BIG_DECIMAL,
LONG,
BOOLEAN,
BYTES,
LITERAL,
REVERSED,
FROZEN,
@ -174,7 +177,7 @@ public class IndexTermType
/**
* Returns {@code true} if the index type is a literal type and will use a literal index. This applies to
* string types, frozen types, composite types and boolean type.
* string types, frozen types, composite types, bytes type and boolean type.
*/
public boolean isLiteral()
{
@ -208,6 +211,14 @@ public class IndexTermType
return capabilities.contains(Capability.REVERSED);
}
/**
* Returns {@code true} if the index type is a bytes/blob type.
*/
public boolean isBytes()
{
return capabilities.contains(Capability.BYTES);
}
/**
* Returns {@code true} if the index type is frozen, e.g. the type is wrapped with {@code frozen<type>}.
*/
@ -778,8 +789,12 @@ public class IndexTermType
if (indexType instanceof BooleanType)
capabilities.add(Capability.BOOLEAN);
if (indexType instanceof BytesType)
capabilities.add(Capability.BYTES);
if (capabilities.contains(Capability.STRING) ||
capabilities.contains(Capability.BOOLEAN) ||
capabilities.contains(Capability.BYTES) ||
capabilities.contains(Capability.FROZEN) ||
capabilities.contains(Capability.COMPOSITE))
capabilities.add(Capability.LITERAL);

View File

@ -0,0 +1,119 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.db.guardrails;
import java.nio.ByteBuffer;
import org.junit.Test;
import org.apache.cassandra.config.DataStorageSpec;
import org.apache.cassandra.transport.messages.ResultMessage;
import static java.nio.ByteBuffer.allocate;
import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.BYTES;
import static org.junit.Assert.assertEquals;
/**
* Tests the guardrails around the size of SAI blob terms
*
* @see Guardrails#saiBlobTermSize
*/
public class GuardrailSaiBlobTermSizeTest extends ValueThresholdTester
{
private static final int WARN_THRESHOLD = 1024; // bytes
private static final int FAIL_THRESHOLD = WARN_THRESHOLD * 4; // bytes
public GuardrailSaiBlobTermSizeTest()
{
super(WARN_THRESHOLD + "B",
FAIL_THRESHOLD + "B",
Guardrails.saiBlobTermSize,
Guardrails::setSaiBlobTermSizeThreshold,
Guardrails::getSaiBlobTermSizeWarnThreshold,
Guardrails::getSaiBlobTermSizeFailThreshold,
bytes -> new DataStorageSpec.LongBytesBound(bytes, BYTES).toString(),
size -> new DataStorageSpec.LongBytesBound(size).toBytes());
}
@Override
protected int warnThreshold()
{
return WARN_THRESHOLD;
}
@Override
protected int failThreshold()
{
return FAIL_THRESHOLD;
}
@Test
public void testRegularColumn() throws Throwable
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, v blob)");
createIndex("CREATE INDEX ON %s (v) USING 'sai'");
testThreshold("v", "INSERT INTO %s (k, v) VALUES (0, ?)");
testThreshold("v", "UPDATE %s SET v = ? WHERE k = 0");
}
@Test
public void testStaticColumn() throws Throwable
{
createTable("CREATE TABLE %s (k int, c int, s blob STATIC, r int, PRIMARY KEY(k, c))");
createIndex("CREATE INDEX ON %s (s) USING 'sai'");
testThreshold("s", "INSERT INTO %s (k, s) VALUES (0, ?)");
testThreshold("s", "INSERT INTO %s (k, c, s, r) VALUES (0, 0, ?, 0)");
testThreshold("s", "UPDATE %s SET s = ? WHERE k = 0");
testThreshold("s", "UPDATE %s SET s = ?, r = 0 WHERE k = 0 AND c = 0");
}
@Test
public void testWarningTermOnBuild()
{
ByteBuffer largeTerm = allocate(warnThreshold() + 1);
ByteBuffer smallTerm = allocate(1);
createTable(KEYSPACE, "CREATE TABLE %s (k int PRIMARY KEY, v blob)");
execute("INSERT INTO %s (k, v) VALUES (0, ?)", largeTerm);
execute("INSERT INTO %s (k, v) VALUES (1, ?)", smallTerm);
createIndex("CREATE INDEX ON %s(v) USING 'sai'");
// verify that the large term is written on initial index build
assertEquals(((ResultMessage.Rows) execute("SELECT * FROM %s WHERE v = ?", largeTerm)).result.size(), 1);
assertEquals(((ResultMessage.Rows) execute("SELECT * FROM %s WHERE v = ?", smallTerm)).result.size(), 1);
}
@Test
public void testFailingTermOnBuild()
{
ByteBuffer oversizedTerm = allocate(failThreshold() + 1);
ByteBuffer smallTerm = allocate(1);
createTable(KEYSPACE, "CREATE TABLE %s (k int PRIMARY KEY, v blob)");
execute("INSERT INTO %s (k, v) VALUES (0, ?)", oversizedTerm);
execute("INSERT INTO %s (k, v) VALUES (1, ?)", smallTerm);
createIndex("CREATE INDEX ON %s(v) USING 'sai'");
// verify that the oversized term isn't written on initial index build
assertEquals(((ResultMessage.Rows) execute("SELECT * FROM %s WHERE v = ?", oversizedTerm)).result.size(), 0);
assertEquals(((ResultMessage.Rows) execute("SELECT * FROM %s WHERE v = ?", smallTerm)).result.size(), 1);
}
}

View File

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types;
import java.util.Collection;
import org.junit.runners.Parameterized;
public class BlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new DataSet.BlobDataSet());
}
}

View File

@ -694,4 +694,37 @@ public abstract class DataSet<T> extends SAITester
return "inet";
}
}
public static class BlobDataSet extends DataSet<ByteBuffer>
{
public BlobDataSet()
{
values = new ByteBuffer[NUMBER_OF_VALUES];
List<ByteBuffer> list = Arrays.asList(values);
for (int index = 0; index < values.length; index++)
{
ByteBuffer value;
do
{
byte[] bytes = new byte[getRandom().nextIntBetween(1, 256)];
getRandom().nextBytes(bytes);
value = ByteBuffer.wrap(bytes);
}
while (list.contains(value));
values[index] = value;
}
}
@Override
public QuerySet querySet()
{
return new QuerySet.LiteralQuerySet();
}
public String toString()
{
return "blob";
}
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.lists;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class FrozenListBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.FrozenListDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.lists;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class ListBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.ListDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.maps;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class FrozenMapBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.FrozenMapValuesDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.maps;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class MapBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.MapDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.maps;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class MapEntriesBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.MapEntriesDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.maps;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class MapKeysBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.MapKeysDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.maps;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class MapValuesBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.MapValuesDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.maps;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class MultiMapBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.MultiMapDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.sets;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class FrozenSetBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.FrozenSetDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.index.sai.cql.types.collections.sets;
import java.util.Collection;
import org.junit.runners.Parameterized;
import org.apache.cassandra.index.sai.cql.types.DataSet;
import org.apache.cassandra.index.sai.cql.types.IndexingTypeSupport;
import org.apache.cassandra.index.sai.cql.types.collections.CollectionDataSet;
public class SetBlobTest extends IndexingTypeSupport
{
@Parameterized.Parameters(name = "dataset={0},wide={1},scenario={2}")
public static Collection<Object[]> generateParameters()
{
return generateParameters(new CollectionDataSet.SetDataSet<>(new DataSet.BlobDataSet()));
}
}

View File

@ -67,7 +67,8 @@ public class IndexTermTypeTest
boolean isUTF8OrAscii = cql3Type == CQL3Type.Native.ASCII || cql3Type == CQL3Type.Native.TEXT ||
cql3Type == CQL3Type.Native.VARCHAR;
boolean isLiteral = cql3Type == CQL3Type.Native.ASCII || cql3Type == CQL3Type.Native.TEXT ||
cql3Type == CQL3Type.Native.VARCHAR || cql3Type == CQL3Type.Native.BOOLEAN;
cql3Type == CQL3Type.Native.VARCHAR || cql3Type == CQL3Type.Native.BOOLEAN ||
cql3Type == CQL3Type.Native.BLOB;
assertEquals(isLiteral, indexTermType.isLiteral());
assertEquals(indexTermType.isLiteral(), reversedIndexTermType.isLiteral());
assertEquals(isUTF8OrAscii, indexTermType.isString());

View File

@ -244,6 +244,7 @@ public class GuardrailsConfigCommandsTest extends CQLTester
"partition_keys_in_select_threshold [-1, -1] \n" +
"partition_size_threshold [null, null] \n" +
"partition_tombstones_threshold [-1, -1] \n" +
"sai_blob_term_size_threshold [8KiB, 1KiB] \n" +
"sai_frozen_term_size_threshold [8KiB, 1KiB] \n" +
"sai_sstable_indexes_per_query_threshold [-1, 32] \n" +
"sai_string_term_size_threshold [8KiB, 1KiB] \n" +
@ -299,6 +300,8 @@ public class GuardrailsConfigCommandsTest extends CQLTester
"partition_size_warn_threshold null \n" +
"partition_tombstones_fail_threshold -1 \n" +
"partition_tombstones_warn_threshold -1 \n" +
"sai_blob_term_size_fail_threshold 8KiB \n" +
"sai_blob_term_size_warn_threshold 1KiB \n" +
"sai_frozen_term_size_fail_threshold 8KiB \n" +
"sai_frozen_term_size_warn_threshold 1KiB \n" +
"sai_sstable_indexes_per_query_fail_threshold -1 \n" +