use of org.apache.cassandra.cql3.statements.IndexTarget in project cassandra by apache.
the class SchemaLoader method compositeMultipleIndexCFMD.
public static TableMetadata.Builder compositeMultipleIndexCFMD(String ksName, String cfName) throws ConfigurationException {
TableMetadata.Builder builder = TableMetadata.builder(ksName, cfName).addPartitionKeyColumn("key", AsciiType.instance).addClusteringColumn("c1", AsciiType.instance).addRegularColumn("birthdate", LongType.instance).addRegularColumn("notbirthdate", LongType.instance).compression(getCompressionParameters());
Indexes.Builder indexes = Indexes.builder();
indexes.add(IndexMetadata.fromIndexTargets(Collections.singletonList(new IndexTarget(new ColumnIdentifier("birthdate", true), IndexTarget.Type.VALUES)), "birthdate_key_index", IndexMetadata.Kind.COMPOSITES, Collections.EMPTY_MAP));
indexes.add(IndexMetadata.fromIndexTargets(Collections.singletonList(new IndexTarget(new ColumnIdentifier("notbirthdate", true), IndexTarget.Type.VALUES)), "notbirthdate_key_index", IndexMetadata.Kind.COMPOSITES, Collections.EMPTY_MAP));
return builder.indexes(indexes.build());
}
use of org.apache.cassandra.cql3.statements.IndexTarget in project cassandra by apache.
the class SchemaLoader method keysIndexCFMD.
public static TableMetadata.Builder keysIndexCFMD(String ksName, String cfName, boolean withIndex) {
TableMetadata.Builder builder = TableMetadata.builder(ksName, cfName).addPartitionKeyColumn("key", AsciiType.instance).addClusteringColumn("c1", AsciiType.instance).addStaticColumn("birthdate", LongType.instance).addStaticColumn("notbirthdate", LongType.instance).addRegularColumn("value", LongType.instance).compression(getCompressionParameters());
if (withIndex) {
IndexMetadata index = IndexMetadata.fromIndexTargets(Collections.singletonList(new IndexTarget(new ColumnIdentifier("birthdate", true), IndexTarget.Type.VALUES)), cfName + "_birthdate_composite_index", IndexMetadata.Kind.KEYS, Collections.EMPTY_MAP);
builder.indexes(Indexes.builder().add(index).build());
}
return builder;
}
use of org.apache.cassandra.cql3.statements.IndexTarget 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)));
}
use of org.apache.cassandra.cql3.statements.IndexTarget in project cassandra by apache.
the class SecondaryIndexTest method testIndexCreate.
@Test
public void testIndexCreate() throws IOException, InterruptedException, ExecutionException {
Keyspace keyspace = Keyspace.open(KEYSPACE1);
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(COMPOSITE_INDEX_TO_BE_ADDED);
// 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";
ColumnMetadata old = cfs.metadata().getColumn(ByteBufferUtil.bytes("birthdate"));
IndexMetadata indexDef = IndexMetadata.fromIndexTargets(Collections.singletonList(new IndexTarget(old.name, IndexTarget.Type.VALUES)), indexName, IndexMetadata.Kind.COMPOSITES, Collections.EMPTY_MAP);
TableMetadata current = cfs.metadata();
TableMetadata updated = current.unbuild().indexes(current.indexes.with(indexDef)).build();
MigrationManager.announceTableUpdate(updated, true);
// wait for the index to be built
Index index = cfs.indexManager.getIndex(indexDef);
do {
TimeUnit.MILLISECONDS.sleep(100);
} while (!cfs.indexManager.isIndexQueryable(index));
// 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
ColumnFamilyStore indexCfs = cfs.indexManager.getIndex(indexDef).getBackingTable().orElseThrow(throwAssert("Index not found"));
assertFalse(indexCfs.getLiveSSTables().isEmpty());
assertIndexedOne(cfs, ByteBufferUtil.bytes("birthdate"), 1L);
// validate that drop clears it out & rebuild works (CASSANDRA-2320)
assertTrue(cfs.getBuiltIndexes().contains(indexName));
cfs.indexManager.removeIndex(indexDef.name);
assertFalse(cfs.getBuiltIndexes().contains(indexName));
// rebuild & re-query
Future future = cfs.indexManager.addIndex(indexDef, false);
future.get();
assertIndexedOne(cfs, ByteBufferUtil.bytes("birthdate"), 1L);
}
use of org.apache.cassandra.cql3.statements.IndexTarget in project cassandra by apache.
the class RangeTombstoneTest method testRowWithRangeTombstonesUpdatesSecondaryIndex.
@Test
public void testRowWithRangeTombstonesUpdatesSecondaryIndex() throws Exception {
Keyspace table = Keyspace.open(KSNAME);
ColumnFamilyStore cfs = table.getColumnFamilyStore(CFNAME);
ByteBuffer key = ByteBufferUtil.bytes("k5");
ByteBuffer indexedColumnName = ByteBufferUtil.bytes("val");
cfs.truncateBlocking();
cfs.disableAutoCompaction();
ColumnMetadata cd = cfs.metadata().getColumn(indexedColumnName).copy();
IndexMetadata indexDef = IndexMetadata.fromIndexTargets(Collections.singletonList(new IndexTarget(cd.name, IndexTarget.Type.VALUES)), "test_index", IndexMetadata.Kind.CUSTOM, ImmutableMap.of(IndexTarget.CUSTOM_INDEX_OPTION_NAME, StubIndex.class.getName()));
TableMetadata current = cfs.metadata();
if (!current.indexes.get("test_index").isPresent()) {
TableMetadata updated = current.unbuild().indexes(current.indexes.with(indexDef)).build();
MigrationManager.announceTableUpdate(updated, true);
}
Future<?> rebuild = cfs.indexManager.addIndex(indexDef, false);
// If rebuild there is, wait for the rebuild to finish so it doesn't race with the following insertions
if (rebuild != null)
rebuild.get();
StubIndex index = (StubIndex) cfs.indexManager.listIndexes().stream().filter(i -> "test_index".equals(i.getIndexMetadata().name)).findFirst().orElseThrow(() -> new RuntimeException(new AssertionError("Index not found")));
index.reset();
UpdateBuilder builder = UpdateBuilder.create(cfs.metadata(), key).withTimestamp(0);
for (int i = 0; i < 10; i++) builder.newRow(i).add("val", i);
builder.applyUnsafe();
cfs.forceBlockingFlush();
new RowUpdateBuilder(cfs.metadata(), 0, key).addRangeTombstone(0, 7).build().applyUnsafe();
cfs.forceBlockingFlush();
assertEquals(10, index.rowsInserted.size());
CompactionManager.instance.performMaximal(cfs, false);
// compacted down to single sstable
assertEquals(1, cfs.getLiveSSTables().size());
assertEquals(8, index.rowsDeleted.size());
}
Aggregations