Search in sources :

Example 1 with CollectionType

use of org.apache.cassandra.db.marshal.CollectionType 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 CollectionType

use of org.apache.cassandra.db.marshal.CollectionType in project cassandra by apache.

the class CollectionEntryIndex method isStale.

public boolean isStale(Row data, ByteBuffer indexValue, int nowInSec) {
    ByteBuffer[] components = ((CompositeType) functions.getIndexedValueType(indexedColumn)).split(indexValue);
    ByteBuffer mapKey = components[0];
    ByteBuffer mapValue = components[1];
    ColumnMetadata columnDef = indexedColumn;
    Cell cell = data.getCell(columnDef, CellPath.create(mapKey));
    if (cell == null || !cell.isLive(nowInSec))
        return true;
    AbstractType<?> valueComparator = ((CollectionType) columnDef.type).valueComparator();
    return valueComparator.compare(mapValue, cell.value()) != 0;
}
Also used : ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) CollectionType(org.apache.cassandra.db.marshal.CollectionType) ByteBuffer(java.nio.ByteBuffer) Cell(org.apache.cassandra.db.rows.Cell) CompositeType(org.apache.cassandra.db.marshal.CompositeType)

Example 3 with CollectionType

use of org.apache.cassandra.db.marshal.CollectionType in project cassandra by apache.

the class JsonTransformer method serializeCell.

private void serializeCell(Cell cell, LivenessInfo liveInfo) {
    try {
        json.writeStartObject();
        objectIndenter.setCompact(true);
        json.writeFieldName("name");
        AbstractType<?> type = cell.column().type;
        json.writeString(cell.column().name.toCQLString());
        if (cell.path() != null && cell.path().size() > 0) {
            CollectionType ct = (CollectionType) type;
            json.writeFieldName("path");
            arrayIndenter.setCompact(true);
            json.writeStartArray();
            for (int i = 0; i < cell.path().size(); i++) {
                json.writeString(ct.nameComparator().getString(cell.path().get(i)));
            }
            json.writeEndArray();
            arrayIndenter.setCompact(false);
        }
        if (cell.isTombstone()) {
            json.writeFieldName("deletion_info");
            objectIndenter.setCompact(true);
            json.writeStartObject();
            json.writeFieldName("local_delete_time");
            json.writeString(dateString(TimeUnit.SECONDS, cell.localDeletionTime()));
            json.writeEndObject();
            objectIndenter.setCompact(false);
        } else {
            json.writeFieldName("value");
            json.writeString(cell.column().cellValueType().getString(cell.value()));
        }
        if (liveInfo.isEmpty() || cell.timestamp() != liveInfo.timestamp()) {
            json.writeFieldName("tstamp");
            json.writeString(dateString(TimeUnit.MICROSECONDS, cell.timestamp()));
        }
        if (cell.isExpiring() && (liveInfo.isEmpty() || cell.ttl() != liveInfo.ttl())) {
            json.writeFieldName("ttl");
            json.writeNumber(cell.ttl());
            json.writeFieldName("expires_at");
            json.writeString(dateString(TimeUnit.SECONDS, cell.localDeletionTime()));
            json.writeFieldName("expired");
            json.writeBoolean(!cell.isLive((int) (System.currentTimeMillis() / 1000)));
        }
        json.writeEndObject();
        objectIndenter.setCompact(false);
    } catch (IOException e) {
        logger.error("Failure parsing cell.", e);
    }
}
Also used : CollectionType(org.apache.cassandra.db.marshal.CollectionType) IOException(java.io.IOException)

Example 4 with CollectionType

use of org.apache.cassandra.db.marshal.CollectionType in project cassandra by apache.

the class AbstractRow method toString.

public String toString(TableMetadata metadata, boolean includeClusterKeys, boolean fullDetails) {
    StringBuilder sb = new StringBuilder();
    sb.append("Row");
    if (fullDetails) {
        sb.append("[info=").append(primaryKeyLivenessInfo());
        if (!deletion().isLive())
            sb.append(" del=").append(deletion());
        sb.append(" ]");
    }
    sb.append(": ");
    if (includeClusterKeys)
        sb.append(clustering().toString(metadata));
    else
        sb.append(clustering().toCQLString(metadata));
    sb.append(" | ");
    boolean isFirst = true;
    for (ColumnData cd : this) {
        if (isFirst)
            isFirst = false;
        else
            sb.append(", ");
        if (fullDetails) {
            if (cd.column().isSimple()) {
                sb.append(cd);
            } else {
                ComplexColumnData complexData = (ComplexColumnData) cd;
                if (!complexData.complexDeletion().isLive())
                    sb.append("del(").append(cd.column().name).append(")=").append(complexData.complexDeletion());
                for (Cell cell : complexData) sb.append(", ").append(cell);
            }
        } else {
            if (cd.column().isSimple()) {
                Cell cell = (Cell) cd;
                sb.append(cell.column().name).append('=');
                if (cell.isTombstone())
                    sb.append("<tombstone>");
                else
                    sb.append(cell.column().type.getString(cell.value()));
            } else {
                sb.append(cd.column().name).append('=');
                ComplexColumnData complexData = (ComplexColumnData) cd;
                Function<Cell, String> transform = null;
                if (cd.column().type.isCollection()) {
                    CollectionType ct = (CollectionType) cd.column().type;
                    transform = cell -> String.format("%s -> %s", ct.nameComparator().getString(cell.path().get(0)), ct.valueComparator().getString(cell.value()));
                } else if (cd.column().type.isUDT()) {
                    UserType ut = (UserType) cd.column().type;
                    transform = cell -> {
                        Short fId = ut.nameComparator().getSerializer().deserialize(cell.path().get(0));
                        return String.format("%s -> %s", ut.fieldNameAsString(fId), ut.fieldType(fId).getString(cell.value()));
                    };
                } else {
                    transform = cell -> "";
                }
                sb.append(StreamSupport.stream(complexData.spliterator(), false).map(transform).collect(Collectors.joining(", ", "{", "}")));
            }
        }
    }
    return sb.toString();
}
Also used : Iterables(com.google.common.collect.Iterables) FBUtilities(org.apache.cassandra.utils.FBUtilities) MessageDigest(java.security.MessageDigest) org.apache.cassandra.db(org.apache.cassandra.db) Function(java.util.function.Function) Collectors(java.util.stream.Collectors) ByteBuffer(java.nio.ByteBuffer) Objects(java.util.Objects) AbstractCollection(java.util.AbstractCollection) TableMetadata(org.apache.cassandra.schema.TableMetadata) StreamSupport(java.util.stream.StreamSupport) CollectionType(org.apache.cassandra.db.marshal.CollectionType) UserType(org.apache.cassandra.db.marshal.UserType) MarshalException(org.apache.cassandra.serializers.MarshalException) CollectionType(org.apache.cassandra.db.marshal.CollectionType) UserType(org.apache.cassandra.db.marshal.UserType)

Aggregations

CollectionType (org.apache.cassandra.db.marshal.CollectionType)4 Iterables (com.google.common.collect.Iterables)2 ByteBuffer (java.nio.ByteBuffer)2 Collectors (java.util.stream.Collectors)2 ColumnMetadata (org.apache.cassandra.schema.ColumnMetadata)2 TableMetadata (org.apache.cassandra.schema.TableMetadata)2 IOException (java.io.IOException)1 MessageDigest (java.security.MessageDigest)1 java.util (java.util)1 AbstractCollection (java.util.AbstractCollection)1 Objects (java.util.Objects)1 Function (java.util.function.Function)1 StreamSupport (java.util.stream.StreamSupport)1 Permission (org.apache.cassandra.auth.Permission)1 org.apache.cassandra.cql3 (org.apache.cassandra.cql3)1 org.apache.cassandra.db (org.apache.cassandra.db)1 ColumnFamilyStore (org.apache.cassandra.db.ColumnFamilyStore)1 Keyspace (org.apache.cassandra.db.Keyspace)1 AbstractType (org.apache.cassandra.db.marshal.AbstractType)1 CompositeType (org.apache.cassandra.db.marshal.CompositeType)1