This is an automated email from the ASF dual-hosted git repository.
maedhroz pushed a commit to branch cep-7-sai
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cep-7-sai by this push:
new 4b43c75b00 Add support for index implementation selection via USING
for CREATE INDEX
4b43c75b00 is described below
commit 4b43c75b00703c5863228331326ecc95d3fe1605
Author: Caleb Rackliffe <[email protected]>
AuthorDate: Wed Jun 21 17:29:05 2023 -0500
Add support for index implementation selection via USING for CREATE INDEX
patch by Caleb Rackliffe; reviewed by Maxwell Guo and Andres de la Peña for
CASSANDRA-18615
---
conf/cassandra.yaml | 9 ++
doc/cql3/CQL.textile | 12 +-
.../examples/BNF/create_index_statement.bnf | 3 +-
.../cassandra/examples/CQL/create_index.cql | 3 +-
.../pages/developing/cql/cql_singlefile.adoc | 27 +++--
.../cassandra/pages/developing/cql/indexes.adoc | 29 +++--
src/java/org/apache/cassandra/config/Config.java | 7 +-
.../cassandra/config/DatabaseDescriptor.java | 20 ++++
.../statements/schema/CreateIndexStatement.java | 23 ++++
.../cassandra/index/internal/CassandraIndex.java | 2 +
src/java/org/apache/cassandra/index/sai/README.md | 4 +-
.../cassandra/index/sai/StorageAttachedIndex.java | 2 +
.../org/apache/cassandra/schema/IndexMetadata.java | 5 +-
.../validation/entities/SecondaryIndexTest.java | 46 ++++++++
.../org/apache/cassandra/index/sai/SAITester.java | 2 +-
.../index/sai/cql/CollectionIndexingTest.java | 53 +++++----
.../sai/cql/CompositePartitionKeyIndexTest.java | 12 +-
.../index/sai/cql/MultipleColumnIndexTest.java | 20 ++--
.../index/sai/cql/StorageAttachedIndexDDLTest.java | 124 ++++++++++++++-------
.../index/sai/cql/types/IndexingTypeSupport.java | 6 +-
.../index/sai/functional/GroupComponentsTest.java | 6 +-
.../index/sai/virtual/SSTablesSystemViewTest.java | 4 +-
22 files changed, 305 insertions(+), 114 deletions(-)
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index 2c4844beca..e016babba8 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -1956,6 +1956,15 @@ drop_compact_storage_enabled: false
# if zero_ttl_on_twcs_enabled is set to false, this property is irrelevant as
such statements will fail.
#zero_ttl_on_twcs_warned: true
+# 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
+#default_secondary_index: legacy_local_table
+
+# Whether a default secondary index implementation is allowed. If this is
"false", CREATE INDEX must
+# specify an index implementation via USING.
+#default_secondary_index_enabled: true
+
# Startup Checks are executed as part of Cassandra startup process, not all of
them
# are configurable (so you can disable them) but these which are enumerated
bellow.
# Uncomment the startup checks and configure them appropriately to cover your
needs.
diff --git a/doc/cql3/CQL.textile b/doc/cql3/CQL.textile
index 0073ff7ed3..4f6a4d7338 100644
--- a/doc/cql3/CQL.textile
+++ b/doc/cql3/CQL.textile
@@ -513,7 +513,8 @@ __Sample:__
bc(sample).
CREATE INDEX userIndex ON NerdMovies (user);
CREATE INDEX ON Mutants (abilityId);
-CREATE INDEX ON users (keys(favs));
+CREATE INDEX ON users (KEYS(favs));
+CREATE INDEX ON users (age) USING 'sai';
CREATE CUSTOM INDEX ON users (email) USING 'path.to.the.IndexClass';
CREATE CUSTOM INDEX ON users (email) USING 'path.to.the.IndexClass' WITH
OPTIONS = {'storage': '/mnt/ssd/indexes/'};
@@ -521,6 +522,15 @@ The @CREATE INDEX@ statement is used to create a new
(automatic) secondary index
Attempting to create an already existing index will return an error unless the
@IF NOT EXISTS@ option is used. If it is used, the statement will be a no-op if
the index already exists.
+h4(#usingIndex). Index Types
+
+The @USING@ keyword optionally specifies an index type. There are two built-in
types:
+
+* legacy_local_table - (default) legacy secondary index, implemented as a
hidden local table
+* sai - "storage-attched" index, implemented via optimized
SSTable/Memtable-attached indexes
+
+To create a custom index, a fully qualified class name must be specified.
+
h4(#keysIndex). Indexes on Map Keys
When creating an index on a "map column":#map, you may index either the keys
or the values. If the column identifier is placed within the @keys()@
function, the index will be on the map keys, allowing you to use @CONTAINS KEY@
in @WHERE@ clauses. Otherwise, the index will be on the map values.
diff --git a/doc/modules/cassandra/examples/BNF/create_index_statement.bnf
b/doc/modules/cassandra/examples/BNF/create_index_statement.bnf
index 6e76947243..322799de1c 100644
--- a/doc/modules/cassandra/examples/BNF/create_index_statement.bnf
+++ b/doc/modules/cassandra/examples/BNF/create_index_statement.bnf
@@ -1,5 +1,6 @@
create_index_statement::= CREATE [ CUSTOM ] INDEX [ IF NOT EXISTS ] [
index_name ]
ON table_name '(' index_identifier ')'
- [ USING string [ WITH OPTIONS = map_literal ] ]
+ [ USING index_type [ WITH OPTIONS = map_literal ] ]
index_identifier::= column_name
| ( KEYS | VALUES | ENTRIES | FULL ) '(' column_name ')'
+index_type::= 'sai' | 'legacy_local_table' | fully_qualified_class_name
\ No newline at end of file
diff --git a/doc/modules/cassandra/examples/CQL/create_index.cql
b/doc/modules/cassandra/examples/CQL/create_index.cql
index f84452aa1d..38bdfdff02 100644
--- a/doc/modules/cassandra/examples/CQL/create_index.cql
+++ b/doc/modules/cassandra/examples/CQL/create_index.cql
@@ -1,6 +1,7 @@
CREATE INDEX userIndex ON NerdMovies (user);
CREATE INDEX ON Mutants (abilityId);
-CREATE INDEX ON users (keys(favs));
+CREATE INDEX ON users (KEYS(favs));
+CREATE INDEX ON users (age) USING 'sai';
CREATE CUSTOM INDEX ON users (email)
USING 'path.to.the.IndexClass';
CREATE CUSTOM INDEX ON users (email)
diff --git a/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
b/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
index b6a0966cbf..64e71b051c 100644
--- a/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
+++ b/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
@@ -853,6 +853,11 @@ The `TRUNCATE` statement permanently removes all data from
a table.
[[createIndexStmt]]
==== CREATE INDEX
+The `CREATE INDEX` statement is used to create a new
+secondary index for a given (existing) column in a given table. A name
+for the index itself can be specified before the `ON` keyword, if
+desired.
+
_Syntax:_
bc(syntax).. +
@@ -869,20 +874,26 @@ bc(sample). +
CREATE INDEX userIndex ON NerdMovies (user); +
CREATE INDEX ON Mutants (abilityId); +
CREATE INDEX ON users (keys(favs)); +
+CREATE INDEX ON users (age) USING 'sai'; +
CREATE CUSTOM INDEX ON users (email) USING `path.to.the.IndexClass'; +
CREATE CUSTOM INDEX ON users (email) USING `path.to.the.IndexClass' WITH
OPTIONS = \{’storage’: `/mnt/ssd/indexes/'};
-The `CREATE INDEX` statement is used to create a new (automatic)
-secondary index for a given (existing) column in a given table. A name
-for the index itself can be specified before the `ON` keyword, if
-desired. If data already exists for the column, it will be indexed
+If data already exists for the column, it will be indexed
asynchronously. After the index is created, new data for the column is
-indexed automatically at insertion time.
+indexed automatically at insertion time. Attempting to create an already
+existing index will return an error unless the `IF NOT EXISTS` option is used.
+If it is used, the statement will be a no-op if the index already exists.
-Attempting to create an already existing index will return an error
-unless the `IF NOT EXISTS` option is used. If it is used, the statement
-will be a no-op if the index already exists.
+[[indexTypes]]
+===== Index Types
+
+The `USING` keyword optionally specifies an index type. There are two built-in
types:
+
+- legacy_local_table - (default) legacy secondary index, implemented as a
hidden local table
+- sai - "storage-attched" index, implemented via optimized
SSTable/Memtable-attached indexes
+
+To create a custom index, a fully qualified class name must be specified.
[[keysIndex]]
===== Indexes on Map Keys
diff --git a/doc/modules/cassandra/pages/developing/cql/indexes.adoc
b/doc/modules/cassandra/pages/developing/cql/indexes.adoc
index 32b45b59f5..20daf072f8 100644
--- a/doc/modules/cassandra/pages/developing/cql/indexes.adoc
+++ b/doc/modules/cassandra/pages/developing/cql/indexes.adoc
@@ -12,30 +12,37 @@ include::example$BNF/index_name.bnf[]
[[create-index-statement]]
== CREATE INDEX
-Creating a secondary index on a table uses the `CREATE INDEX` statement:
+The `CREATE INDEX` statement is used to create a new
+secondary index for a given (existing) column in a given table. A name
+for the index itself can be specified before the `ON` keyword, if
+desired.
[source,bnf]
----
include::example$BNF/create_index_statement.bnf[]
----
-For instance:
+If data already exists for the column, it will be indexed
+asynchronously. After the index is created, new data for the column is
+indexed automatically at insertion time. Attempting to create an already
+existing index will return an error unless the `IF NOT EXISTS` option is used.
+If it is used, the statement will be a no-op if the index already exists.
+
+*Examples*:
[source,cql]
----
include::example$CQL/create_index.cql[]
----
-The `CREATE INDEX` statement is used to create a new (automatic)
-secondary index for a given (existing) column in a given table. A name
-for the index itself can be specified before the `ON` keyword, if
-desired. If data already exists for the column, it will be indexed
-asynchronously. After the index is created, new data for the column is
-indexed automatically at insertion time.
+=== Index Types
+
+The `USING` keyword optionally specifies an index type. There are two built-in
types:
+
+- legacy_local_table - (default) legacy secondary index, implemented as a
hidden local table
+- sai - "storage-attched" index, implemented via optimized
SSTable/Memtable-attached indexes
-Attempting to create an already existing index will return an error
-unless the `IF NOT EXISTS` option is used. If it is used, the statement
-will be a no-op if the index already exists.
+To create a custom index, a fully qualified class name must be specified.
=== Indexes on Map Keys
diff --git a/src/java/org/apache/cassandra/config/Config.java
b/src/java/org/apache/cassandra/config/Config.java
index cb666e01b5..9bd07e3d32 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.audit.AuditLogOptions;
import org.apache.cassandra.db.ConsistencyLevel;
import org.apache.cassandra.fql.FullQueryLoggerOptions;
+import org.apache.cassandra.index.internal.CassandraIndex;
import org.apache.cassandra.io.sstable.format.big.BigFormat;
import org.apache.cassandra.service.StartupChecks.StartupCheckType;
import org.apache.cassandra.utils.StorageCompatibilityMode;
@@ -49,7 +50,7 @@ import static
org.apache.cassandra.config.CassandraRelevantProperties.SKIP_PAXOS
/**
* A class that contains configuration properties for the cassandra node it
runs within.
- *
+ * <p>
* Properties declared as volatile can be mutated via JMX.
*/
public class Config
@@ -864,6 +865,10 @@ public class Config
public volatile boolean drop_truncate_table_enabled = true;
public volatile boolean drop_keyspace_enabled = true;
public volatile boolean secondary_indexes_enabled = true;
+
+ public volatile String default_secondary_index = CassandraIndex.NAME;
+ public volatile boolean default_secondary_index_enabled = true;
+
public volatile boolean uncompressed_tables_enabled = true;
public volatile boolean compact_tables_enabled = true;
public volatile boolean read_before_write_list_operations_enabled = true;
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 972776992d..d2450f82b9 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -3765,6 +3765,26 @@ public class DatabaseDescriptor
conf.sasi_indexes_enabled = enableSASIIndexes;
}
+ public static String getDefaultSecondaryIndex()
+ {
+ return conf.default_secondary_index;
+ }
+
+ public static void setDefaultSecondaryIndex(String name)
+ {
+ conf.default_secondary_index = name;
+ }
+
+ public static boolean getDefaultSecondaryIndexEnabled()
+ {
+ return conf.default_secondary_index_enabled;
+ }
+
+ public static void setDefaultSecondaryIndexEnabled(boolean enabled)
+ {
+ conf.default_secondary_index_enabled = enabled;
+ }
+
public static boolean isTransientReplicationEnabled()
{
return conf.transient_replication_enabled;
diff --git
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
index 73b66b738d..b53e066f90 100644
---
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
+++
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
@@ -35,6 +35,7 @@ import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.guardrails.Guardrails;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.index.internal.CassandraIndex;
import org.apache.cassandra.index.sasi.SASIIndex;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
@@ -77,6 +78,7 @@ public final class CreateIndexStatement extends
AlterSchemaStatement
public static final String INDEX_DUPLICATE_OF_EXISTING = "Index %s is a
duplicate of existing index %s";
public static final String KEYSPACE_DOES_NOT_MATCH_TABLE = "Keyspace name
'%s' doesn't match table name '%s'";
public static final String KEYSPACE_DOES_NOT_MATCH_INDEX = "Keyspace name
'%s' doesn't match index name '%s'";
+ public static final String MUST_SPECIFY_INDEX_IMPLEMENTATION = "Must
specify index implementation via USING";
private final String indexName;
private final String tableName;
@@ -316,6 +318,27 @@ public final class CreateIndexStatement extends
AlterSchemaStatement
if (indexName.hasKeyspace() &&
!keyspaceName.equals(indexName.getKeyspace()))
throw ire(KEYSPACE_DOES_NOT_MATCH_INDEX, keyspaceName,
tableName);
+
+ // Set the configured default 2i implementation if one isn't
specified with USING:
+ if (attrs.customClass == null)
+ {
+ if (DatabaseDescriptor.getDefaultSecondaryIndexEnabled())
+ attrs.customClass =
DatabaseDescriptor.getDefaultSecondaryIndex();
+ else
+ // However, operators may require an implementation be
specified
+ throw ire(MUST_SPECIFY_INDEX_IMPLEMENTATION);
+ }
+
+ // If we explicitly specify the index type "legacy_local_table",
we can just clear the custom class, and the
+ // non-custom 2i creation process will begin. Otherwise, if an
index type has been specified with
+ // USING, make sure the appropriate custom index is created.
+ if (attrs.customClass != null)
+ {
+ if (!attrs.isCustom &&
attrs.customClass.equalsIgnoreCase(CassandraIndex.NAME))
+ attrs.customClass = null;
+ else
+ attrs.isCustom = true;
+ }
return new CreateIndexStatement(keyspaceName, tableName.getName(),
indexName.getName(), rawIndexTargets, attrs, ifNotExists);
}
diff --git a/src/java/org/apache/cassandra/index/internal/CassandraIndex.java
b/src/java/org/apache/cassandra/index/internal/CassandraIndex.java
index 39423097a0..d2053bdf7d 100644
--- a/src/java/org/apache/cassandra/index/internal/CassandraIndex.java
+++ b/src/java/org/apache/cassandra/index/internal/CassandraIndex.java
@@ -69,6 +69,8 @@ import static
org.apache.cassandra.cql3.statements.RequestValidations.checkFalse
*/
public abstract class CassandraIndex implements Index
{
+ public static final String NAME = "legacy_local_table";
+
private static final Logger logger =
LoggerFactory.getLogger(CassandraIndex.class);
public final ColumnFamilyStore baseCfs;
diff --git a/src/java/org/apache/cassandra/index/sai/README.md
b/src/java/org/apache/cassandra/index/sai/README.md
index 6be0fa981a..1b434dba3c 100644
--- a/src/java/org/apache/cassandra/index/sai/README.md
+++ b/src/java/org/apache/cassandra/index/sai/README.md
@@ -61,9 +61,9 @@ Follow the instructions to build and start Cassandra in
README.asc in root folde
`CREATE TABLE person (id int, name text, age int, PRIMARY KEY (id));`
-`CREATE CUSTOM INDEX ON person (name) USING 'StorageAttachedIndex' WITH
OPTIONS = {'case_sensitive': false};`
+`CREATE INDEX ON person (name) USING 'sai' WITH OPTIONS = {'case_sensitive':
false};`
-`CREATE CUSTOM INDEX ON person (age) USING 'StorageAttachedIndex';`
+`CREATE INDEX ON person (age) USING 'sai';`
2.) Add some data.
diff --git a/src/java/org/apache/cassandra/index/sai/StorageAttachedIndex.java
b/src/java/org/apache/cassandra/index/sai/StorageAttachedIndex.java
index 264abdd71a..5a8f7b6a58 100644
--- a/src/java/org/apache/cassandra/index/sai/StorageAttachedIndex.java
+++ b/src/java/org/apache/cassandra/index/sai/StorageAttachedIndex.java
@@ -95,6 +95,8 @@ import org.apache.cassandra.utils.concurrent.OpOrder;
public class StorageAttachedIndex implements Index
{
+ public static final String NAME = "sai";
+
private static final Logger logger =
LoggerFactory.getLogger(StorageAttachedIndex.class);
private static class StorageAttachedIndexBuildingSupport implements
IndexBuildingSupport
diff --git a/src/java/org/apache/cassandra/schema/IndexMetadata.java
b/src/java/org/apache/cassandra/schema/IndexMetadata.java
index 577c12b4ba..795abad984 100644
--- a/src/java/org/apache/cassandra/schema/IndexMetadata.java
+++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java
@@ -67,7 +67,8 @@ public final class IndexMetadata
static
{
- indexNameAliases.put(StorageAttachedIndex.class.getSimpleName(),
StorageAttachedIndex.class.getCanonicalName());
+ indexNameAliases.put(StorageAttachedIndex.NAME,
StorageAttachedIndex.class.getCanonicalName());
+
indexNameAliases.put(StorageAttachedIndex.class.getSimpleName().toLowerCase(),
StorageAttachedIndex.class.getCanonicalName());
indexNameAliases.put(SASIIndex.class.getSimpleName(),
SASIIndex.class.getCanonicalName());
}
@@ -154,7 +155,7 @@ public final class IndexMetadata
if (isCustom())
{
String className =
options.get(IndexTarget.CUSTOM_INDEX_OPTION_NAME);
- return indexNameAliases.getOrDefault(className, className);
+ return indexNameAliases.getOrDefault(className.toLowerCase(),
className);
}
return CassandraIndex.class.getName();
}
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
index d87855a8bd..38f724968e 100644
---
a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
+++
b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
@@ -25,9 +25,12 @@ import java.util.concurrent.CountDownLatch;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.StringUtils;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.index.internal.CassandraIndex;
+import org.apache.cassandra.index.sai.StorageAttachedIndex;
import org.apache.cassandra.schema.ColumnMetadata;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.config.DatabaseDescriptor;
@@ -70,6 +73,12 @@ import static org.junit.Assert.fail;
public class SecondaryIndexTest extends CQLTester
{
public static final int TOO_BIG = 1024 * 65;
+
+ @BeforeClass
+ public static void setDefaultSecondaryIndex()
+ {
+ DatabaseDescriptor.setDefaultSecondaryIndex(CassandraIndex.NAME);
+ }
@Test
public void testCreateAndDropIndex() throws Throwable
@@ -161,6 +170,43 @@ public class SecondaryIndexTest extends CQLTester
return StringUtils.remove(indexName, '\"');
}
+ @Test
+ public void shouldCreateCassandraIndexExplicitly() throws Throwable
+ {
+ createTable("CREATE TABLE %s (userid uuid PRIMARY KEY, firstname text,
lastname text, age int)");
+ createIndex("CREATE INDEX byAge ON %s(age) USING
'legacy_local_table'");
+
+ SecondaryIndexManager indexManager =
getCurrentColumnFamilyStore().indexManager;
+ assertTrue(indexManager.getIndexByName("byage") instanceof
CassandraIndex);
+
+ UUID id1 = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");
+ execute("INSERT INTO %s (userid, firstname, lastname, age) VALUES (?,
'Frodo', 'Baggins', 32)", id1);
+ assertEmpty(execute("SELECT firstname FROM %s WHERE userid = ? AND age
= 33", id1));
+ }
+
+ @Test
+ public void shouldCreateCassandraIndexWhenNotDefault() throws Throwable
+ {
+ DatabaseDescriptor.setDefaultSecondaryIndex(StorageAttachedIndex.NAME);
+
+ try
+ {
+ createTable("CREATE TABLE %s (userid uuid PRIMARY KEY, firstname
text, lastname text, age int)");
+ createIndex("CREATE INDEX byAge ON %s(age) USING
'legacy_local_table'");
+
+ SecondaryIndexManager indexManager =
getCurrentColumnFamilyStore().indexManager;
+ assertTrue(indexManager.getIndexByName("byage") instanceof
CassandraIndex);
+
+ UUID id1 = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");
+ execute("INSERT INTO %s (userid, firstname, lastname, age) VALUES
(?, 'Frodo', 'Baggins', 32)", id1);
+ assertEmpty(execute("SELECT firstname FROM %s WHERE userid = ? AND
age = 33", id1));
+ }
+ finally
+ {
+ DatabaseDescriptor.setDefaultSecondaryIndex(CassandraIndex.NAME);
+ }
+ }
+
/**
* Check that you can query for an indexed column even with a key EQ
clause,
* migrated from cql_tests.py:TestCQL.static_cf_test()
diff --git a/test/unit/org/apache/cassandra/index/sai/SAITester.java
b/test/unit/org/apache/cassandra/index/sai/SAITester.java
index d1616f49f9..4f147dc4b8 100644
--- a/test/unit/org/apache/cassandra/index/sai/SAITester.java
+++ b/test/unit/org/apache/cassandra/index/sai/SAITester.java
@@ -115,7 +115,7 @@ public abstract class SAITester extends CQLTester
protected static final String CREATE_TABLE_TEMPLATE = "CREATE TABLE %s
(id1 TEXT PRIMARY KEY, v1 INT, v2 TEXT) WITH compaction = " +
"{'class' :
'SizeTieredCompactionStrategy', 'enabled' : false }";
- protected static final String CREATE_INDEX_TEMPLATE = "CREATE CUSTOM INDEX
IF NOT EXISTS ON %%s(%s) USING 'StorageAttachedIndex'";
+ protected static final String CREATE_INDEX_TEMPLATE = "CREATE INDEX IF NOT
EXISTS ON %%s(%s) USING 'sai'";
protected static final ColumnIdentifier V1_COLUMN_IDENTIFIER =
ColumnIdentifier.getInterned("v1", true);
protected static final ColumnIdentifier V2_COLUMN_IDENTIFIER =
ColumnIdentifier.getInterned("v2", true);
diff --git
a/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java
b/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java
index 8bc9efb1ca..a82f539842 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/CollectionIndexingTest.java
@@ -28,9 +28,11 @@ import org.apache.cassandra.index.sai.SAITester;
import static org.junit.Assert.assertEquals;
-// This test is primarily handling edge conditions, error conditions
-// and basic functionality. Comprehensive type testing of collections
-// is in the cql/types/collections package
+/**
+ * This test is primarily handling edge conditions, error conditions
+ * and basic functionality. Comprehensive type testing of collections
+ * is in the cql/types/collections package
+ */
public class CollectionIndexingTest extends SAITester
{
@Before
@@ -42,28 +44,28 @@ public class CollectionIndexingTest extends SAITester
@Test
public void indexMap() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(value) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("value"));
assertEquals(2, execute("SELECT * FROM %s WHERE value CONTAINS
'v1'").size());
}
@Test
public void indexMapKeys() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(KEYS(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("KEYS(value)"));
assertEquals(2, execute("SELECT * FROM %s WHERE value CONTAINS KEY
1").size());
}
@Test
public void indexMapValues() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(VALUES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("VALUES(value)"));
assertEquals(2, execute("SELECT * FROM %s WHERE value CONTAINS
'v1'").size());
}
@Test
public void indexMapEntries() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(ENTRIES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("ENTRIES(value)"));
assertEquals(2, execute("SELECT * FROM %s WHERE value[1] =
'v1'").size());
assertEquals(1, execute("SELECT * FROM %s WHERE value[1] = 'v1' AND
value[2] = 'v2'").size());
}
@@ -71,14 +73,14 @@ public class CollectionIndexingTest extends SAITester
@Test
public void indexFrozenList() throws Throwable
{
- createPopulatedFrozenList("CREATE CUSTOM INDEX ON %s(FULL(value))
USING 'StorageAttachedIndex'");
+ createPopulatedFrozenList(createIndexDDL("FULL(value)"));
assertEquals(2, execute("SELECT * FROM %s WHERE value = ?",
Arrays.asList(1, 2, 3)).size());
}
@Test
public void indexFrozenMap() throws Throwable
{
- createPopulatedFrozenMap("CREATE CUSTOM INDEX ON %s(FULL(value)) USING
'StorageAttachedIndex'");
+ createPopulatedFrozenMap(createIndexDDL("FULL(value)"));
assertEquals(1, execute("SELECT * FROM %s WHERE value = ?", new
HashMap<Integer, String>() {{
put(1, "v1");
put(2, "v2");
@@ -89,21 +91,21 @@ public class CollectionIndexingTest extends SAITester
@Test
public void indexFrozenMapQueryKeys() throws Throwable
{
- createPopulatedFrozenMap("CREATE CUSTOM INDEX ON %s(FULL(value)) USING
'StorageAttachedIndex'");
+ createPopulatedFrozenMap(createIndexDDL("FULL(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value
contains key 1");
}
@Test
public void indexFrozenMapQueryValues() throws Throwable
{
- createPopulatedFrozenMap("CREATE CUSTOM INDEX ON %s(FULL(value)) USING
'StorageAttachedIndex'");
+ createPopulatedFrozenMap(createIndexDDL("FULL(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value
contains 'v1'");
}
@Test
public void indexFrozenMapQueryEntries() throws Throwable
{
- createPopulatedFrozenMap("CREATE CUSTOM INDEX ON %s(FULL(value)) USING
'StorageAttachedIndex'");
+ createPopulatedFrozenMap(createIndexDDL("FULL(value)"));
assertInvalidMessage("Map-entry equality predicates on frozen map
column value are not supported",
"SELECT * FROM %s WHERE value[1] = 'v1'");
}
@@ -111,7 +113,7 @@ public class CollectionIndexingTest extends SAITester
@Test
public void indexMapEntriesQueryEq() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(ENTRIES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("ENTRIES(value)"));
assertInvalidMessage("Collection column 'value' (map<int, text>)
cannot be restricted by a '=' relation",
"SELECT * FROM %s WHERE value = ?", Arrays.asList(1, 2));
}
@@ -119,21 +121,21 @@ public class CollectionIndexingTest extends SAITester
@Test
public void indexMapEntriesQueryKeys() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(ENTRIES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("ENTRIES(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value
contains key 1");
}
@Test
public void indexMapEntriesQueryValues() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(ENTRIES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("ENTRIES(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value
contains 'v1'");
}
@Test
public void indexMapKeysQueryEq() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(KEYS(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("KEYS(value)"));
assertInvalidMessage("Collection column 'value' (map<int, text>)
cannot be restricted by a '=' relation",
"SELECT * FROM %s WHERE value = ?", Arrays.asList(1, 2));
}
@@ -141,21 +143,21 @@ public class CollectionIndexingTest extends SAITester
@Test
public void indexMapKeysQueryValues() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(KEYS(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("KEYS(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value
contains 'v1'");
}
@Test
public void indexMapKeysQueryEntries() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(KEYS(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("KEYS(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value[1] =
'v1'");
}
@Test
public void indexMapValuesQueryEq() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(VALUES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("VALUES(value)"));
assertInvalidMessage("Collection column 'value' (map<int, text>)
cannot be restricted by a '=' relation",
"SELECT * FROM %s WHERE value = ?", Arrays.asList(1, 2));
}
@@ -163,18 +165,18 @@ public class CollectionIndexingTest extends SAITester
@Test
public void indexMapValuesQueryKeys() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(VALUES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("VALUES(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value
contains key 1");
}
@Test
public void indexMapValuesQueryEntries() throws Throwable
{
- createPopulatedMap("CREATE CUSTOM INDEX ON %s(VALUES(value)) USING
'StorageAttachedIndex'");
+ createPopulatedMap(createIndexDDL("VALUES(value)"));
assertUnsupportedIndexOperator(2, "SELECT * FROM %s WHERE value[1] =
'v1'");
}
- private void createPopulatedMap(String createIndex) throws Throwable
+ private void createPopulatedMap(String createIndex)
{
createTable("CREATE TABLE %s (pk int primary key, value map<int,
text>)");
createIndex(createIndex);
@@ -204,7 +206,7 @@ public class CollectionIndexingTest extends SAITester
}
@SuppressWarnings("SameParameterValue")
- private void createPopulatedFrozenList(String createIndex) throws Throwable
+ private void createPopulatedFrozenList(String createIndex)
{
createTable("CREATE TABLE %s (pk int primary key, value
frozen<list<int>>)");
createIndex(createIndex);
@@ -220,4 +222,9 @@ public class CollectionIndexingTest extends SAITester
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
query, values);
assertEquals(expectedSize, execute(query + " ALLOW FILTERING").size());
}
+
+ private static String createIndexDDL(String target)
+ {
+ return "CREATE INDEX ON %s(" + target + ") USING 'sai'";
+ }
}
diff --git
a/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java
b/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java
index bfaabf5b9a..0e488b2507 100644
---
a/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java
+++
b/test/unit/org/apache/cassandra/index/sai/cql/CompositePartitionKeyIndexTest.java
@@ -30,20 +30,20 @@ public class CompositePartitionKeyIndexTest extends
SAITester
public void createTableAndIndex()
{
createTable("CREATE TABLE %s (pk1 int, pk2 text, val int, PRIMARY
KEY((pk1, pk2)))");
- createIndex("CREATE CUSTOM INDEX ON %s(pk1) USING
'StorageAttachedIndex'");
- createIndex("CREATE CUSTOM INDEX ON %s(pk2) USING
'StorageAttachedIndex'");
+ createIndex("CREATE INDEX ON %s(pk1) USING 'sai'");
+ createIndex("CREATE INDEX ON %s(pk2) USING 'sai'");
disableCompaction();
}
- private void insertData1() throws Throwable
+ private void insertData1()
{
execute("INSERT INTO %s (pk1, pk2, val) VALUES (1, '1', 1)");
execute("INSERT INTO %s (pk1, pk2, val) VALUES (2, '2', 2)");
execute("INSERT INTO %s (pk1, pk2, val) VALUES (3, '3', 3)");
}
- private void insertData2() throws Throwable
+ private void insertData2()
{
execute("INSERT INTO %s (pk1, pk2, val) VALUES (4, '4', 4)");
execute("INSERT INTO %s (pk1, pk2, val) VALUES (5, '5', 5)");
@@ -51,7 +51,7 @@ public class CompositePartitionKeyIndexTest extends SAITester
}
@Test
- public void queryFromMemtable() throws Throwable
+ public void queryFromMemtable()
{
insertData1();
insertData2();
@@ -62,7 +62,7 @@ public class CompositePartitionKeyIndexTest extends SAITester
return row(index, Integer.toString(index), index);
}
- private void runQueries() throws Throwable
+ private void runQueries()
{
assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk1 = 2"),
expectedRow(2));
diff --git
a/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java
b/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java
index 97f93e29aa..459d608dc5 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/MultipleColumnIndexTest.java
@@ -25,26 +25,26 @@ import static org.junit.Assert.assertEquals;
public class MultipleColumnIndexTest extends SAITester
{
- // Note: Full testing of multiple map index types is done in the
- // types/collections/maps/MultiMap*Test tests
- // This is just testing that the indexes can be created
@Test
public void canCreateMultipleMapIndexesOnSameColumn()
{
+ // Note: Full testing of multiple map index types is done in the
+ // types/collections/maps/MultiMap*Test tests
+ // This is just testing that the indexes can be created
createTable("CREATE TABLE %s (pk int, ck int, value map<int,int>,
PRIMARY KEY(pk, ck))");
- createIndex("CREATE CUSTOM INDEX ON %s(KEYS(value)) USING
'StorageAttachedIndex'");
- createIndex("CREATE CUSTOM INDEX ON %s(VALUES(value)) USING
'StorageAttachedIndex'");
- createIndex("CREATE CUSTOM INDEX ON %s(ENTRIES(value)) USING
'StorageAttachedIndex'");
+ createIndex("CREATE INDEX ON %s(KEYS(value)) USING 'sai'");
+ createIndex("CREATE INDEX ON %s(VALUES(value)) USING 'sai'");
+ createIndex("CREATE INDEX ON %s(ENTRIES(value)) USING 'sai'");
}
@Test
- public void indexNamedAsColumnWillCoExistWithGeneratedIndexNames() throws
Throwable
+ public void indexNamedAsColumnWillCoExistWithGeneratedIndexNames()
{
createTable("CREATE TABLE %s(id int PRIMARY KEY, text_map map<text,
text>)");
- createIndex("CREATE CUSTOM INDEX text_map ON %s(keys(text_map)) USING
'StorageAttachedIndex'");
- createIndex("CREATE CUSTOM INDEX ON %s(values(text_map)) USING
'StorageAttachedIndex'");
- createIndex("CREATE CUSTOM INDEX ON %s(entries(text_map)) USING
'StorageAttachedIndex'");
+ createIndex("CREATE INDEX text_map ON %s(keys(text_map)) USING 'sai'");
+ createIndex("CREATE INDEX ON %s(values(text_map)) USING 'sai'");
+ createIndex("CREATE INDEX ON %s(entries(text_map)) USING 'sai'");
execute("INSERT INTO %s(id, text_map) values (1, {'k1':'v1',
'k2':'v2'})");
execute("INSERT INTO %s(id, text_map) values (2, {'k1':'v1',
'k3':'v3'})");
diff --git
a/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java
b/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java
index 2b621fcfe7..43635c2e7a 100644
---
a/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java
+++
b/test/unit/org/apache/cassandra/index/sai/cql/StorageAttachedIndexDDLTest.java
@@ -37,6 +37,7 @@ import com.datastax.driver.core.ResultSet;
import
com.datastax.driver.core.exceptions.InvalidConfigurationInQueryException;
import com.datastax.driver.core.exceptions.InvalidQueryException;
import com.datastax.driver.core.exceptions.ReadFailureException;
+import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.cql3.restrictions.IndexRestrictions;
@@ -50,6 +51,7 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.db.marshal.ReversedType;
import org.apache.cassandra.db.marshal.UTF8Type;
+import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.index.Index;
import org.apache.cassandra.index.SecondaryIndexManager;
import org.apache.cassandra.index.sai.IndexContext;
@@ -145,7 +147,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
try
{
- executeNet(String.format("CREATE CUSTOM INDEX ON %%s(%s) USING
'StorageAttachedIndex'", cql3Type));
+ executeNet(String.format("CREATE INDEX ON %%s(%s) USING
'sai'", cql3Type));
assertTrue("Index creation on unsupported type " + cql3Type +
" should have failed.", supported);
}
catch (RuntimeException e)
@@ -161,7 +163,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
public void shouldFailCreationOnPartitionKey()
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(id)
USING 'StorageAttachedIndex'"))
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(id) USING
'sai'"))
.isInstanceOf(InvalidQueryException.class)
.hasMessageContaining(String.format(CreateIndexStatement.ONLY_PARTITION_KEY,
"id"));
}
@@ -171,8 +173,8 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(val)
USING " +
- "'StorageAttachedIndex' WITH
OPTIONS = { 'mode' : 'CONTAINS'
}")).isInstanceOf(InvalidConfigurationInQueryException.class);
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(val) USING
'sai' " +
+ "WITH OPTIONS = { 'mode' :
'CONTAINS' }")).isInstanceOf(InvalidConfigurationInQueryException.class);
}
@Test
@@ -180,8 +182,8 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(val) " +
- "USING 'StorageAttachedIndex' " +
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(val) " +
+ "USING 'sai' " +
"WITH OPTIONS = { 'analyzer_class'
: 'org.apache.cassandra.index.sai.analyzer.NonTokenizingAnalyzer' }"))
.isInstanceOf(InvalidConfigurationInQueryException.class);
}
@@ -191,8 +193,8 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(val) " +
- "USING 'StorageAttachedIndex' " +
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(val) " +
+ "USING 'sai' " +
"WITH OPTIONS = { 'case-sensitive'
: true }")).isInstanceOf(InvalidConfigurationInQueryException.class);
}
@@ -201,8 +203,8 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val int)");
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(val) " +
- "USING 'StorageAttachedIndex' " +
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(val) " +
+ "USING 'sai' " +
"WITH OPTIONS = { 'case_sensitive'
: true }")).isInstanceOf(InvalidQueryException.class);
}
@@ -211,8 +213,8 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val int)");
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(val) " +
- "USING 'StorageAttachedIndex' " +
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(val) " +
+ "USING 'sai' " +
"WITH OPTIONS = { 'normalize' :
true }")).isInstanceOf(InvalidQueryException.class);
}
@@ -222,8 +224,8 @@ public class StorageAttachedIndexDDLTest extends SAITester
String typeName = createType("CREATE TYPE %s (a text, b int, c
double)");
createTable("CREATE TABLE %s (id text PRIMARY KEY, val " + typeName +
')');
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(val) " +
- "USING
'StorageAttachedIndex'")).isInstanceOf(InvalidQueryException.class);
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(val) " +
+ "USING
'sai'")).isInstanceOf(InvalidQueryException.class);
}
@Test
@@ -231,7 +233,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val tuple<text,
int, double>)");
- executeNet("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex'");
+ executeNet("CREATE INDEX ON %s(val) USING 'sai'");
TableMetadata metadata = currentTableMetadata();
AbstractType<?> tuple =
metadata.getColumn(ColumnIdentifier.getInterned("val", false)).type;
@@ -246,8 +248,8 @@ public class StorageAttachedIndexDDLTest extends SAITester
String invalidColumn = "/invalid";
createTable(String.format("CREATE TABLE %%s (id text PRIMARY KEY,
\"%s\" text)", invalidColumn));
- assertThatThrownBy(() -> executeNet(String.format("CREATE CUSTOM INDEX
ON %%s(\"%s\")" +
- " USING
'StorageAttachedIndex'", invalidColumn)))
+ assertThatThrownBy(() -> executeNet(String.format("CREATE INDEX ON
%%s(\"%s\")" +
+ " USING 'sai'",
invalidColumn)))
.isInstanceOf(InvalidQueryException.class)
.hasMessage(String.format(CreateIndexStatement.INVALID_CUSTOM_INDEX_TARGET,
invalidColumn, SchemaConstants.NAME_LENGTH));
}
@@ -256,20 +258,65 @@ public class StorageAttachedIndexDDLTest extends SAITester
public void shouldCreateIndexIfExists()
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
+ createIndex("CREATE INDEX IF NOT EXISTS ON %s(val) USING 'sai' ");
+ createIndexAsync("CREATE INDEX IF NOT EXISTS ON %s(val) USING 'sai' ");
- createIndex("CREATE CUSTOM INDEX IF NOT EXISTS ON %s(val) USING
'StorageAttachedIndex' ");
+ assertEquals(1, saiCreationCounter.get());
+ }
+
+ @Test
+ public void shouldCreateIndexCaseInsensitive()
+ {
+ createTable("CREATE TABLE %s (id text PRIMARY KEY, val1 text, val2
text)");
+ createIndex("CREATE INDEX mixed_case_val ON %s(val1) USING 'Sai' ");
+ createIndex("CREATE INDEX upper_case_val ON %s(val2) USING 'SAI' ");
+
+ assertEquals(2, saiCreationCounter.get());
+ }
- createIndexAsync("CREATE CUSTOM INDEX IF NOT EXISTS ON %s(val) USING
'StorageAttachedIndex' ");
+ @Test
+ public void shouldCreateIndexWithClassName()
+ {
+ createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
+ createIndex("CREATE INDEX ON %s(val) USING 'StorageAttachedIndex' ");
+ assertEquals(1, saiCreationCounter.get());
+ }
+ @Test
+ public void shouldCreateIndexWithDefault()
+ {
+ DatabaseDescriptor.setDefaultSecondaryIndex(StorageAttachedIndex.NAME);
+ createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
+ createIndex("CREATE INDEX ON %s(val)");
assertEquals(1, saiCreationCounter.get());
}
+ @Test
+ public void shouldFailWithDefaultIndexDisabled()
+ {
+ DatabaseDescriptor.setDefaultSecondaryIndex(StorageAttachedIndex.NAME);
+ boolean original =
DatabaseDescriptor.getDefaultSecondaryIndexEnabled();
+
+ try
+ {
+ DatabaseDescriptor.setDefaultSecondaryIndexEnabled(false);
+ createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
+ assertThatThrownBy(() -> createIndex("CREATE INDEX ON
%s(val)")).hasRootCauseInstanceOf(InvalidRequestException.class)
+
.hasRootCauseMessage(CreateIndexStatement.MUST_SPECIFY_INDEX_IMPLEMENTATION);
+ assertEquals(0, saiCreationCounter.get());
+ }
+ finally
+ {
+ DatabaseDescriptor.setDefaultSecondaryIndexEnabled(original);
+ }
+ }
+
@Test
public void shouldBeCaseSensitiveByDefault()
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex'");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai'");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Camel')");
@@ -283,7 +330,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex' WITH OPTIONS = { 'case_sensitive' : true }");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai' WITH OPTIONS = {
'case_sensitive' : true }");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Camel')");
@@ -297,7 +344,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex' WITH OPTIONS = { 'case_sensitive' : false }");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai' WITH OPTIONS = {
'case_sensitive' : false }");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Camel')");
@@ -309,7 +356,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex'");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai'");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Cam\u00E1l')");
@@ -324,7 +371,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex' WITH OPTIONS = { 'normalize' : false }");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai' WITH OPTIONS = {
'normalize' : false }");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Cam\u00E1l')");
@@ -339,7 +386,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex' WITH OPTIONS = { 'normalize' : true }");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai' WITH OPTIONS = {
'normalize' : true }");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Cam\u00E1l')");
@@ -351,7 +398,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex' WITH OPTIONS = { 'normalize' : true, 'case_sensitive' :
false}");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai' WITH OPTIONS = {
'normalize' : true, 'case_sensitive' : false}");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Cam\u00E1l')");
@@ -363,7 +410,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex' WITH OPTIONS = { 'ascii' : true, 'case_sensitive' :
false}");
+ createIndex("CREATE INDEX ON %s(val) USING 'sai' WITH OPTIONS = {
'ascii' : true, 'case_sensitive' : false}");
execute("INSERT INTO %s (id, val) VALUES ('1', 'Éppinger')");
@@ -371,11 +418,11 @@ public class StorageAttachedIndexDDLTest extends SAITester
}
@Test
- public void shouldCreateIndexOnReversedType() throws Throwable
+ public void shouldCreateIndexOnReversedType()
{
createTable("CREATE TABLE %s (id text, ck1 text, val text, PRIMARY KEY
(id,ck1)) WITH CLUSTERING ORDER BY (ck1 desc)");
- String indexNameCk1 = createIndex("CREATE CUSTOM INDEX ON %s(ck1)
USING 'StorageAttachedIndex'");
+ String indexNameCk1 = createIndex("CREATE INDEX ON %s(ck1) USING
'sai'");
execute("insert into %s(id, ck1, val) values('1', '2', '3')");
execute("insert into %s(id, ck1, val) values('1', '3', '4')");
@@ -392,11 +439,10 @@ public class StorageAttachedIndexDDLTest extends SAITester
}
@Test
- public void shouldCreateIndexWithAlias()
+ public void shouldCreateIndexWithFullClassName()
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val text)");
-
- createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex'");
+ createIndex("CREATE CUSTOM INDEX ON %s(val) USING
'org.apache.cassandra.index.sai.StorageAttachedIndex'");
assertEquals(1, saiCreationCounter.get());
}
@@ -406,7 +452,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
* Not putting in {@link MixedIndexImplementationsTest} because it uses
CQLTester which doesn't load SAI dependency.
*/
@Test
- public void shouldCreateSASI() throws Throwable
+ public void shouldCreateSASI()
{
createTable(CREATE_TABLE_TEMPLATE);
@@ -433,7 +479,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
{
createTable("CREATE TABLE %s (id text PRIMARY KEY, val1 text, val2
text)");
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(val1,
val2) USING 'StorageAttachedIndex'"))
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(val1, val2)
USING 'sai'"))
.isInstanceOf(InvalidQueryException.class)
.hasMessageContaining("storage-attached index cannot be created over
multiple columns");
}
@@ -445,21 +491,21 @@ public class StorageAttachedIndexDDLTest extends SAITester
execute("INSERT INTO %s (id, v1) VALUES(1, '1')");
flush();
- executeNet("CREATE CUSTOM INDEX index_1 ON %s(v1) USING
'StorageAttachedIndex'");
+ executeNet("CREATE INDEX index_1 ON %s(v1) USING 'sai'");
waitForTableIndexesQueryable();
// same name
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX index_1 ON
%s(v1) USING 'StorageAttachedIndex'"))
+ assertThatThrownBy(() -> executeNet("CREATE INDEX index_1 ON %s(v1)
USING 'sai'"))
.isInstanceOf(InvalidQueryException.class)
.hasMessageContaining(String.format(CreateIndexStatement.INDEX_ALREADY_EXISTS,
"index_1"));
// different name, same option
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX index_2 ON
%s(v1) USING 'StorageAttachedIndex'"))
+ assertThatThrownBy(() -> executeNet("CREATE INDEX index_2 ON %s(v1)
USING 'sai'"))
.isInstanceOf(InvalidQueryException.class)
.hasMessageContaining(String.format(CreateIndexStatement.INDEX_DUPLICATE_OF_EXISTING,
"index_2", "index_1"));
// different name, different option, same target.
- assertThatThrownBy(() -> executeNet("CREATE CUSTOM INDEX ON %s(v1)
USING 'StorageAttachedIndex' WITH OPTIONS = { 'case_sensitive' : true }"))
+ assertThatThrownBy(() -> executeNet("CREATE INDEX ON %s(v1) USING
'sai' WITH OPTIONS = { 'case_sensitive' : true }"))
.isInstanceOf(InvalidQueryException.class)
.hasMessageContaining("Cannot create more than one storage-attached
index on the same column: v1" );
@@ -496,7 +542,7 @@ public class StorageAttachedIndexDDLTest extends SAITester
// Create the index, but do not allow the initial index build to begin:
Injections.inject(delayInitializationTask);
- createIndexAsync("CREATE CUSTOM INDEX ON %s(val) USING
'StorageAttachedIndex'");
+ createIndexAsync("CREATE INDEX ON %s(val) USING 'sai'");
// Flush the Memtable's contents, which will feed data to the index as
the SSTable is written:
flush();
diff --git
a/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java
b/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java
index b1d54085df..a9320ea173 100644
---
a/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java
+++
b/test/unit/org/apache/cassandra/index/sai/cql/types/IndexingTypeSupport.java
@@ -87,7 +87,7 @@ public abstract class IndexingTypeSupport extends SAITester
if (scenario != Scenario.POST_BUILD_QUERY)
{
for (String index : dataset.decorateIndexColumn("value"))
- createIndex(String.format("CREATE CUSTOM INDEX ON %%s(%s)
USING 'StorageAttachedIndex'", index));
+ createIndex(String.format("CREATE INDEX ON %%s(%s) USING
'sai'", index));
}
insertData(this, allRows, scenario);
@@ -104,14 +104,14 @@ public abstract class IndexingTypeSupport extends
SAITester
case POST_BUILD_QUERY:
flush();
for (String index : dataset.decorateIndexColumn("value"))
- createIndex(String.format("CREATE CUSTOM INDEX ON %%s(%s)
USING 'StorageAttachedIndex'", index));
+ createIndex(String.format("CREATE INDEX ON %%s(%s) USING
'sai'", index));
break;
}
dataset.querySet().runQueries(this, allRows);
}
- public static void insertData(SAITester tester, Object[][] allRows,
Scenario scenario) throws Throwable
+ public static void insertData(SAITester tester, Object[][] allRows,
Scenario scenario)
{
int sstableCounter = 0;
int sstableIncrement = NUMBER_OF_VALUES / 8;
diff --git
a/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java
b/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java
index 9e348dcd6c..45fd55bcd9 100644
---
a/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java
+++
b/test/unit/org/apache/cassandra/index/sai/functional/GroupComponentsTest.java
@@ -45,7 +45,7 @@ public class GroupComponentsTest extends SAITester
public void testInvalidateWithoutObsolete()
{
createTable("CREATE TABLE %s (pk int primary key, value text)");
- createIndex("CREATE CUSTOM INDEX ON %s(value) USING
'StorageAttachedIndex'");
+ createIndex("CREATE INDEX ON %s(value) USING 'sai'");
execute("INSERT INTO %s (pk) VALUES (1)");
flush();
@@ -70,7 +70,7 @@ public class GroupComponentsTest extends SAITester
public void getLiveComponentsForEmptyIndex()
{
createTable("CREATE TABLE %s (pk int primary key, value text)");
- createIndex("CREATE CUSTOM INDEX ON %s(value) USING
'StorageAttachedIndex'");
+ createIndex("CREATE INDEX ON %s(value) USING 'sai'");
execute("INSERT INTO %s (pk) VALUES (1)");
flush();
@@ -91,7 +91,7 @@ public class GroupComponentsTest extends SAITester
public void getLiveComponentsForPopulatedIndex()
{
createTable("CREATE TABLE %s (pk int primary key, value text)");
- IndexContext indexContext = createIndexContext(createIndex("CREATE
CUSTOM INDEX ON %s(value) USING 'StorageAttachedIndex'"), UTF8Type.instance);
+ IndexContext indexContext = createIndexContext(createIndex("CREATE
INDEX ON %s(value) USING 'sai'"), UTF8Type.instance);
execute("INSERT INTO %s (pk, value) VALUES (1, '1')");
flush();
diff --git
a/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java
b/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java
index eebcdf6561..580d2694d5 100644
---
a/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java
+++
b/test/unit/org/apache/cassandra/index/sai/virtual/SSTablesSystemViewTest.java
@@ -73,7 +73,7 @@ public class SSTablesSystemViewTest extends SAITester
public void testVirtualTableThroughIndexLifeCycle() throws Throwable
{
createTable("CREATE TABLE %s (k text, c text, v1 text, v2 text,
PRIMARY KEY (k, c))");
- String v1IndexName = createIndex("CREATE CUSTOM INDEX ON %s(v1) USING
'StorageAttachedIndex'");
+ String v1IndexName = createIndex("CREATE INDEX ON %s(v1) USING 'sai'");
String insert = "INSERT INTO %s(k, c, v1, v2) VALUES (?, ?, ?, ?)";
@@ -99,7 +99,7 @@ public class SSTablesSystemViewTest extends SAITester
assertRowsIgnoringOrder(execute(SELECT), row1, row2);
// create a second index, this should create a new additional entry in
the table for each sstable
- String v2IndexName = createIndex("CREATE CUSTOM INDEX ON %s(v2) USING
'StorageAttachedIndex'");
+ String v2IndexName = createIndex("CREATE INDEX ON %s(v2) USING 'sai'");
Object[] row3 = readRow(v2IndexName, id1, "v2", 1L, 0L, 0L);
Object[] row4 = readRow(v2IndexName, id2, "v2", 2L, 0L, 1L);
assertRowsIgnoringOrder(execute(SELECT), row1, row2, row3, row4);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]