From fde97c3b3d93901722ee2975552909e013b48b65 Mon Sep 17 00:00:00 2001 From: Sam Tunnicliffe Date: Wed, 16 Sep 2015 11:09:02 +0100 Subject: [PATCH] Remove target_columns from index metadata Patch by Sam Tunnicliffe; reviewed by Sylvain Lebresne for CASSANDRA-10216 --- ...-3.0.0-alpha3-d56dd0b-SNAPSHOT-shaded.jar} | Bin 2218913 -> 2216851 bytes ...r-internal-only-3.0.0a2.post0-fecbd54.zip} | Bin 230630 -> 230674 bytes .../apache/cassandra/config/CFMetaData.java | 13 +- src/java/org/apache/cassandra/cql3/Cql.g | 3 +- .../cql3/statements/AlterTableStatement.java | 23 ++-- .../cql3/statements/CreateIndexStatement.java | 38 ++---- .../cql3/statements/IndexPropDefs.java | 5 + .../cql3/statements/IndexTarget.java | 104 ++++++++------- .../org/apache/cassandra/index/Index.java | 13 ++ .../index/SecondaryIndexManager.java | 19 ++- .../index/internal/CassandraIndex.java | 111 ++++++++++++---- .../cassandra/schema/IndexMetadata.java | 119 +++++++++--------- .../org/apache/cassandra/schema/Indexes.java | 34 ----- .../schema/LegacySchemaMigrator.java | 31 ++--- .../cassandra/schema/SchemaKeyspace.java | 46 +------ .../cassandra/thrift/ThriftConversion.java | 65 +++++++--- .../org/apache/cassandra/SchemaLoader.java | 17 ++- .../entities/FrozenCollectionsTest.java | 6 +- .../entities/SecondaryIndexTest.java | 67 +++++++++- .../org/apache/cassandra/db/CleanupTest.java | 4 +- .../apache/cassandra/db/DirectoriesTest.java | 6 +- .../cassandra/db/RangeTombstoneTest.java | 16 ++- .../cassandra/db/SecondaryIndexTest.java | 41 +++--- .../org/apache/cassandra/index/StubIndex.java | 6 +- .../index/internal/CustomCassandraIndex.java | 93 ++------------ .../org/apache/cassandra/schema/DefsTest.java | 38 ++---- .../schema/LegacySchemaMigratorTest.java | 12 +- 27 files changed, 495 insertions(+), 435 deletions(-) rename lib/{cassandra-driver-core-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar => cassandra-driver-core-3.0.0-alpha3-d56dd0b-SNAPSHOT-shaded.jar} (88%) rename lib/{cassandra-driver-internal-only-3.0.0a2.post0-96883eb.zip => cassandra-driver-internal-only-3.0.0a2.post0-fecbd54.zip} (78%) diff --git a/lib/cassandra-driver-core-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar b/lib/cassandra-driver-core-3.0.0-alpha3-d56dd0b-SNAPSHOT-shaded.jar similarity index 88% rename from lib/cassandra-driver-core-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar rename to lib/cassandra-driver-core-3.0.0-alpha3-d56dd0b-SNAPSHOT-shaded.jar index fc5d2f0c561a6963cebd835f03ff7e55e8cb32cf..79d5a8a8a9dbc114ae5b9231a3ab0a842f1631fd 100644 GIT binary patch delta 94361 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 delta 96370 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 xZlIek|2(av`&rAkt#|}C8it^OaA@?eJeA42b{$ diff --git a/lib/cassandra-driver-internal-only-3.0.0a2.post0-96883eb.zip b/lib/cassandra-driver-internal-only-3.0.0a2.post0-fecbd54.zip similarity index 78% rename from lib/cassandra-driver-internal-only-3.0.0a2.post0-96883eb.zip rename to lib/cassandra-driver-internal-only-3.0.0a2.post0-fecbd54.zip index e55b4c327ecbd9af157820449cadad773088fbb8..fe9e0de8c15780576be587bd788abf07a9b3b535 100644 GIT binary patch delta 26865 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 mY($@lu8_~}Gccbd0CZocVTU!2bXWH$=7o diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java index cf1dbbf6f5..929a34ad1c 100644 --- a/src/java/org/apache/cassandra/config/CFMetaData.java +++ b/src/java/org/apache/cassandra/config/CFMetaData.java @@ -957,9 +957,18 @@ public final class CFMetaData { throw new InvalidRequestException(String.format("Cannot rename non PRIMARY KEY part %s", from)); } - else if (getIndexes().hasIndexFor(def)) + + if (!getIndexes().isEmpty()) { - throw new InvalidRequestException(String.format("Cannot rename column %s because it is secondary indexed", from)); + ColumnFamilyStore store = Keyspace.openAndGetStore(this); + Set dependentIndexes = store.indexManager.getDependentIndexes(def); + if (!dependentIndexes.isEmpty()) + throw new InvalidRequestException(String.format("Cannot rename column %s because it has " + + "dependent secondary indexes (%s)", + from, + dependentIndexes.stream() + .map(i -> i.name) + .collect(Collectors.joining(",")))); } ColumnDefinition newDef = def.withNewName(to); diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g index f6d54f5359..b552165d5a 100644 --- a/src/java/org/apache/cassandra/cql3/Cql.g +++ b/src/java/org/apache/cassandra/cql3/Cql.g @@ -726,7 +726,8 @@ createIndexStatement returns [CreateIndexStatement expr] ; indexIdent returns [IndexTarget.Raw id] - : c=cident { $id = IndexTarget.Raw.valuesOf(c); } + : c=cident { $id = IndexTarget.Raw.simpleIndexOn(c); } + | K_VALUES '(' c=cident ')' { $id = IndexTarget.Raw.valuesOf(c); } | K_KEYS '(' c=cident ')' { $id = IndexTarget.Raw.keysOf(c); } | K_ENTRIES '(' c=cident ')' { $id = IndexTarget.Raw.keysAndValuesOf(c); } | K_FULL '(' c=cident ')' { $id = IndexTarget.Raw.fullCollection(c); } diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java index af9a75c5d7..0d2011b334 100644 --- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java @@ -18,6 +18,7 @@ package org.apache.cassandra.cql3.statements; import java.util.*; +import java.util.stream.Collectors; import com.google.common.collect.Iterables; @@ -26,6 +27,8 @@ import org.apache.cassandra.config.*; import org.apache.cassandra.cql3.CFName; import org.apache.cassandra.cql3.CQL3Type; import org.apache.cassandra.cql3.ColumnIdentifier; +import org.apache.cassandra.db.ColumnFamilyStore; +import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.db.marshal.CollectionType; import org.apache.cassandra.db.marshal.CounterColumnType; @@ -268,17 +271,21 @@ public class AlterTableStatement extends SchemaAlteringStatement break; } - // If the dropped column is the only target column of a secondary - // index (and it's only possible to create an index with TargetType.COLUMN - // and a single target right now) we need to also drop the index. + // If the dropped column is required by any secondary indexes + // we reject the operation, as the indexes must be dropped first Indexes allIndexes = cfm.getIndexes(); - Collection indexes = allIndexes.get(def); - for (IndexMetadata index : indexes) + if (!allIndexes.isEmpty()) { - assert index.columns.size() == 1 : String.format("Can't drop column %s as it's a target of multi-column index %s", def.name, index.name); - allIndexes = allIndexes.without(index.name); + ColumnFamilyStore store = Keyspace.openAndGetStore(cfm); + Set dependentIndexes = store.indexManager.getDependentIndexes(def); + if (!dependentIndexes.isEmpty()) + throw new InvalidRequestException(String.format("Cannot drop column %s because it has " + + "dependent secondary indexes (%s)", + def, + dependentIndexes.stream() + .map(i -> i.name) + .collect(Collectors.joining(",")))); } - cfm.indexes(allIndexes); // If a column is dropped which is included in a view, we don't allow the drop to take place. boolean rejectAlter = false; diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java index 19d89b01ef..6cc416d79b 100644 --- a/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java @@ -22,7 +22,6 @@ import java.util.Map; import com.google.common.base.Optional; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,9 +80,6 @@ public class CreateIndexStatement extends SchemaAlteringStatement IndexTarget target = rawTarget.prepare(cfm); ColumnDefinition cd = cfm.getColumnDefinition(target.column); - if (cd == null) - throw new InvalidRequestException("No column definition found for column " + target.column); - boolean isMap = cd.type instanceof MapType; boolean isFrozenCollection = cd.type.isCollection() && !cd.type.isMultiCell(); @@ -94,7 +90,7 @@ public class CreateIndexStatement extends SchemaAlteringStatement else { validateNotFullIndex(target); - validateIsValuesIndexIfTargetColumnNotCollection(cd, target); + validateIsSimpleIndexIfTargetColumnNotCollection(cd, target); validateTargetColumnIsMapIfIndexInvolvesKeys(isMap, target); } @@ -136,7 +132,9 @@ public class CreateIndexStatement extends SchemaAlteringStatement private void validateForFrozenCollection(IndexTarget target) throws InvalidRequestException { if (target.type != IndexTarget.Type.FULL) - throw new InvalidRequestException(String.format("Cannot create index on %s of frozen column %s", target.type, target.column)); + throw new InvalidRequestException(String.format("Cannot create %s() index on frozen column %s. " + + "Frozen collections only support full() indexes", + target.type, target.column)); } private void validateNotFullIndex(IndexTarget target) throws InvalidRequestException @@ -145,11 +143,12 @@ public class CreateIndexStatement extends SchemaAlteringStatement throw new InvalidRequestException("full() indexes can only be created on frozen collections"); } - private void validateIsValuesIndexIfTargetColumnNotCollection(ColumnDefinition cd, IndexTarget target) throws InvalidRequestException + private void validateIsSimpleIndexIfTargetColumnNotCollection(ColumnDefinition cd, IndexTarget target) throws InvalidRequestException { - if (!cd.type.isCollection() && target.type != IndexTarget.Type.VALUES) - throw new InvalidRequestException(String.format("Cannot create index on %s of column %s; only non-frozen collections support %s indexes", - target.type, target.column, target.type)); + if (!cd.type.isCollection() && target.type != IndexTarget.Type.SIMPLE) + throw new InvalidRequestException(String.format("Cannot create %s() index on %s. " + + "Non-collection columns support only simple indexes", + target.type.toString(), target.column)); } private void validateTargetColumnIsMapIfIndexInvolvesKeys(boolean isMap, IndexTarget target) throws InvalidRequestException @@ -180,31 +179,20 @@ public class CreateIndexStatement extends SchemaAlteringStatement throw new InvalidRequestException(String.format("Index %s already exists", acceptedName)); } - IndexMetadata.IndexType indexType; + IndexMetadata.Kind kind; Map indexOptions; if (properties.isCustom) { - indexType = IndexMetadata.IndexType.CUSTOM; + kind = IndexMetadata.Kind.CUSTOM; indexOptions = properties.getOptions(); } - else if (cfm.isCompound()) - { - Map options = Collections.emptyMap(); - // For now, we only allow indexing values for collections, but we could later allow - // to also index map keys, so we record that this is the values we index to make our - // lives easier then. - if (cd.type.isCollection() && cd.type.isMultiCell()) - options = ImmutableMap.of(target.type.indexOption(), ""); - indexType = IndexMetadata.IndexType.COMPOSITES; - indexOptions = options; - } else { - indexType = IndexMetadata.IndexType.KEYS; indexOptions = Collections.emptyMap(); + kind = cfm.isCompound() ? IndexMetadata.Kind.COMPOSITES : IndexMetadata.Kind.KEYS; } - IndexMetadata index = IndexMetadata.singleColumnIndex(cd, acceptedName, indexType, indexOptions); + IndexMetadata index = IndexMetadata.singleTargetIndex(cfm, target, acceptedName, kind, indexOptions); // check to disallow creation of an index which duplicates an existing one in all but name Optional existingIndex = Iterables.tryFind(cfm.getIndexes(), existing -> existing.equalsWithoutName(index)); diff --git a/src/java/org/apache/cassandra/cql3/statements/IndexPropDefs.java b/src/java/org/apache/cassandra/cql3/statements/IndexPropDefs.java index e067217f9b..b8ce7ecafc 100644 --- a/src/java/org/apache/cassandra/cql3/statements/IndexPropDefs.java +++ b/src/java/org/apache/cassandra/cql3/statements/IndexPropDefs.java @@ -54,6 +54,11 @@ public class IndexPropDefs extends PropertyDefinitions if (getRawOptions().containsKey(IndexTarget.CUSTOM_INDEX_OPTION_NAME)) throw new InvalidRequestException(String.format("Cannot specify %s as a CUSTOM option", IndexTarget.CUSTOM_INDEX_OPTION_NAME)); + + if (getRawOptions().containsKey(IndexTarget.TARGET_OPTION_NAME)) + throw new InvalidRequestException(String.format("Cannot specify %s as a CUSTOM option", + IndexTarget.TARGET_OPTION_NAME)); + } public Map getRawOptions() throws SyntaxException diff --git a/src/java/org/apache/cassandra/cql3/statements/IndexTarget.java b/src/java/org/apache/cassandra/cql3/statements/IndexTarget.java index f948d8b130..6210a864f8 100644 --- a/src/java/org/apache/cassandra/cql3/statements/IndexTarget.java +++ b/src/java/org/apache/cassandra/cql3/statements/IndexTarget.java @@ -17,15 +17,16 @@ */ package org.apache.cassandra.cql3.statements; -import java.util.Map; +import java.util.regex.Pattern; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.cql3.ColumnIdentifier; -import org.apache.cassandra.schema.IndexMetadata; +import org.apache.cassandra.exceptions.InvalidRequestException; public class IndexTarget { + public static final String TARGET_OPTION_NAME = "target"; public static final String CUSTOM_INDEX_OPTION_NAME = "class_name"; /** @@ -33,23 +34,44 @@ public class IndexTarget */ public static final String INDEX_KEYS_OPTION_NAME = "index_keys"; - /** - * The name of the option used to specify that the index is on the collection values. - */ - public static final String INDEX_VALUES_OPTION_NAME = "index_values"; - /** * The name of the option used to specify that the index is on the collection (map) entries. */ public static final String INDEX_ENTRIES_OPTION_NAME = "index_keys_and_values"; + /** + * Regex for *unquoted* column names, anything which does not match this pattern must be a quoted name + */ + private static final Pattern COLUMN_IDENTIFIER_PATTERN = Pattern.compile("[a-z_0-9]+"); + public final ColumnIdentifier column; + public final boolean quoteName; public final Type type; - private IndexTarget(ColumnIdentifier column, Type type) + public IndexTarget(ColumnIdentifier column, Type type) { this.column = column; this.type = type; + + // if the column name contains anything other than lower case alphanumerics + // or underscores, then it must be quoted when included in the target string + quoteName = !COLUMN_IDENTIFIER_PATTERN.matcher(column.toString()).matches(); + } + + public String asCqlString(CFMetaData cfm) + { + if (! cfm.getColumnDefinition(column).type.isCollection()) + return maybeEscapeQuotedName(column.toString()); + + return String.format("%s(%s)", type.toString(), maybeEscapeQuotedName(column.toString())); + } + + // Quoted column names may themselves contain quotes, these need + // to be escaped with a preceding quote when written out as cql. + // Of course, the escaped name also needs to be wrapped in quotes. + private String maybeEscapeQuotedName(String name) + { + return quoteName ? '\"' + name.replace("\"", "\"\"") + '\"' : name; } public static class Raw @@ -63,6 +85,11 @@ public class IndexTarget this.type = type; } + public static Raw simpleIndexOn(ColumnIdentifier.Raw c) + { + return new Raw(c, Type.SIMPLE); + } + public static Raw valuesOf(ColumnIdentifier.Raw c) { return new Raw(c, Type.VALUES); @@ -85,13 +112,24 @@ public class IndexTarget public IndexTarget prepare(CFMetaData cfm) { - return new IndexTarget(column.prepare(cfm), type); + // Until we've prepared the target column, we can't be certain about the target type + // because (for backwards compatibility) an index on a collection's values uses the + // same syntax as an index on a regular column (i.e. the 'values' in + // 'CREATE INDEX on table(values(collection));' is optional). So we correct the target type + // when the target column is a collection & the target type is SIMPLE. + ColumnIdentifier colId = column.prepare(cfm); + ColumnDefinition columnDef = cfm.getColumnDefinition(colId); + if (columnDef == null) + throw new InvalidRequestException("No column definition found for column " + colId); + + Type actualType = (type == Type.SIMPLE && columnDef.type.isCollection()) ? Type.VALUES : type; + return new IndexTarget(colId, actualType); } } public static enum Type { - VALUES, KEYS, KEYS_AND_VALUES, FULL; + VALUES, KEYS, KEYS_AND_VALUES, FULL, SIMPLE; public String toString() { @@ -100,44 +138,26 @@ public class IndexTarget case KEYS: return "keys"; case KEYS_AND_VALUES: return "entries"; case FULL: return "full"; - default: return "values"; + case VALUES: return "values"; + case SIMPLE: return ""; + default: return ""; } } - public String indexOption() + public static Type fromString(String s) { - switch (this) - { - case KEYS: return INDEX_KEYS_OPTION_NAME; - case KEYS_AND_VALUES: return INDEX_ENTRIES_OPTION_NAME; - case VALUES: return INDEX_VALUES_OPTION_NAME; - default: throw new AssertionError(); - } - } - - public static Type fromIndexMetadata(IndexMetadata index, CFMetaData cfm) - { - Map options = index.options; - if (options.containsKey(INDEX_KEYS_OPTION_NAME)) - { + if ("".equals(s)) + return SIMPLE; + else if ("values".equals(s)) + return VALUES; + else if ("keys".equals(s)) return KEYS; - } - else if (options.containsKey(INDEX_ENTRIES_OPTION_NAME)) - { + else if ("entries".equals(s)) return KEYS_AND_VALUES; - } - else - { - ColumnDefinition cd = index.indexedColumn(cfm); - if (cd.type.isCollection() && !cd.type.isMultiCell()) - { - return FULL; - } - else - { - return VALUES; - } - } + else if ("full".equals(s)) + return FULL; + + throw new AssertionError("Unrecognized index target type " + s); } } } diff --git a/src/java/org/apache/cassandra/index/Index.java b/src/java/org/apache/cassandra/index/Index.java index 5dc44a4f2e..f07baad5b7 100644 --- a/src/java/org/apache/cassandra/index/Index.java +++ b/src/java/org/apache/cassandra/index/Index.java @@ -202,6 +202,19 @@ public interface Index */ public boolean indexes(PartitionColumns columns); + /** + * Called to determine whether this index targets a specific column. + * Used during schema operations such as when dropping or renaming a column, to check if + * the index will be affected by the change. Typically, if an index answers that it does + * depend upon a column, then schema operations on that column are not permitted until the index + * is dropped or altered. + * + * @param column the column definition to check + * @return true if the index depends on the supplied column being present; false if the column may be + * safely dropped or modified without adversely affecting the index + */ + public boolean dependsOn(ColumnDefinition column); + // TODO : this will change when we decouple indexes from specific columns for real per-row indexes /** * Called to determine whether this index can provide a searcher to execute a query on the diff --git a/src/java/org/apache/cassandra/index/SecondaryIndexManager.java b/src/java/org/apache/cassandra/index/SecondaryIndexManager.java index ff4567bf0b..1af2f6e026 100644 --- a/src/java/org/apache/cassandra/index/SecondaryIndexManager.java +++ b/src/java/org/apache/cassandra/index/SecondaryIndexManager.java @@ -31,12 +31,10 @@ import com.google.common.collect.Maps; import com.google.common.primitives.Longs; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; - import org.apache.commons.lang3.StringUtils; - -import org.apache.cassandra.db.Directories; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.apache.cassandra.concurrent.JMXEnabledThreadPoolExecutor; import org.apache.cassandra.concurrent.NamedThreadFactory; import org.apache.cassandra.concurrent.StageManager; @@ -188,6 +186,21 @@ public class SecondaryIndexManager implements IndexRegistry } } + + public Set getDependentIndexes(ColumnDefinition column) + { + if (indexes.isEmpty()) + return Collections.emptySet(); + + Set dependentIndexes = new HashSet<>(); + for (Index index : indexes.values()) + if (index.dependsOn(column)) + dependentIndexes.add(index.getIndexMetadata()); + + return dependentIndexes; + } + + /** * Called when dropping a Table */ diff --git a/src/java/org/apache/cassandra/index/internal/CassandraIndex.java b/src/java/org/apache/cassandra/index/internal/CassandraIndex.java index 89c072cd09..d10af1fa1d 100644 --- a/src/java/org/apache/cassandra/index/internal/CassandraIndex.java +++ b/src/java/org/apache/cassandra/index/internal/CassandraIndex.java @@ -5,14 +5,18 @@ import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.function.BiFunction; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.StreamSupport; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ColumnDefinition; +import org.apache.cassandra.cql3.ColumnIdentifier; import org.apache.cassandra.cql3.Operator; import org.apache.cassandra.cql3.statements.IndexTarget; import org.apache.cassandra.db.*; @@ -38,6 +42,7 @@ import org.apache.cassandra.io.sstable.ReducingKeyIterator; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.schema.IndexMetadata; import org.apache.cassandra.utils.FBUtilities; +import org.apache.cassandra.utils.Pair; import org.apache.cassandra.utils.concurrent.OpOrder; import org.apache.cassandra.utils.concurrent.Refs; @@ -49,13 +54,15 @@ public abstract class CassandraIndex implements Index { private static final Logger logger = LoggerFactory.getLogger(CassandraIndex.class); + public static final Pattern TARGET_REGEX = Pattern.compile("^(keys|entries|values|full)\\((.+)\\)$"); + public final ColumnFamilyStore baseCfs; protected IndexMetadata metadata; protected ColumnFamilyStore indexCfs; protected ColumnDefinition indexedColumn; protected CassandraIndexFunctions functions; - public CassandraIndex(ColumnFamilyStore baseCfs, IndexMetadata indexDef) + protected CassandraIndex(ColumnFamilyStore baseCfs, IndexMetadata indexDef) { this.baseCfs = baseCfs; setMetadata(indexDef); @@ -69,7 +76,7 @@ public abstract class CassandraIndex implements Index */ protected boolean supportsOperator(ColumnDefinition indexedColumn, Operator operator) { - return operator.equals(Operator.EQ); + return operator == Operator.EQ; } /** @@ -77,7 +84,6 @@ public abstract class CassandraIndex implements Index * The clustering columns in the index table encode the values required to retrieve the correct data from the base * table and varies depending on the kind of the indexed column. See indexCfsMetadata for more details * Used whenever a row in the index table is written or deleted. - * @param metadata * @param partitionKey from the base data being indexed * @param prefix from the base data being indexed * @param path from the base data being indexed @@ -90,7 +96,6 @@ public abstract class CassandraIndex implements Index /** * Used at search time to convert a row in the index table into a simple struct containing the values required * to retrieve the corresponding row from the base table. - * @param metadata * @param indexedValue the partition key of the indexed table (i.e. the value that was indexed) * @param indexEntry a row from the index table * @return @@ -102,7 +107,6 @@ public abstract class CassandraIndex implements Index * Check whether a value retrieved from an index is still valid by comparing it to current row from the base table. * Used at read time to identify out of date index entries so that they can be excluded from search results and * repaired - * @param metadata required to get the indexed column definition * @param row the current row from the primary data table * @param indexValue the value we retrieved from the index * @param nowInSec @@ -112,7 +116,6 @@ public abstract class CassandraIndex implements Index /** * Extract the value to be inserted into the index from the components of the base data - * @param metadata * @param partitionKey from the primary data * @param clustering from the primary data * @param path from the primary data @@ -197,14 +200,14 @@ public abstract class CassandraIndex implements Index private void setMetadata(IndexMetadata indexDef) { metadata = indexDef; - functions = getFunctions(baseCfs.metadata, indexDef); + Pair target = parseTarget(baseCfs.metadata, indexDef); + functions = getFunctions(indexDef, target); CFMetaData cfm = indexCfsMetadata(baseCfs.metadata, indexDef); indexCfs = ColumnFamilyStore.createColumnFamilyStore(baseCfs.keyspace, cfm.cfName, cfm, baseCfs.getTracker().loadsstables); - assert indexDef.columns.size() == 1 : "Build in indexes on multiple target columns are not supported"; - indexedColumn = indexDef.indexedColumn(baseCfs.metadata); + indexedColumn = target.left; } public Callable getTruncateTask(final long truncatedAt) @@ -227,6 +230,11 @@ public abstract class CassandraIndex implements Index return isPrimaryKeyIndex() || columns.contains(indexedColumn); } + public boolean dependsOn(ColumnDefinition column) + { + return indexedColumn.name.equals(column.name); + } + public boolean supportsExpression(ColumnDefinition column, Operator operator) { return indexedColumn.name.equals(column.name) @@ -269,7 +277,7 @@ public abstract class CassandraIndex implements Index if (target.isPresent()) { target.get().validateForIndexing(); - switch (getIndexMetadata().indexType) + switch (getIndexMetadata().kind) { case COMPOSITES: return new CompositesSearcher(command, target.get(), this); @@ -277,7 +285,7 @@ public abstract class CassandraIndex implements Index return new KeysSearcher(command, target.get(), this); default: throw new IllegalStateException(String.format("Unsupported index type %s for index %s on %s", - metadata.indexType, + metadata.kind, metadata.name, indexedColumn.name.toString())); } @@ -531,7 +539,7 @@ public abstract class CassandraIndex implements Index private void validatePartitionKey(DecoratedKey partitionKey) throws InvalidRequestException { assert indexedColumn.isPartitionKey(); - validateIndexedValue(getIndexedValue(partitionKey.getKey(), null, null )); + validateIndexedValue(getIndexedValue(partitionKey.getKey(), null, null)); } private void validateClusterings(PartitionUpdate update) throws InvalidRequestException @@ -613,7 +621,7 @@ public abstract class CassandraIndex implements Index Collection cfss = Collections.singleton(indexCfs); CompactionManager.instance.interruptCompactionForCFs(cfss, true); CompactionManager.instance.waitForCessation(cfss); - indexCfs.keyspace.writeOrder.awaitNewBarrier(); + Keyspace.writeOrder.awaitNewBarrier(); indexCfs.forceBlockingFlush(); indexCfs.readOrdering.awaitNewBarrier(); indexCfs.invalidate(); @@ -695,8 +703,9 @@ public abstract class CassandraIndex implements Index */ public static final CFMetaData indexCfsMetadata(CFMetaData baseCfsMetadata, IndexMetadata indexMetadata) { - CassandraIndexFunctions utils = getFunctions(baseCfsMetadata, indexMetadata); - ColumnDefinition indexedColumn = indexMetadata.indexedColumn(baseCfsMetadata); + Pair target = parseTarget(baseCfsMetadata, indexMetadata); + CassandraIndexFunctions utils = getFunctions(indexMetadata, target); + ColumnDefinition indexedColumn = target.left; AbstractType indexedValueType = utils.getIndexedValueType(indexedColumn); CFMetaData.Builder builder = CFMetaData.Builder.create(baseCfsMetadata.ksName, baseCfsMetadata.indexColumnFamilyName(indexMetadata)) @@ -715,17 +724,65 @@ public abstract class CassandraIndex implements Index * @param indexMetadata * @return */ - public static final CassandraIndex newIndex(ColumnFamilyStore baseCfs, IndexMetadata indexMetadata) + public static CassandraIndex newIndex(ColumnFamilyStore baseCfs, IndexMetadata indexMetadata) { - return getFunctions(baseCfs.metadata, indexMetadata).newIndexInstance(baseCfs, indexMetadata); + return getFunctions(indexMetadata, parseTarget(baseCfs.metadata, indexMetadata)).newIndexInstance(baseCfs, indexMetadata); } - private static CassandraIndexFunctions getFunctions(CFMetaData baseCfMetadata, IndexMetadata indexDef) + // Public because it's also used to convert index metadata into a thrift-compatible format + public static Pair parseTarget(CFMetaData cfm, + IndexMetadata indexDef) + { + String target = indexDef.options.get("target"); + assert target != null : String.format("No target definition found for index %s", indexDef.name); + + // if the regex matches then the target is in the form "keys(foo)", "entries(bar)" etc + // if not, then it must be a simple column name and implictly its type is VALUES + Matcher matcher = TARGET_REGEX.matcher(target); + String columnName; + IndexTarget.Type targetType; + if (matcher.matches()) + { + targetType = IndexTarget.Type.fromString(matcher.group(1)); + columnName = matcher.group(2); + } + else + { + columnName = target; + targetType = IndexTarget.Type.VALUES; + } + + // in the case of a quoted column name the name in the target string + // will be enclosed in quotes, which we need to unwrap. It may also + // include quote characters internally, escaped like so: + // abc"def -> abc""def. + // Because the target string is stored in a CQL compatible form, we + // need to un-escape any such quotes to get the actual column name + if (columnName.startsWith("\"")) + { + columnName = StringUtils.substring(StringUtils.substring(columnName, 1), 0, -1); + columnName = columnName.replaceAll("\"\"", "\""); + } + + // if it's not a CQL table, we can't assume that the column name is utf8, so + // in that case we have to do a linear scan of the cfm's columns to get the matching one + if (cfm.isCQLTable()) + return Pair.create(cfm.getColumnDefinition(new ColumnIdentifier(columnName, true)), targetType); + else + for (ColumnDefinition column : cfm.allColumns()) + if (column.name.toString().equals(columnName)) + return Pair.create(column, targetType); + + throw new RuntimeException(String.format("Unable to parse targets for index %s (%s)", indexDef.name, target)); + } + + static CassandraIndexFunctions getFunctions(IndexMetadata indexDef, + Pair target) { if (indexDef.isKeys()) return CassandraIndexFunctions.KEYS_INDEX_FUNCTIONS; - ColumnDefinition indexedColumn = indexDef.indexedColumn(baseCfMetadata); + ColumnDefinition indexedColumn = target.left; if (indexedColumn.type.isCollection() && indexedColumn.type.isMultiCell()) { switch (((CollectionType)indexedColumn.type).kind) @@ -735,12 +792,16 @@ public abstract class CassandraIndex implements Index case SET: return CassandraIndexFunctions.COLLECTION_KEY_INDEX_FUNCTIONS; case MAP: - if (indexDef.options.containsKey(IndexTarget.INDEX_KEYS_OPTION_NAME)) - return CassandraIndexFunctions.COLLECTION_KEY_INDEX_FUNCTIONS; - else if (indexDef.options.containsKey(IndexTarget.INDEX_ENTRIES_OPTION_NAME)) - return CassandraIndexFunctions.COLLECTION_ENTRY_INDEX_FUNCTIONS; - else - return CassandraIndexFunctions.COLLECTION_VALUE_INDEX_FUNCTIONS; + switch (target.right) + { + case KEYS: + return CassandraIndexFunctions.COLLECTION_KEY_INDEX_FUNCTIONS; + case KEYS_AND_VALUES: + return CassandraIndexFunctions.COLLECTION_ENTRY_INDEX_FUNCTIONS; + case VALUES: + return CassandraIndexFunctions.COLLECTION_VALUE_INDEX_FUNCTIONS; + } + throw new AssertionError(); } } diff --git a/src/java/org/apache/cassandra/schema/IndexMetadata.java b/src/java/org/apache/cassandra/schema/IndexMetadata.java index 6846a14b77..8052e9e0c1 100644 --- a/src/java/org/apache/cassandra/schema/IndexMetadata.java +++ b/src/java/org/apache/cassandra/schema/IndexMetadata.java @@ -20,11 +20,13 @@ package org.apache.cassandra.schema; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import org.apache.commons.lang3.builder.ToStringBuilder; import org.slf4j.Logger; @@ -50,53 +52,78 @@ public final class IndexMetadata public static final Serializer serializer = new Serializer(); - public enum IndexType + public enum Kind { KEYS, CUSTOM, COMPOSITES } - public enum TargetType - { - COLUMN, ROW - } - // UUID for serialization. This is a deterministic UUID generated from the index name // Both the id and name are guaranteed unique per keyspace. public final UUID id; public final String name; - public final IndexType indexType; - public final TargetType targetType; + public final Kind kind; public final Map options; - public final Set columns; private IndexMetadata(String name, Map options, - IndexType indexType, - TargetType targetType, - Set columns) + Kind kind) { this.id = UUID.nameUUIDFromBytes(name.getBytes()); this.name = name; this.options = options == null ? ImmutableMap.of() : ImmutableMap.copyOf(options); - this.indexType = indexType; - this.targetType = targetType; - this.columns = columns == null ? ImmutableSet.of() : ImmutableSet.copyOf(columns); + this.kind = kind; } - public static IndexMetadata singleColumnIndex(ColumnIdentifier column, - String name, - IndexType type, - Map options) + public static IndexMetadata fromLegacyMetadata(CFMetaData cfm, + ColumnDefinition column, + String name, + Kind kind, + Map options) { - return new IndexMetadata(name, options, type, TargetType.COLUMN, Collections.singleton(column)); + Map newOptions = new HashMap<>(); + if (options != null) + newOptions.putAll(options); + + IndexTarget target; + if (newOptions.containsKey(IndexTarget.INDEX_KEYS_OPTION_NAME)) + { + newOptions.remove(IndexTarget.INDEX_KEYS_OPTION_NAME); + target = new IndexTarget(column.name, IndexTarget.Type.KEYS); + } + else if (newOptions.containsKey(IndexTarget.INDEX_ENTRIES_OPTION_NAME)) + { + newOptions.remove(IndexTarget.INDEX_KEYS_OPTION_NAME); + target = new IndexTarget(column.name, IndexTarget.Type.KEYS_AND_VALUES); + } + else + { + if (column.type.isCollection() && !column.type.isMultiCell()) + { + target = new IndexTarget(column.name, IndexTarget.Type.FULL); + } + else + { + target = new IndexTarget(column.name, IndexTarget.Type.VALUES); + } + } + newOptions.put(IndexTarget.TARGET_OPTION_NAME, target.asCqlString(cfm)); + return new IndexMetadata(name, newOptions, kind); } - public static IndexMetadata singleColumnIndex(ColumnDefinition column, + public static IndexMetadata fromSchemaMetadata(String name, Kind kind, Map options) + { + return new IndexMetadata(name, options, kind); + } + + public static IndexMetadata singleTargetIndex(CFMetaData cfm, + IndexTarget target, String name, - IndexType type, + Kind kind, Map options) { - return singleColumnIndex(column.name, name, type, options); + Map newOptions = new HashMap<>(options); + newOptions.put(IndexTarget.TARGET_OPTION_NAME, target.asCqlString(cfm)); + return new IndexMetadata(name, newOptions, kind); } public static boolean isNameValid(String name) @@ -115,13 +142,10 @@ public final class IndexMetadata if (!isNameValid(name)) throw new ConfigurationException("Illegal index name " + name); - if (indexType == null) - throw new ConfigurationException("Index type is null for index " + name); + if (kind == null) + throw new ConfigurationException("Index kind is null for index " + name); - if (targetType == null) - throw new ConfigurationException("Target type is null for index " + name); - - if (indexType == IndexMetadata.IndexType.CUSTOM) + if (kind == Kind.CUSTOM) { if (options == null || !options.containsKey(IndexTarget.CUSTOM_INDEX_OPTION_NAME)) throw new ConfigurationException(String.format("Required option missing for index %s : %s", @@ -169,47 +193,29 @@ public final class IndexMetadata } } - // to be removed in CASSANDRA-10124 with multi-target & row based indexes - public ColumnDefinition indexedColumn(CFMetaData cfm) - { - return cfm.getColumnDefinition(columns.iterator().next()); - } - public boolean isCustom() { - return indexType == IndexType.CUSTOM; + return kind == Kind.CUSTOM; } public boolean isKeys() { - return indexType == IndexType.KEYS; + return kind == Kind.KEYS; } public boolean isComposites() { - return indexType == IndexType.COMPOSITES; - } - - public boolean isRowIndex() - { - return targetType == TargetType.ROW; - } - - public boolean isColumnIndex() - { - return targetType == TargetType.COLUMN; + return kind == Kind.COMPOSITES; } public int hashCode() { - return Objects.hashCode(id, name, indexType, targetType, options, columns); + return Objects.hashCode(id, name, kind, options); } public boolean equalsWithoutName(IndexMetadata other) { - return Objects.equal(indexType, other.indexType) - && Objects.equal(targetType, other.targetType) - && Objects.equal(columns, other.columns) + return Objects.equal(kind, other.kind) && Objects.equal(options, other.options); } @@ -231,9 +237,7 @@ public final class IndexMetadata return new ToStringBuilder(this) .append("id", id.toString()) .append("name", name) - .append("indexType", indexType) - .append("targetType", targetType) - .append("columns", columns) + .append("kind", kind) .append("options", options) .build(); } @@ -255,6 +259,5 @@ public final class IndexMetadata { return UUIDSerializer.serializer.serializedSize(metadata.id, version); } - } } diff --git a/src/java/org/apache/cassandra/schema/Indexes.java b/src/java/org/apache/cassandra/schema/Indexes.java index 9114f63466..422a94c97b 100644 --- a/src/java/org/apache/cassandra/schema/Indexes.java +++ b/src/java/org/apache/cassandra/schema/Indexes.java @@ -21,9 +21,7 @@ package org.apache.cassandra.schema; import java.util.*; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMultimap; -import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.config.Schema; import org.apache.cassandra.cql3.ColumnIdentifier; @@ -42,13 +40,11 @@ public class Indexes implements Iterable { private final ImmutableMap indexesByName; private final ImmutableMap indexesById; - private final ImmutableMultimap indexesByColumn; private Indexes(Builder builder) { indexesByName = builder.indexesByName.build(); indexesById = builder.indexesById.build(); - indexesByColumn = builder.indexesByColumn.build(); } public static Builder builder() @@ -120,28 +116,6 @@ public class Indexes implements Iterable return indexesById.containsKey(id); } - /** - * Get the index associated with the specified column. This may be removed or modified as support is added - * for indexes with multiple target columns and with TargetType.ROW - * - * @param column a column definition for which an {@link IndexMetadata} is being sought - * @return an empty {@link Optional} if the named index is not found; a non-empty optional of {@link IndexMetadata} otherwise - */ - public Collection get(ColumnDefinition column) - { - return indexesByColumn.get(column.name); - } - - /** - * Answer true if an index is associated with the specified column. - * @param column - * @return - */ - public boolean hasIndexFor(ColumnDefinition column) - { - return !indexesByColumn.get(column.name).isEmpty(); - } - /** * Create a SecondaryIndexes instance with the provided index added */ @@ -206,7 +180,6 @@ public class Indexes implements Iterable { final ImmutableMap.Builder indexesByName = new ImmutableMap.Builder<>(); final ImmutableMap.Builder indexesById = new ImmutableMap.Builder<>(); - final ImmutableMultimap.Builder indexesByColumn = new ImmutableMultimap.Builder<>(); private Builder() { @@ -221,13 +194,6 @@ public class Indexes implements Iterable { indexesByName.put(index.name, index); indexesById.put(index.id, index); - // All indexes are column indexes at the moment - if (index.isColumnIndex()) - { - for (ColumnIdentifier target : index.columns) - indexesByColumn.put(target, index); - - } return this; } diff --git a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java index 1674de8cae..0d5a040f41 100644 --- a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java +++ b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java @@ -296,15 +296,6 @@ public final class LegacySchemaMigrator isStaticCompactTable, needsUpgrade); - Indexes indexes = createIndexesFromColumnRows(columnRows, - ksName, - cfName, - rawComparator, - subComparator, - isSuper, - isCQLTable, - isStaticCompactTable, - needsUpgrade); if (needsUpgrade) { @@ -328,6 +319,17 @@ public final class LegacySchemaMigrator false, // legacy schema did not contain views columnDefs, DatabaseDescriptor.getPartitioner()); + + Indexes indexes = createIndexesFromColumnRows(cfm, + columnRows, + ksName, + cfName, + rawComparator, + subComparator, + isSuper, + isCQLTable, + isStaticCompactTable, + needsUpgrade); cfm.indexes(indexes); if (tableRow.has("dropped_columns")) @@ -591,7 +593,8 @@ public final class LegacySchemaMigrator return new ColumnDefinition(keyspace, table, name, validator, componentIndex, kind); } - private static Indexes createIndexesFromColumnRows(UntypedResultSet rows, + private static Indexes createIndexesFromColumnRows(CFMetaData cfm, + UntypedResultSet rows, String keyspace, String table, AbstractType rawComparator, @@ -605,11 +608,11 @@ public final class LegacySchemaMigrator for (UntypedResultSet.Row row : rows) { - IndexMetadata.IndexType indexType = null; + IndexMetadata.Kind kind = null; if (row.has("index_type")) - indexType = IndexMetadata.IndexType.valueOf(row.getString("index_type")); + kind = IndexMetadata.Kind.valueOf(row.getString("index_type")); - if (indexType == null) + if (kind == null) continue; Map indexOptions = null; @@ -630,7 +633,7 @@ public final class LegacySchemaMigrator isStaticCompactTable, needsUpgrade); - indexes.add(IndexMetadata.singleColumnIndex(column, indexName, indexType, indexOptions)); + indexes.add(IndexMetadata.fromLegacyMetadata(cfm, column, indexName, kind, indexOptions)); } return indexes.build(); diff --git a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java index c92261245a..d8992bd340 100644 --- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java +++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java @@ -177,10 +177,8 @@ public final class SchemaKeyspace + "keyspace_name text," + "table_name text," + "index_name text," - + "index_type text," + + "kind text," + "options frozen>," - + "target_columns frozen>," - + "target_type text," + "PRIMARY KEY ((keyspace_name), table_name, index_name))"); private static final CFMetaData Types = @@ -1449,10 +1447,8 @@ public final class SchemaKeyspace { RowUpdateBuilder builder = new RowUpdateBuilder(Indexes, timestamp, mutation).clustering(table.cfName, index.name); - builder.add("index_type", index.indexType.toString()); + builder.add("kind", index.kind.toString()); builder.frozenMap("options", index.options); - builder.frozenSet("target_columns", index.columns.stream().map(ColumnIdentifier::toString).collect(Collectors.toSet())); - builder.add("target_type", index.targetType.toString()); builder.build(); } @@ -1481,46 +1477,16 @@ public final class SchemaKeyspace { Indexes.Builder indexes = org.apache.cassandra.schema.Indexes.builder(); String query = String.format("SELECT * FROM %s.%s", NAME, INDEXES); - QueryProcessor.resultify(query, partition).forEach(row -> indexes.add(createIndexMetadataFromIndexesRow(cfm, row))); + QueryProcessor.resultify(query, partition).forEach(row -> indexes.add(createIndexMetadataFromIndexesRow(row))); return indexes.build(); } - private static IndexMetadata createIndexMetadataFromIndexesRow(CFMetaData cfm, UntypedResultSet.Row row) + private static IndexMetadata createIndexMetadataFromIndexesRow(UntypedResultSet.Row row) { String name = row.getString("index_name"); - IndexMetadata.IndexType type = IndexMetadata.IndexType.valueOf(row.getString("index_type")); - IndexMetadata.TargetType targetType = IndexMetadata.TargetType.valueOf(row.getString("target_type")); + IndexMetadata.Kind type = IndexMetadata.Kind.valueOf(row.getString("kind")); Map options = row.getFrozenTextMap("options"); - if (options == null) - options = Collections.emptyMap(); - - Set targetColumnNames = row.getFrozenSet("target_columns", UTF8Type.instance); - assert targetType == IndexMetadata.TargetType.COLUMN : "Per row indexes with dynamic target columns are not supported yet"; - - Set targetColumns = new HashSet<>(); - // if it's not a CQL table, we can't assume that the column name is utf8, so - // in that case we have to do a linear scan of the cfm's columns to get the matching one - if (targetColumnNames != null) - { - assert targetColumnNames.size() == 1 : "Secondary indexes targetting multiple columns are not supported yet"; - targetColumnNames.forEach(targetColumnName -> { - if (cfm.isCQLTable()) - targetColumns.add(ColumnIdentifier.getInterned(targetColumnName, true)); - else - findColumnIdentifierWithName(targetColumnName, cfm.allColumns()).ifPresent(targetColumns::add); - }); - } - return IndexMetadata.singleColumnIndex(targetColumns.iterator().next(), name, type, options); - } - - private static Optional findColumnIdentifierWithName(String name, - Iterable columns) - { - for (ColumnDefinition column : columns) - if (column.name.toString().equals(name)) - return Optional.of(column.name); - - return Optional.empty(); + return IndexMetadata.fromSchemaMetadata(name, type, options); } /* diff --git a/src/java/org/apache/cassandra/thrift/ThriftConversion.java b/src/java/org/apache/cassandra/thrift/ThriftConversion.java index b721226f87..80b6447a03 100644 --- a/src/java/org/apache/cassandra/thrift/ThriftConversion.java +++ b/src/java/org/apache/cassandra/thrift/ThriftConversion.java @@ -18,6 +18,7 @@ package org.apache.cassandra.thrift; import java.util.*; +import java.util.regex.Matcher; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; @@ -26,6 +27,7 @@ import com.google.common.collect.Maps; import org.apache.cassandra.config.*; import org.apache.cassandra.cql3.ColumnIdentifier; import org.apache.cassandra.cql3.Operator; +import org.apache.cassandra.cql3.statements.IndexTarget; import org.apache.cassandra.db.CompactTables; import org.apache.cassandra.db.LegacyLayout; import org.apache.cassandra.db.WriteType; @@ -33,6 +35,7 @@ import org.apache.cassandra.db.compaction.AbstractCompactionStrategy; import org.apache.cassandra.db.filter.RowFilter; import org.apache.cassandra.db.marshal.*; import org.apache.cassandra.exceptions.*; +import org.apache.cassandra.index.internal.CassandraIndex; import org.apache.cassandra.io.compress.ICompressor; import org.apache.cassandra.locator.AbstractReplicationStrategy; import org.apache.cassandra.locator.LocalStrategy; @@ -287,7 +290,8 @@ public class ThriftConversion DatabaseDescriptor.getPartitioner()); // Convert any secondary indexes defined in the thrift column_metadata - newCFMD.indexes(indexDefsFromThrift(cf_def.keyspace, + newCFMD.indexes(indexDefsFromThrift(newCFMD, + cf_def.keyspace, cf_def.name, rawComparator, subComparator, @@ -526,7 +530,8 @@ public class ThriftConversion return defs; } - private static Indexes indexDefsFromThrift(String ksName, + private static Indexes indexDefsFromThrift(CFMetaData cfm, + String ksName, String cfName, AbstractType thriftComparator, AbstractType thriftSubComparator, @@ -554,12 +559,12 @@ public class ThriftConversion indexNames.add(indexName); Map indexOptions = def.getIndex_options(); - IndexMetadata.IndexType indexType = IndexMetadata.IndexType.valueOf(def.index_type.name()); + if (indexOptions != null && indexOptions.containsKey(IndexTarget.TARGET_OPTION_NAME)) + throw new ConfigurationException("Reserved index option 'target' cannot be used"); - indexes.add(IndexMetadata.singleColumnIndex(column, - indexName, - indexType, - indexOptions)); + IndexMetadata.Kind kind = IndexMetadata.Kind.valueOf(def.index_type.name()); + + indexes.add(IndexMetadata.fromLegacyMetadata(cfm, column, indexName, kind, indexOptions)); } } return indexes.build(); @@ -572,22 +577,44 @@ public class ThriftConversion cd.setName(ByteBufferUtil.clone(column.name.bytes)); cd.setValidation_class(column.type.toString()); - Collection indexes = cfMetaData.getIndexes().get(column); - // we include the index in the ColumnDef iff - // * it is the only index on the column - // * it is the only target column for the index - if (indexes.size() == 1) + + // we include the index in the ColumnDef iff its targets are compatible with + // pre-3.0 indexes AND it is the only index defined on the given column, that is: + // * it is the only index on the column (i.e. with this column as its target) + // * it has only a single target, which matches the pattern for pre-3.0 indexes + // i.e. keys/values/entries/full, with exactly 1 argument that matches the + // column name OR a simple column name (for indexes on non-collection columns) + // n.b. it's a guess that using a pre-compiled regex and checking the group is + // cheaper than compiling a new regex for each column, but as this isn't on + // any hot path this hasn't been verified yet. + IndexMetadata matchedIndex = null; + for (IndexMetadata index : cfMetaData.getIndexes()) { - IndexMetadata index = indexes.iterator().next(); - if (index.columns.size() == 1) + String target = index.options.get(IndexTarget.TARGET_OPTION_NAME); + Matcher m = CassandraIndex.TARGET_REGEX.matcher(target); + if (target.equals(column.name.toString()) || + (m.matches() && m.group(2).equals(column.name.toString()))) { - cd.setIndex_type(org.apache.cassandra.thrift.IndexType.valueOf(index.indexType.name())); - cd.setIndex_name(index.name); - cd.setIndex_options(index.options == null || index.options.isEmpty() - ? null - : Maps.newHashMap(index.options)); + // we already found an index for this column, we've no option but to + // ignore both of them (and any others we've yet to find) + if (matchedIndex != null) + return cd; + + matchedIndex = index; } } + + if (matchedIndex != null) + { + cd.setIndex_type(org.apache.cassandra.thrift.IndexType.valueOf(matchedIndex.kind.name())); + cd.setIndex_name(matchedIndex.name); + Map filteredOptions = Maps.filterKeys(matchedIndex.options, + s -> !IndexTarget.TARGET_OPTION_NAME.equals(s)); + cd.setIndex_options(filteredOptions.isEmpty() + ? null + : Maps.newHashMap(matchedIndex.options)); + } + return cd; } diff --git a/test/unit/org/apache/cassandra/SchemaLoader.java b/test/unit/org/apache/cassandra/SchemaLoader.java index 72bfd00ece..c4b99c6b82 100644 --- a/test/unit/org/apache/cassandra/SchemaLoader.java +++ b/test/unit/org/apache/cassandra/SchemaLoader.java @@ -299,9 +299,10 @@ public class SchemaLoader cfm.indexes( cfm.getIndexes() - .with(IndexMetadata.singleColumnIndex(indexedColumn, + .with(IndexMetadata.singleTargetIndex(cfm, + new IndexTarget(indexedColumn.name, IndexTarget.Type.VALUES), "indexe1", - IndexMetadata.IndexType.CUSTOM, + IndexMetadata.Kind.CUSTOM, indexOptions))); return cfm; } @@ -410,9 +411,11 @@ public class SchemaLoader if (withIndex) cfm.indexes( cfm.getIndexes() - .with(IndexMetadata.singleColumnIndex(cfm.getColumnDefinition(new ColumnIdentifier("birthdate", true)), + .with(IndexMetadata.singleTargetIndex(cfm, + new IndexTarget(new ColumnIdentifier("birthdate", true), + IndexTarget.Type.VALUES), "birthdate_key_index", - IndexMetadata.IndexType.COMPOSITES, + IndexMetadata.Kind.COMPOSITES, Collections.EMPTY_MAP))); return cfm.compression(getCompressionParameters()); @@ -430,9 +433,11 @@ public class SchemaLoader if (withIndex) cfm.indexes( cfm.getIndexes() - .with(IndexMetadata.singleColumnIndex(cfm.getColumnDefinition(new ColumnIdentifier("birthdate", true)), + .with(IndexMetadata.singleTargetIndex(cfm, + new IndexTarget(new ColumnIdentifier("birthdate", true), + IndexTarget.Type.VALUES), "birthdate_composite_index", - IndexMetadata.IndexType.KEYS, + IndexMetadata.Kind.KEYS, Collections.EMPTY_MAP))); diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java index e07e421cc2..70f7f19ac9 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java @@ -601,8 +601,10 @@ public class FrozenCollectionsTest extends CQLTester // for now, we don't support indexing values or keys of collections in the primary key assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (full(a))", "Cannot create secondary index on partition key column"); - assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (keys(a))", "Cannot create index on keys of frozen column"); - assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (keys(b))", "Cannot create index on keys of frozen column"); + assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (keys(a))", "Cannot create keys() index on frozen column a. " + + "Frozen collections only support full() indexes"); + assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (keys(b))", "Cannot create keys() index on frozen column b. " + + "Frozen collections only support full() indexes"); createTable("CREATE TABLE %s (a int, b frozen>, c frozen>, d frozen>, PRIMARY KEY (a, b))"); 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 02b2abd939..48d3a852c9 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java @@ -27,15 +27,19 @@ import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.cql3.CQLTester; import org.apache.cassandra.cql3.ColumnIdentifier; +import org.apache.cassandra.cql3.statements.IndexTarget; import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.db.rows.Row; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.exceptions.SyntaxException; +import org.apache.cassandra.index.SecondaryIndexManager; import org.apache.cassandra.index.StubIndex; +import org.apache.cassandra.schema.IndexMetadata; import static org.apache.cassandra.Util.throwAssert; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -209,7 +213,7 @@ public class SecondaryIndexTest extends CQLTester assertInvalidThrow(SyntaxException.class, String.format("CREATE TABLE %s (key varchar PRIMARY KEY, password varchar, gender varchar) WITH compression_parameters:sstable_compressor = 'DeflateCompressor'", tableName)); assertInvalidThrow(ConfigurationException.class, String.format("CREATE TABLE %s (key varchar PRIMARY KEY, password varchar, gender varchar) WITH compression = { 'sstable_compressor': 'DeflateCompressor' }", - tableName)); + tableName)); } /** @@ -462,6 +466,67 @@ public class SecondaryIndexTest extends CQLTester assertRows(execute("select count(*) from %s where app_name='foo' and account='bar' and last_access > 4 allow filtering"), row(1L)); } + @Test + public void testSyntaxVariationsForIndexOnCollectionsValue() throws Throwable + { + createTable("CREATE TABLE %s (k int, m map, l list, s set, PRIMARY KEY (k))"); + createAndDropCollectionValuesIndex("m"); + createAndDropCollectionValuesIndex("l"); + createAndDropCollectionValuesIndex("s"); + } + + private void createAndDropCollectionValuesIndex(String columnName) throws Throwable + { + String indexName = columnName + "_idx"; + SecondaryIndexManager indexManager = getCurrentColumnFamilyStore().indexManager; + createIndex(String.format("CREATE INDEX %s on %%s(%s)", indexName, columnName)); + IndexMetadata indexDef = indexManager.getIndexByName(indexName).getIndexMetadata(); + assertEquals(String.format("values(%s)", columnName), indexDef.options.get(IndexTarget.TARGET_OPTION_NAME)); + dropIndex(String.format("DROP INDEX %s.%s", KEYSPACE, indexName)); + assertFalse(indexManager.hasIndexes()); + createIndex(String.format("CREATE INDEX %s on %%s(values(%s))", indexName, columnName)); + assertEquals(indexDef, indexManager.getIndexByName(indexName).getIndexMetadata()); + dropIndex(String.format("DROP INDEX %s.%s", KEYSPACE, indexName)); + } + + @Test + public void testCreateIndexWithQuotedColumnNames() throws Throwable + { + createTable("CREATE TABLE %s (" + + " k int," + + " v int, " + + " lower_case_map map," + + " \"MixedCaseMap\" map," + + " lower_case_frozen_list frozen>," + + " \"UPPER_CASE_FROZEN_LIST\" frozen>," + + " \"set name with spaces\" set," + + " \"column_name_with\"\"escaped quote\" int," + + " PRIMARY KEY (k))"); + + createAndDropIndexWithQuotedColumnIdentifier("\"v\""); + createAndDropIndexWithQuotedColumnIdentifier("keys(\"lower_case_map\")"); + createAndDropIndexWithQuotedColumnIdentifier("keys(\"MixedCaseMap\")"); + createAndDropIndexWithQuotedColumnIdentifier("full(\"lower_case_frozen_list\")"); + createAndDropIndexWithQuotedColumnIdentifier("full(\"UPPER_CASE_FROZEN_LIST\")"); + createAndDropIndexWithQuotedColumnIdentifier("values(\"set name with spaces\")"); + createAndDropIndexWithQuotedColumnIdentifier("\"column_name_with\"\"escaped quote\""); + } + + private void createAndDropIndexWithQuotedColumnIdentifier(String target) throws Throwable + { + String indexName = "test_mixed_case_idx"; + createIndex(String.format("CREATE INDEX %s ON %%s(%s)", indexName, target)); + SecondaryIndexManager indexManager = getCurrentColumnFamilyStore().indexManager; + IndexMetadata indexDef = indexManager.getIndexByName(indexName).getIndexMetadata(); + dropIndex(String.format("DROP INDEX %s.%s", KEYSPACE, indexName)); + // verify we can re-create the index using the target string + createIndex(String.format("CREATE INDEX %s ON %%s(%s)", + indexName, indexDef.options.get(IndexTarget.TARGET_OPTION_NAME))); + assertEquals(indexDef, indexManager.getIndexByName(indexName).getIndexMetadata()); + dropIndex(String.format("DROP INDEX %s.%s", KEYSPACE, indexName)); + } + + /** * Test for CASSANDRA-5732, Can not query secondary index * migrated from cql_tests.py:TestCQL.bug_5732_test(), diff --git a/test/unit/org/apache/cassandra/db/CleanupTest.java b/test/unit/org/apache/cassandra/db/CleanupTest.java index 7b03640613..a4aca7f3c4 100644 --- a/test/unit/org/apache/cassandra/db/CleanupTest.java +++ b/test/unit/org/apache/cassandra/db/CleanupTest.java @@ -114,9 +114,7 @@ public class CleanupTest assertEquals(LOOPS, Util.getAll(Util.cmd(cfs).build()).size()); ColumnDefinition cdef = cfs.metadata.getColumnDefinition(COLUMN); - String indexName = cfs.metadata.getIndexes() - .get(cdef) - .iterator().next().name; + String indexName = "birthdate_key_index"; long start = System.nanoTime(); while (!cfs.getBuiltIndexes().contains(indexName) && System.nanoTime() - start < TimeUnit.SECONDS.toNanos(10)) Thread.sleep(10); diff --git a/test/unit/org/apache/cassandra/db/DirectoriesTest.java b/test/unit/org/apache/cassandra/db/DirectoriesTest.java index 40093eacd4..6e514481be 100644 --- a/test/unit/org/apache/cassandra/db/DirectoriesTest.java +++ b/test/unit/org/apache/cassandra/db/DirectoriesTest.java @@ -34,6 +34,7 @@ import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.config.Config.DiskFailurePolicy; import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.cql3.statements.IndexTarget; import org.apache.cassandra.db.Directories.DataDirectory; import org.apache.cassandra.db.marshal.UTF8Type; import org.apache.cassandra.index.internal.CassandraIndex; @@ -168,9 +169,10 @@ public class DirectoriesTest .addClusteringColumn("col", UTF8Type.instance) .build(); ColumnDefinition col = PARENT_CFM.getColumnDefinition(ByteBufferUtil.bytes("col")); - IndexMetadata indexDef = IndexMetadata.singleColumnIndex(col, + IndexMetadata indexDef = IndexMetadata.singleTargetIndex(PARENT_CFM, + new IndexTarget(col.name, IndexTarget.Type.VALUES), "idx", - IndexMetadata.IndexType.KEYS, + IndexMetadata.Kind.KEYS, Collections.emptyMap()); PARENT_CFM.indexes(PARENT_CFM.getIndexes().with(indexDef)); CFMetaData INDEX_CFM = CassandraIndex.indexCfsMetadata(PARENT_CFM, indexDef); diff --git a/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java b/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java index ffc43c504d..e0fc68a56f 100644 --- a/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java +++ b/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java @@ -464,9 +464,10 @@ public class RangeTombstoneTest cfs.disableAutoCompaction(); ColumnDefinition cd = cfs.metadata.getColumnDefinition(indexedColumnName).copy(); - IndexMetadata indexDef = IndexMetadata.singleColumnIndex(cd, + IndexMetadata indexDef = IndexMetadata.singleTargetIndex(cfs.metadata, + new IndexTarget(cd.name, IndexTarget.Type.VALUES), "test_index", - IndexMetadata.IndexType.CUSTOM, + IndexMetadata.Kind.CUSTOM, ImmutableMap.of(IndexTarget.CUSTOM_INDEX_OPTION_NAME, StubIndex.class.getName())); @@ -560,9 +561,10 @@ public class RangeTombstoneTest cfs.disableAutoCompaction(); ColumnDefinition cd = cfs.metadata.getColumnDefinition(indexedColumnName).copy(); - IndexMetadata indexDef = IndexMetadata.singleColumnIndex(cd, + IndexMetadata indexDef = IndexMetadata.singleTargetIndex(cfs.metadata, + new IndexTarget(cd.name,IndexTarget.Type.VALUES), "test_index", - IndexMetadata.IndexType.CUSTOM, + IndexMetadata.Kind.CUSTOM, ImmutableMap.of(IndexTarget.CUSTOM_INDEX_OPTION_NAME, StubIndex.class.getName())); @@ -574,11 +576,7 @@ public class RangeTombstoneTest if (rebuild != null) rebuild.get(); - StubIndex index = (StubIndex)cfs.indexManager.listIndexes() - .stream() - .filter(i -> "test_index".equals(i.getIndexName())) - .findFirst() - .orElseThrow(() -> new RuntimeException(new AssertionError("Index not found"))); + StubIndex index = (StubIndex)cfs.indexManager.getIndexByName("test_index"); index.reset(); UpdateBuilder.create(cfs.metadata, key).withTimestamp(0).newRow(1).add("val", 1).applyUnsafe(); diff --git a/test/unit/org/apache/cassandra/db/SecondaryIndexTest.java b/test/unit/org/apache/cassandra/db/SecondaryIndexTest.java index 0003f8f802..2a43e333cf 100644 --- a/test/unit/org/apache/cassandra/db/SecondaryIndexTest.java +++ b/test/unit/org/apache/cassandra/db/SecondaryIndexTest.java @@ -29,12 +29,11 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.apache.cassandra.index.SecondaryIndexManager; - import org.apache.cassandra.SchemaLoader; import org.apache.cassandra.Util; import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.cql3.Operator; +import org.apache.cassandra.cql3.statements.IndexTarget; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.db.partitions.*; import org.apache.cassandra.db.rows.Row; @@ -44,6 +43,8 @@ import org.apache.cassandra.schema.IndexMetadata; import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.FBUtilities; + +import static org.apache.cassandra.Util.throwAssert; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -63,8 +64,8 @@ public class SecondaryIndexTest SchemaLoader.prepareServer(); SchemaLoader.createKeyspace(KEYSPACE1, KeyspaceParams.simple(1), - SchemaLoader.compositeIndexCFMD(KEYSPACE1, WITH_COMPOSITE_INDEX, true) .gcGraceSeconds(0), - SchemaLoader.compositeIndexCFMD(KEYSPACE1, COMPOSITE_INDEX_TO_BE_ADDED, false) .gcGraceSeconds(0), + SchemaLoader.compositeIndexCFMD(KEYSPACE1, WITH_COMPOSITE_INDEX, true).gcGraceSeconds(0), + SchemaLoader.compositeIndexCFMD(KEYSPACE1, COMPOSITE_INDEX_TO_BE_ADDED, false).gcGraceSeconds(0), SchemaLoader.keysIndexCFMD(KEYSPACE1, WITH_KEYS_INDEX, true).gcGraceSeconds(0)); } @@ -435,10 +436,12 @@ public class SecondaryIndexTest // create a row and update the birthdate value, test that the index query fetches the new version new RowUpdateBuilder(cfs.metadata, 0, "k1").clustering("c").add("birthdate", 1L).build().applyUnsafe(); + String indexName = "birthdate_index"; ColumnDefinition old = cfs.metadata.getColumnDefinition(ByteBufferUtil.bytes("birthdate")); - IndexMetadata indexDef = IndexMetadata.singleColumnIndex(old, - "birthdate_index", - IndexMetadata.IndexType.COMPOSITES, + IndexMetadata indexDef = IndexMetadata.singleTargetIndex(cfs.metadata, + new IndexTarget(old.name, IndexTarget.Type.VALUES), + indexName, + IndexMetadata.Kind.COMPOSITES, Collections.EMPTY_MAP); cfs.metadata.indexes(cfs.metadata.getIndexes().with(indexDef)); Future future = cfs.indexManager.addIndex(indexDef); @@ -446,15 +449,11 @@ public class SecondaryIndexTest // we had a bug (CASSANDRA-2244) where index would get created but not flushed -- check for that // the way we find the index cfs is a bit convoluted at the moment - ColumnDefinition cDef = cfs.metadata.getColumnDefinition(ByteBufferUtil.bytes("birthdate")); - String indexName = getIndexNameForColumn(cfs, cDef); - assertNotNull(indexName); boolean flushed = false; - for (ColumnFamilyStore indexCfs : cfs.indexManager.getAllIndexColumnFamilyStores()) - { - if (SecondaryIndexManager.getIndexName(indexCfs).equals(indexName)) - flushed = indexCfs.getLiveSSTables().size() > 0; - } + ColumnFamilyStore indexCfs = cfs.indexManager.getIndex(indexDef) + .getBackingTable() + .orElseThrow(throwAssert("Index not found")); + flushed = !indexCfs.getLiveSSTables().isEmpty(); assertTrue(flushed); assertIndexedOne(cfs, ByteBufferUtil.bytes("birthdate"), 1L); @@ -469,18 +468,6 @@ public class SecondaryIndexTest assertIndexedOne(cfs, ByteBufferUtil.bytes("birthdate"), 1L); } - private String getIndexNameForColumn(ColumnFamilyStore cfs, ColumnDefinition column) - { - // this is mega-ugly because there is a mismatch between the name of an index - // stored in schema metadata & the name used to refer to that index in other - // places (such as system.IndexInfo). Hopefully this is temporary and - // Index.getIndexName() can be made equalivalent to Index.getIndexMetadata().name - // (ideally even removing the former completely) - Collection indexes = cfs.metadata.getIndexes().get(column); - assertEquals(1, indexes.size()); - return cfs.indexManager.getIndex(indexes.iterator().next()).getIndexName(); - } - @Test public void testKeysSearcherSimple() throws Exception { diff --git a/test/unit/org/apache/cassandra/index/StubIndex.java b/test/unit/org/apache/cassandra/index/StubIndex.java index 0ea03dc210..544d482e08 100644 --- a/test/unit/org/apache/cassandra/index/StubIndex.java +++ b/test/unit/org/apache/cassandra/index/StubIndex.java @@ -23,7 +23,6 @@ import java.util.concurrent.Callable; import java.util.function.BiFunction; import org.apache.cassandra.config.ColumnDefinition; -import org.apache.cassandra.cql3.ColumnIdentifier; import org.apache.cassandra.cql3.Operator; import org.apache.cassandra.db.*; import org.apache.cassandra.db.filter.RowFilter; @@ -70,6 +69,11 @@ public class StubIndex implements Index return false; } + public boolean dependsOn(ColumnDefinition column) + { + return false; + } + public boolean supportsExpression(ColumnDefinition column, Operator operator) { return operator == Operator.EQ; diff --git a/test/unit/org/apache/cassandra/index/internal/CustomCassandraIndex.java b/test/unit/org/apache/cassandra/index/internal/CustomCassandraIndex.java index 0a62d9b8b6..86950181c8 100644 --- a/test/unit/org/apache/cassandra/index/internal/CustomCassandraIndex.java +++ b/test/unit/org/apache/cassandra/index/internal/CustomCassandraIndex.java @@ -20,27 +20,27 @@ import org.apache.cassandra.db.compaction.CompactionManager; import org.apache.cassandra.db.filter.RowFilter; import org.apache.cassandra.db.lifecycle.SSTableSet; import org.apache.cassandra.db.lifecycle.View; -import org.apache.cassandra.db.marshal.AbstractType; -import org.apache.cassandra.db.marshal.CollectionType; import org.apache.cassandra.db.partitions.PartitionIterator; import org.apache.cassandra.db.partitions.PartitionUpdate; import org.apache.cassandra.db.rows.*; -import org.apache.cassandra.dht.LocalPartitioner; import org.apache.cassandra.exceptions.InvalidRequestException; import org.apache.cassandra.index.Index; import org.apache.cassandra.index.IndexRegistry; import org.apache.cassandra.index.SecondaryIndexBuilder; -import org.apache.cassandra.index.internal.composites.CompositesSearcher; -import org.apache.cassandra.index.internal.keys.KeysSearcher; import org.apache.cassandra.index.transactions.IndexTransaction; import org.apache.cassandra.index.transactions.UpdateTransaction; import org.apache.cassandra.io.sstable.ReducingKeyIterator; import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.schema.IndexMetadata; import org.apache.cassandra.utils.FBUtilities; +import org.apache.cassandra.utils.Pair; import org.apache.cassandra.utils.concurrent.OpOrder; import org.apache.cassandra.utils.concurrent.Refs; +import static org.apache.cassandra.index.internal.CassandraIndex.getFunctions; +import static org.apache.cassandra.index.internal.CassandraIndex.indexCfsMetadata; +import static org.apache.cassandra.index.internal.CassandraIndex.parseTarget; + /** * Clone of KeysIndex used in CassandraIndexTest#testCustomIndexWithCFS to verify * behaviour of flushing CFS backed CUSTOM indexes @@ -145,14 +145,14 @@ public class CustomCassandraIndex implements Index private void setMetadata(IndexMetadata indexDef) { metadata = indexDef; - functions = getFunctions(baseCfs.metadata, indexDef); + Pair target = parseTarget(baseCfs.metadata, indexDef); + functions = getFunctions(indexDef, target); CFMetaData cfm = indexCfsMetadata(baseCfs.metadata, indexDef); indexCfs = ColumnFamilyStore.createColumnFamilyStore(baseCfs.keyspace, cfm.cfName, cfm, baseCfs.getTracker().loadsstables); - assert indexDef.columns.size() == 1 : "Build in indexes on multiple target columns are not supported"; - indexedColumn = indexDef.indexedColumn(baseCfs.metadata); + indexedColumn = target.left; } public Callable getTruncateTask(final long truncatedAt) @@ -174,6 +174,11 @@ public class CustomCassandraIndex implements Index return isPrimaryKeyIndex() || columns.contains(indexedColumn); } + public boolean dependsOn(ColumnDefinition column) + { + return column.equals(indexedColumn); + } + public boolean supportsExpression(ColumnDefinition column, Operator operator) { return indexedColumn.name.equals(column.name) @@ -668,76 +673,4 @@ public class CustomCassandraIndex implements Index .map(SSTableReader::toString) .collect(Collectors.joining(", ")); } - - /** - * Construct the CFMetadata for an index table, the clustering columns in the index table - * vary dependent on the kind of the indexed value. - * @param baseCfsMetadata - * @param indexMetadata - * @return - */ - public static final CFMetaData indexCfsMetadata(CFMetaData baseCfsMetadata, IndexMetadata indexMetadata) - { - CassandraIndexFunctions utils = getFunctions(baseCfsMetadata, indexMetadata); - ColumnDefinition indexedColumn = indexMetadata.indexedColumn(baseCfsMetadata); - AbstractType indexedValueType = utils.getIndexedValueType(indexedColumn); - CFMetaData.Builder builder = CFMetaData.Builder.create(baseCfsMetadata.ksName, - baseCfsMetadata.indexColumnFamilyName(indexMetadata)) - .withId(baseCfsMetadata.cfId) - .withPartitioner(new LocalPartitioner(indexedValueType)) - .addPartitionKey(indexedColumn.name, indexedColumn.type); - - builder.addClusteringColumn("partition_key", baseCfsMetadata.partitioner.partitionOrdering()); - builder = utils.addIndexClusteringColumns(builder, baseCfsMetadata, indexedColumn); - return builder.build().reloadIndexMetadataProperties(baseCfsMetadata); - } - - /** - * Factory method for new CassandraIndex instances - * @param baseCfs - * @param indexMetadata - * @return - */ - public static final CassandraIndex newIndex(ColumnFamilyStore baseCfs, IndexMetadata indexMetadata) - { - return getFunctions(baseCfs.metadata, indexMetadata).newIndexInstance(baseCfs, indexMetadata); - } - - private static CassandraIndexFunctions getFunctions(CFMetaData baseCfMetadata, IndexMetadata indexDef) - { - if (indexDef.isKeys()) - return CassandraIndexFunctions.KEYS_INDEX_FUNCTIONS; - - ColumnDefinition indexedColumn = indexDef.indexedColumn(baseCfMetadata); - if (indexedColumn.type.isCollection() && indexedColumn.type.isMultiCell()) - { - switch (((CollectionType)indexedColumn.type).kind) - { - case LIST: - return CassandraIndexFunctions.COLLECTION_VALUE_INDEX_FUNCTIONS; - case SET: - return CassandraIndexFunctions.COLLECTION_KEY_INDEX_FUNCTIONS; - case MAP: - if (indexDef.options.containsKey(IndexTarget.INDEX_KEYS_OPTION_NAME)) - return CassandraIndexFunctions.COLLECTION_KEY_INDEX_FUNCTIONS; - else if (indexDef.options.containsKey(IndexTarget.INDEX_ENTRIES_OPTION_NAME)) - return CassandraIndexFunctions.COLLECTION_ENTRY_INDEX_FUNCTIONS; - else - return CassandraIndexFunctions.COLLECTION_VALUE_INDEX_FUNCTIONS; - } - } - - switch (indexedColumn.kind) - { - case CLUSTERING: - return CassandraIndexFunctions.CLUSTERING_COLUMN_INDEX_FUNCTIONS; - case REGULAR: - return CassandraIndexFunctions.REGULAR_COLUMN_INDEX_FUNCTIONS; - case PARTITION_KEY: - return CassandraIndexFunctions.PARTITION_KEY_INDEX_FUNCTIONS; - //case COMPACT_VALUE: - // return new CompositesIndexOnCompactValue(); - } - throw new AssertionError(); - } } diff --git a/test/unit/org/apache/cassandra/schema/DefsTest.java b/test/unit/org/apache/cassandra/schema/DefsTest.java index ee73b2b6b6..f348c30f86 100644 --- a/test/unit/org/apache/cassandra/schema/DefsTest.java +++ b/test/unit/org/apache/cassandra/schema/DefsTest.java @@ -44,14 +44,13 @@ import org.apache.cassandra.db.lifecycle.LifecycleTransaction; import org.apache.cassandra.db.marshal.BytesType; import org.apache.cassandra.db.marshal.UTF8Type; import org.apache.cassandra.exceptions.ConfigurationException; -import org.apache.cassandra.index.Index; import org.apache.cassandra.io.sstable.Component; import org.apache.cassandra.io.sstable.Descriptor; import org.apache.cassandra.locator.OldNetworkTopologyStrategy; import org.apache.cassandra.service.MigrationManager; -import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.FBUtilities; +import static org.apache.cassandra.Util.throwAssert; import static org.apache.cassandra.cql3.CQLTester.assertRows; import static org.apache.cassandra.cql3.CQLTester.row; import static org.junit.Assert.assertEquals; @@ -501,6 +500,7 @@ public class DefsTest // persist keyspace definition in the system keyspace SchemaKeyspace.makeCreateKeyspaceMutation(Schema.instance.getKSMetaData(KEYSPACE6), FBUtilities.timestampMicros()).applyUnsafe(); ColumnFamilyStore cfs = Keyspace.open(KEYSPACE6).getColumnFamilyStore(TABLE1i); + String indexName = "birthdate_key_index"; // insert some data. save the sstable descriptor so we can make sure it's marked for delete after the drop QueryProcessor.executeInternal(String.format( @@ -510,37 +510,17 @@ public class DefsTest "key0", "col0", 1L, 1L); cfs.forceBlockingFlush(); - ColumnDefinition indexedColumn = cfs.metadata.getColumnDefinition(ByteBufferUtil.bytes("birthdate")); - IndexMetadata index = cfs.metadata.getIndexes() - .get(indexedColumn) - .iterator() - .next(); - ColumnFamilyStore indexCfs = cfs.indexManager.listIndexes() - .stream() - .filter(i -> i.getIndexMetadata().equals(index)) - .map(Index::getBackingTable) - .findFirst() - .orElseThrow(() -> new AssertionError("Index not found")) - .orElseThrow(() -> new AssertionError("Index has no backing table")); + ColumnFamilyStore indexCfs = cfs.indexManager.getIndexByName(indexName) + .getBackingTable() + .orElseThrow(throwAssert("Cannot access index cfs")); Descriptor desc = indexCfs.getLiveSSTables().iterator().next().descriptor; // drop the index CFMetaData meta = cfs.metadata.copy(); - // We currently have a mismatch between IndexMetadata.name (which is simply the name - // of the index) and what gets returned from SecondaryIndex#getIndexName() (usually, this - // defaults to .. - // IndexMetadata takes its lead from the prior implementation of ColumnDefinition.name - // which did not include the table name. - // This mismatch causes some other, long standing inconsistencies: - // nodetool rebuild_index - must be qualified, i.e. include the redundant table name - // without it, the rebuild silently fails - // system.IndexInfo (which is also exposed over JMX as CF.BuildIndexes) uses the form . - // cqlsh> describe index [.] - here must not be qualified by the table name. - // - // This should get resolved as part of #9459 by better separating the index name from the - // name of it's underlying CFS (if it as one), as the comment in CFMetaData#indexColumnFamilyName promises - // Then we will be able to just use the value of SI#getIndexName() when removing an index from CFMetaData - IndexMetadata existing = meta.getIndexes().iterator().next(); + IndexMetadata existing = cfs.metadata.getIndexes() + .get(indexName) + .orElseThrow(throwAssert("Index not found")); + meta.indexes(meta.getIndexes().without(existing.name)); MigrationManager.announceColumnFamilyUpdate(meta, false); diff --git a/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java index d841e919ef..7124e40670 100644 --- a/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java +++ b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java @@ -34,6 +34,7 @@ import org.apache.cassandra.cql3.ColumnIdentifier; import org.apache.cassandra.cql3.functions.*; import org.apache.cassandra.db.*; import org.apache.cassandra.db.marshal.*; +import org.apache.cassandra.index.internal.CassandraIndex; import org.apache.cassandra.thrift.ThriftConversion; import static java.lang.String.format; @@ -490,7 +491,7 @@ public class LegacySchemaMigratorTest { IndexMetadata i = index.get(); adder.add("index_name", i.name); - adder.add("index_type", i.indexType.toString()); + adder.add("index_type", i.kind.toString()); adder.add("index_options", json(i.options)); } else @@ -504,11 +505,14 @@ public class LegacySchemaMigratorTest } private static Optional findIndexForColumn(Indexes indexes, - CFMetaData table, - ColumnDefinition column) + CFMetaData table, + ColumnDefinition column) { + // makes the assumptions that the string option denoting the + // index targets can be parsed by CassandraIndex.parseTarget + // which should be true for any pre-3.0 index for (IndexMetadata index : indexes) - if (index.indexedColumn(table).equals(column)) + if (CassandraIndex.parseTarget(table, index).left.equals(column)) return Optional.of(index); return Optional.empty();