This is an automated email from the ASF dual-hosted git repository.

maedhroz pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit 394d4b116868e4897ad3cc40833df801366a8916
Author: Caleb Rackliffe <calebrackli...@gmail.com>
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 9e79d3525b..a9d0ddadbc 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -1975,6 +1975,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 47b197cf9b..5b3bc81887 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 043cb9b5bc..f288baefbf 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 5d3e45089a..2979e41581 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: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to