use of org.apache.cassandra.transport.Event.SchemaChange.Target in project cassandra by apache.
the class CreateIndexStatement method apply.
public Keyspaces apply(Keyspaces schema) {
attrs.validate();
if (attrs.isCustom && attrs.customClass.equals(SASIIndex.class.getName()) && !DatabaseDescriptor.getSASIIndexesEnabled())
throw new InvalidRequestException("SASI indexes are disabled. Enable in cassandra.yaml to use.");
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
TableMetadata table = keyspace.getTableOrViewNullable(tableName);
if (null == table)
throw ire("Table '%s' doesn't exist", tableName);
if (null != indexName && keyspace.hasIndex(indexName)) {
if (ifNotExists)
return schema;
throw ire("Index '%s' already exists", indexName);
}
if (table.isCounter())
throw ire("Secondary indexes on counter tables aren't supported");
if (table.isView())
throw ire("Secondary indexes on materialized views aren't supported");
if (Keyspace.open(table.keyspace).getReplicationStrategy().hasTransientReplicas())
throw new InvalidRequestException("Secondary indexes are not supported on transiently replicated keyspaces");
// guardrails to limit number of secondary indexes per table.
Guardrails.secondaryIndexesPerTable.guard(table.indexes.size() + 1, Strings.isNullOrEmpty(indexName) ? String.format("on table %s", table.name) : String.format("%s on table %s", indexName, table.name), state);
List<IndexTarget> indexTargets = Lists.newArrayList(transform(rawIndexTargets, t -> t.prepare(table)));
if (indexTargets.isEmpty() && !attrs.isCustom)
throw ire("Only CUSTOM indexes can be created without specifying a target column");
if (indexTargets.size() > 1) {
if (!attrs.isCustom)
throw ire("Only CUSTOM indexes support multiple columns");
Set<ColumnIdentifier> columns = new HashSet<>();
for (IndexTarget target : indexTargets) if (!columns.add(target.column))
throw ire("Duplicate column '%s' in index target list", target.column);
}
indexTargets.forEach(t -> validateIndexTarget(table, t));
String name = null == indexName ? generateIndexName(keyspace, indexTargets) : indexName;
IndexMetadata.Kind kind = attrs.isCustom ? IndexMetadata.Kind.CUSTOM : IndexMetadata.Kind.COMPOSITES;
Map<String, String> options = attrs.isCustom ? attrs.getOptions() : Collections.emptyMap();
IndexMetadata index = IndexMetadata.fromIndexTargets(indexTargets, name, kind, options);
// check to disallow creation of an index which duplicates an existing one in all but name
IndexMetadata equalIndex = tryFind(table.indexes, i -> i.equalsWithoutName(index)).orNull();
if (null != equalIndex) {
if (ifNotExists)
return schema;
throw ire("Index %s is a duplicate of existing index %s", index.name, equalIndex.name);
}
TableMetadata newTable = table.withSwapped(table.indexes.with(index));
newTable.validate();
return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.tables.withSwapped(newTable)));
}
Aggregations