Search in sources :

Example 1 with ColumnIdentifier

use of org.apache.cassandra.cql3.ColumnIdentifier in project cassandra by apache.

the class PartitionImplementationTest method makeRow.

Row makeRow(Clustering clustering, String colValue) {
    ColumnMetadata defCol = metadata.getColumn(new ColumnIdentifier("col", true));
    Row.Builder row = BTreeRow.unsortedBuilder(TIMESTAMP);
    row.newRow(clustering);
    row.addCell(BufferCell.live(defCol, TIMESTAMP, ByteBufferUtil.bytes(colValue)));
    return row.build();
}
Also used : ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) ColumnIdentifier(org.apache.cassandra.cql3.ColumnIdentifier)

Example 2 with ColumnIdentifier

use of org.apache.cassandra.cql3.ColumnIdentifier 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 3 with ColumnIdentifier

use of org.apache.cassandra.cql3.ColumnIdentifier 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());
}
Also used : IndexTarget(org.apache.cassandra.cql3.statements.schema.IndexTarget) ColumnIdentifier(org.apache.cassandra.cql3.ColumnIdentifier)

Example 4 with ColumnIdentifier

use of org.apache.cassandra.cql3.ColumnIdentifier 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;
}
Also used : IndexTarget(org.apache.cassandra.cql3.statements.schema.IndexTarget) ColumnIdentifier(org.apache.cassandra.cql3.ColumnIdentifier)

Example 5 with ColumnIdentifier

use of org.apache.cassandra.cql3.ColumnIdentifier 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)));
}
Also used : AuditLogContext(org.apache.cassandra.audit.AuditLogContext) Change(org.apache.cassandra.transport.Event.SchemaChange.Change) java.util(java.util) Iterables.transform(com.google.common.collect.Iterables.transform) Iterables.tryFind(com.google.common.collect.Iterables.tryFind) Permission(org.apache.cassandra.auth.Permission) CQLStatement(org.apache.cassandra.cql3.CQLStatement) QualifiedName(org.apache.cassandra.cql3.QualifiedName) Strings(com.google.common.base.Strings) Guardrails(org.apache.cassandra.db.guardrails.Guardrails) Lists(com.google.common.collect.Lists) KeyspacesDiff(org.apache.cassandra.schema.Keyspaces.KeyspacesDiff) DatabaseDescriptor(org.apache.cassandra.config.DatabaseDescriptor) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) Keyspace(org.apache.cassandra.db.Keyspace) SASIIndex(org.apache.cassandra.index.sasi.SASIIndex) Type(org.apache.cassandra.cql3.statements.schema.IndexTarget.Type) ImmutableSet(com.google.common.collect.ImmutableSet) SchemaChange(org.apache.cassandra.transport.Event.SchemaChange) ClientState(org.apache.cassandra.service.ClientState) AuditLogEntryType(org.apache.cassandra.audit.AuditLogEntryType) MapType(org.apache.cassandra.db.marshal.MapType) ColumnIdentifier(org.apache.cassandra.cql3.ColumnIdentifier) Target(org.apache.cassandra.transport.Event.SchemaChange.Target) org.apache.cassandra.schema(org.apache.cassandra.schema) SASIIndex(org.apache.cassandra.index.sasi.SASIIndex) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) ColumnIdentifier(org.apache.cassandra.cql3.ColumnIdentifier)

Aggregations

ColumnIdentifier (org.apache.cassandra.cql3.ColumnIdentifier)43 ColumnMetadata (org.apache.cassandra.schema.ColumnMetadata)26 Test (org.junit.Test)15 TableMetadata (org.apache.cassandra.schema.TableMetadata)14 Row (org.apache.cassandra.db.rows.Row)10 ByteBuffer (java.nio.ByteBuffer)9 IndexTarget (org.apache.cassandra.cql3.statements.schema.IndexTarget)8 java.util (java.util)4 ArrayList (java.util.ArrayList)4 DatabaseDescriptor (org.apache.cassandra.config.DatabaseDescriptor)4 PartitionIterator (org.apache.cassandra.db.partitions.PartitionIterator)4 PartitionUpdate (org.apache.cassandra.db.partitions.PartitionUpdate)4 RowIterator (org.apache.cassandra.db.rows.RowIterator)4 ClientState (org.apache.cassandra.service.ClientState)4 Iterables (com.google.common.collect.Iterables)3 StatementRestrictions (org.apache.cassandra.cql3.restrictions.StatementRestrictions)3 UnfilteredRowIterator (org.apache.cassandra.db.rows.UnfilteredRowIterator)3 ImmutableSet (com.google.common.collect.ImmutableSet)2 Iterables.transform (com.google.common.collect.Iterables.transform)2 Lists (com.google.common.collect.Lists)2