Search in sources :

Example 1 with IndexMetadata

use of org.apache.cassandra.schema.IndexMetadata in project cassandra by apache.

the class AlterTableStatement method announceMigration.

public Event.SchemaChange announceMigration(QueryState queryState, boolean isLocalOnly) throws RequestValidationException {
    TableMetadata current = Schema.instance.validateTable(keyspace(), columnFamily());
    if (current.isView())
        throw new InvalidRequestException("Cannot use ALTER TABLE on Materialized View");
    TableMetadata.Builder builder = current.unbuild();
    ColumnIdentifier columnName = null;
    ColumnMetadata def = null;
    CQL3Type.Raw dataType = null;
    boolean isStatic = false;
    CQL3Type validator = null;
    List<ViewMetadata> viewUpdates = new ArrayList<>();
    Iterable<ViewMetadata> views = View.findAll(keyspace(), columnFamily());
    switch(oType) {
        case ALTER:
            throw new InvalidRequestException("Altering of types is not allowed");
        case ADD:
            if (current.isDense())
                throw new InvalidRequestException("Cannot add new column to a COMPACT STORAGE table");
            for (AlterTableStatementColumn colData : colNameList) {
                columnName = colData.getColumnName().getIdentifier(current);
                def = builder.getColumn(columnName);
                dataType = colData.getColumnType();
                assert dataType != null;
                isStatic = colData.getStaticType();
                validator = dataType.prepare(keyspace());
                if (isStatic) {
                    if (!current.isCompound())
                        throw new InvalidRequestException("Static columns are not allowed in COMPACT STORAGE tables");
                    if (current.clusteringColumns().isEmpty())
                        throw new InvalidRequestException("Static columns are only useful (and thus allowed) if the table has at least one clustering column");
                }
                if (def != null) {
                    switch(def.kind) {
                        case PARTITION_KEY:
                        case CLUSTERING:
                            throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with a PRIMARY KEY part", columnName));
                        default:
                            throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with an existing column", columnName));
                    }
                }
                // Cannot re-add a dropped counter column. See #7831.
                if (current.isCounter() && current.getDroppedColumn(columnName.bytes) != null)
                    throw new InvalidRequestException(String.format("Cannot re-add previously dropped counter column %s", columnName));
                AbstractType<?> type = validator.getType();
                if (type.isCollection() && type.isMultiCell()) {
                    if (!current.isCompound())
                        throw new InvalidRequestException("Cannot use non-frozen collections in COMPACT STORAGE tables");
                    if (current.isSuper())
                        throw new InvalidRequestException("Cannot use non-frozen collections with super column families");
                    // If there used to be a non-frozen collection column with the same name (that has been dropped),
                    // we could still have some data using the old type, and so we can't allow adding a collection
                    // with the same name unless the types are compatible (see #6276).
                    DroppedColumn dropped = current.droppedColumns.get(columnName.bytes);
                    if (dropped != null && dropped.column.type instanceof CollectionType && dropped.column.type.isMultiCell() && !type.isCompatibleWith(dropped.column.type)) {
                        String message = String.format("Cannot add a collection with the name %s because a collection with the same name" + " and a different type (%s) has already been used in the past", columnName, dropped.column.type.asCQL3Type());
                        throw new InvalidRequestException(message);
                    }
                }
                builder.addColumn(isStatic ? ColumnMetadata.staticColumn(current, columnName.bytes, type) : ColumnMetadata.regularColumn(current, columnName.bytes, type));
                // as well
                if (!isStatic)
                    for (ViewMetadata view : views) if (view.includeAllColumns)
                        viewUpdates.add(view.withAddedRegularColumn(ColumnMetadata.regularColumn(view.metadata, columnName.bytes, type)));
            }
            break;
        case DROP:
            if (!current.isCQLTable())
                throw new InvalidRequestException("Cannot drop columns from a non-CQL3 table");
            for (AlterTableStatementColumn colData : colNameList) {
                columnName = colData.getColumnName().getIdentifier(current);
                def = builder.getColumn(columnName);
                if (def == null)
                    throw new InvalidRequestException(String.format("Column %s was not found in table %s", columnName, columnFamily()));
                switch(def.kind) {
                    case PARTITION_KEY:
                    case CLUSTERING:
                        throw new InvalidRequestException(String.format("Cannot drop PRIMARY KEY part %s", columnName));
                    case REGULAR:
                    case STATIC:
                        builder.removeRegularOrStaticColumn(def.name);
                        builder.recordColumnDrop(def, deleteTimestamp == null ? queryState.getTimestamp() : deleteTimestamp);
                        break;
                }
                // If the dropped column is required by any secondary indexes
                // we reject the operation, as the indexes must be dropped first
                Indexes allIndexes = current.indexes;
                if (!allIndexes.isEmpty()) {
                    ColumnFamilyStore store = Keyspace.openAndGetStore(current);
                    Set<IndexMetadata> 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(","))));
                    }
                }
                // If a column is dropped which is included in a view, we don't allow the drop to take place.
                boolean rejectAlter = false;
                StringBuilder viewNames = new StringBuilder();
                for (ViewMetadata view : views) {
                    if (!view.includes(columnName))
                        continue;
                    if (rejectAlter)
                        viewNames.append(',');
                    rejectAlter = true;
                    viewNames.append(view.name);
                }
                if (rejectAlter)
                    throw new InvalidRequestException(String.format("Cannot drop column %s, depended on by materialized views (%s.{%s})", columnName.toString(), keyspace(), viewNames.toString()));
            }
            break;
        case OPTS:
            if (attrs == null)
                throw new InvalidRequestException("ALTER TABLE WITH invoked, but no parameters found");
            attrs.validate();
            TableParams params = attrs.asAlteredTableParams(current.params);
            if (!Iterables.isEmpty(views) && params.gcGraceSeconds == 0) {
                throw new InvalidRequestException("Cannot alter gc_grace_seconds of the base table of a " + "materialized view to 0, since this value is used to TTL " + "undelivered updates. Setting gc_grace_seconds too low might " + "cause undelivered updates to expire " + "before being replayed.");
            }
            if (current.isCounter() && params.defaultTimeToLive > 0)
                throw new InvalidRequestException("Cannot set default_time_to_live on a table with counters");
            builder.params(params);
            break;
        case RENAME:
            for (Map.Entry<ColumnMetadata.Raw, ColumnMetadata.Raw> entry : renames.entrySet()) {
                ColumnIdentifier from = entry.getKey().getIdentifier(current);
                ColumnIdentifier to = entry.getValue().getIdentifier(current);
                def = current.getColumn(from);
                if (def == null)
                    throw new InvalidRequestException(String.format("Cannot rename unknown column %s in table %s", from, current.name));
                if (current.getColumn(to) != null)
                    throw new InvalidRequestException(String.format("Cannot rename column %s to %s in table %s; another column of that name already exist", from, to, current.name));
                if (!def.isPrimaryKeyColumn())
                    throw new InvalidRequestException(String.format("Cannot rename non PRIMARY KEY part %s", from));
                if (!current.indexes.isEmpty()) {
                    ColumnFamilyStore store = Keyspace.openAndGetStore(current);
                    Set<IndexMetadata> 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(","))));
                }
                builder.renamePrimaryKeyColumn(from, to);
                // If the view includes a renamed column, it must be renamed in the view table and the definition.
                for (ViewMetadata view : views) {
                    if (!view.includes(from))
                        continue;
                    ColumnIdentifier viewFrom = entry.getKey().getIdentifier(view.metadata);
                    ColumnIdentifier viewTo = entry.getValue().getIdentifier(view.metadata);
                    viewUpdates.add(view.renamePrimaryKeyColumn(viewFrom, viewTo));
                }
            }
            break;
    }
    // FIXME: Should really be a single announce for the table and views.
    MigrationManager.announceTableUpdate(builder.build(), isLocalOnly);
    for (ViewMetadata viewUpdate : viewUpdates) MigrationManager.announceViewUpdate(viewUpdate, isLocalOnly);
    return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
}
Also used : DroppedColumn(org.apache.cassandra.schema.DroppedColumn) TableParams(org.apache.cassandra.schema.TableParams) java.util(java.util) Iterables(com.google.common.collect.Iterables) ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) QueryState(org.apache.cassandra.service.QueryState) Permission(org.apache.cassandra.auth.Permission) ClientState(org.apache.cassandra.service.ClientState) AbstractType(org.apache.cassandra.db.marshal.AbstractType) Collectors(java.util.stream.Collectors) ViewMetadata(org.apache.cassandra.schema.ViewMetadata) org.apache.cassandra.cql3(org.apache.cassandra.cql3) Indexes(org.apache.cassandra.schema.Indexes) Schema(org.apache.cassandra.schema.Schema) View(org.apache.cassandra.db.view.View) MigrationManager(org.apache.cassandra.schema.MigrationManager) ColumnFamilyStore(org.apache.cassandra.db.ColumnFamilyStore) org.apache.cassandra.exceptions(org.apache.cassandra.exceptions) TableMetadata(org.apache.cassandra.schema.TableMetadata) Keyspace(org.apache.cassandra.db.Keyspace) CollectionType(org.apache.cassandra.db.marshal.CollectionType) Event(org.apache.cassandra.transport.Event) ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) CollectionType(org.apache.cassandra.db.marshal.CollectionType) DroppedColumn(org.apache.cassandra.schema.DroppedColumn) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) ViewMetadata(org.apache.cassandra.schema.ViewMetadata) TableMetadata(org.apache.cassandra.schema.TableMetadata) TableParams(org.apache.cassandra.schema.TableParams) Indexes(org.apache.cassandra.schema.Indexes) ColumnFamilyStore(org.apache.cassandra.db.ColumnFamilyStore)

Example 2 with IndexMetadata

use of org.apache.cassandra.schema.IndexMetadata in project cassandra by apache.

the class PartitionRangeQueryPager method nextPageReadCommand.

protected ReadCommand nextPageReadCommand(int pageSize) throws RequestExecutionException {
    DataLimits limits;
    DataRange fullRange = ((PartitionRangeReadCommand) command).dataRange();
    DataRange pageRange;
    if (lastReturnedKey == null) {
        pageRange = fullRange;
        limits = command.limits().forPaging(pageSize);
    } else {
        // We want to include the last returned key only if we haven't achieved our per-partition limit, otherwise, don't bother.
        boolean includeLastKey = remainingInPartition() > 0 && lastReturnedRow != null;
        AbstractBounds<PartitionPosition> bounds = makeKeyBounds(lastReturnedKey, includeLastKey);
        if (includeLastKey) {
            pageRange = fullRange.forPaging(bounds, command.metadata().comparator, lastReturnedRow.clustering(command.metadata()), false);
            limits = command.limits().forPaging(pageSize, lastReturnedKey.getKey(), remainingInPartition());
        } else {
            pageRange = fullRange.forSubRange(bounds);
            limits = command.limits().forPaging(pageSize);
        }
    }
    Index index = command.getIndex(Keyspace.openAndGetStore(command.metadata()));
    Optional<IndexMetadata> indexMetadata = index != null ? Optional.of(index.getIndexMetadata()) : Optional.empty();
    return new PartitionRangeReadCommand(command.metadata(), command.nowInSec(), command.columnFilter(), command.rowFilter(), limits, pageRange, indexMetadata);
}
Also used : Index(org.apache.cassandra.index.Index) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) DataLimits(org.apache.cassandra.db.filter.DataLimits)

Example 3 with IndexMetadata

use of org.apache.cassandra.schema.IndexMetadata in project spoon by INRIA.

the class SecondaryIndexManager method reload.

/**
 * Drops and adds new indexes associated with the underlying CF
 */
public void reload() {
    // figure out what needs to be added and dropped.
    Indexes tableIndexes = baseCfs.metadata.getIndexes();
    indexes.keySet().stream().filter(indexName -> !tableIndexes.has(indexName)).forEach(this::removeIndex);
    // some may not have been created here yet, only added to schema
    for (IndexMetadata tableIndex : tableIndexes) addIndex(tableIndex);
}
Also used : java.util(java.util) Iterables(com.google.common.collect.Iterables) MoreExecutors(com.google.common.util.concurrent.MoreExecutors) JMXEnabledThreadPoolExecutor(org.apache.cassandra.concurrent.JMXEnabledThreadPoolExecutor) CompactionManager(org.apache.cassandra.db.compaction.CompactionManager) PartitionUpdate(org.apache.cassandra.db.partitions.PartitionUpdate) SSTableSet(org.apache.cassandra.db.lifecycle.SSTableSet) LoggerFactory(org.slf4j.LoggerFactory) org.apache.cassandra.db(org.apache.cassandra.db) Constructor(java.lang.reflect.Constructor) Function(java.util.function.Function) StringUtils(org.apache.commons.lang3.StringUtils) SSTableReader(org.apache.cassandra.io.sstable.format.SSTableReader) Indexes(org.apache.cassandra.schema.Indexes) org.apache.cassandra.db.rows(org.apache.cassandra.db.rows) OpOrder(org.apache.cassandra.utils.concurrent.OpOrder) Strings(com.google.common.base.Strings) org.apache.cassandra.index.transactions(org.apache.cassandra.index.transactions) IndexTarget(org.apache.cassandra.cql3.statements.IndexTarget) ReducingKeyIterator(org.apache.cassandra.io.sstable.ReducingKeyIterator) Refs(org.apache.cassandra.utils.concurrent.Refs) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) Longs(com.google.common.primitives.Longs) ColumnDefinition(org.apache.cassandra.config.ColumnDefinition) ImmutableSet(com.google.common.collect.ImmutableSet) Logger(org.slf4j.Logger) RowFilter(org.apache.cassandra.db.filter.RowFilter) FBUtilities(org.apache.cassandra.utils.FBUtilities) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) java.util.concurrent(java.util.concurrent) Tracing(org.apache.cassandra.tracing.Tracing) Collectors(java.util.stream.Collectors) Maps(com.google.common.collect.Maps) Futures(com.google.common.util.concurrent.Futures) NamedThreadFactory(org.apache.cassandra.concurrent.NamedThreadFactory) CassandraIndex(org.apache.cassandra.index.internal.CassandraIndex) Stream(java.util.stream.Stream) StageManager(org.apache.cassandra.concurrent.StageManager) Joiner(com.google.common.base.Joiner) View(org.apache.cassandra.db.lifecycle.View) Indexes(org.apache.cassandra.schema.Indexes) IndexMetadata(org.apache.cassandra.schema.IndexMetadata)

Example 4 with IndexMetadata

use of org.apache.cassandra.schema.IndexMetadata 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);
}
Also used : TableMetadata(org.apache.cassandra.schema.TableMetadata) ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) IndexTarget(org.apache.cassandra.cql3.statements.schema.IndexTarget) Future(java.util.concurrent.Future) Index(org.apache.cassandra.index.Index) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) Test(org.junit.Test)

Example 5 with IndexMetadata

use of org.apache.cassandra.schema.IndexMetadata 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());
}
Also used : TableMetadata(org.apache.cassandra.schema.TableMetadata) StubIndex(org.apache.cassandra.index.StubIndex) java.util(java.util) CompactionManager(org.apache.cassandra.db.compaction.CompactionManager) ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) BeforeClass(org.junit.BeforeClass) IndexTarget(org.apache.cassandra.cql3.statements.schema.IndexTarget) ByteBuffer(java.nio.ByteBuffer) Iterators(com.google.common.collect.Iterators) SSTableReader(org.apache.cassandra.io.sstable.format.SSTableReader) org.apache.cassandra.db.rows(org.apache.cassandra.db.rows) Int32Type(org.apache.cassandra.db.marshal.Int32Type) UTF8Type(org.apache.cassandra.db.marshal.UTF8Type) Future(java.util.concurrent.Future) MigrationManager(org.apache.cassandra.schema.MigrationManager) ConfigurationException(org.apache.cassandra.exceptions.ConfigurationException) ColumnFilter(org.apache.cassandra.db.filter.ColumnFilter) UpdateBuilder(org.apache.cassandra.UpdateBuilder) org.apache.cassandra.db.partitions(org.apache.cassandra.db.partitions) SchemaLoader.standardCFMD(org.apache.cassandra.SchemaLoader.standardCFMD) FBUtilities(org.apache.cassandra.utils.FBUtilities) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) ImmutableMap(com.google.common.collect.ImmutableMap) Util(org.apache.cassandra.Util) ByteBufferUtil(org.apache.cassandra.utils.ByteBufferUtil) KeyspaceParams(org.apache.cassandra.schema.KeyspaceParams) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) ExecutionException(java.util.concurrent.ExecutionException) SchemaLoader(org.apache.cassandra.SchemaLoader) Assert.assertFalse(org.junit.Assert.assertFalse) TableMetadata(org.apache.cassandra.schema.TableMetadata) StatsMetadata(org.apache.cassandra.io.sstable.metadata.StatsMetadata) StubIndex(org.apache.cassandra.index.StubIndex) Assert.assertEquals(org.junit.Assert.assertEquals) ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) IndexTarget(org.apache.cassandra.cql3.statements.schema.IndexTarget) UpdateBuilder(org.apache.cassandra.UpdateBuilder) ByteBuffer(java.nio.ByteBuffer) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) Test(org.junit.Test)

Aggregations

IndexMetadata (org.apache.cassandra.schema.IndexMetadata)13 IndexTarget (org.apache.cassandra.cql3.statements.schema.IndexTarget)5 TableMetadata (org.apache.cassandra.schema.TableMetadata)5 java.util (java.util)4 ColumnMetadata (org.apache.cassandra.schema.ColumnMetadata)4 Test (org.junit.Test)4 Collectors (java.util.stream.Collectors)3 CompactionManager (org.apache.cassandra.db.compaction.CompactionManager)3 org.apache.cassandra.db.rows (org.apache.cassandra.db.rows)3 Index (org.apache.cassandra.index.Index)3 SSTableReader (org.apache.cassandra.io.sstable.format.SSTableReader)3 Indexes (org.apache.cassandra.schema.Indexes)3 Joiner (com.google.common.base.Joiner)2 Strings (com.google.common.base.Strings)2 Iterables (com.google.common.collect.Iterables)2 Longs (com.google.common.primitives.Longs)2 Constructor (java.lang.reflect.Constructor)2 ByteBuffer (java.nio.ByteBuffer)2 Future (java.util.concurrent.Future)2 Function (java.util.function.Function)2