use of org.apache.cassandra.db.marshal.AbstractType in project cassandra by apache.
the class SSTableMetadataViewer method printSStableMetadata.
private void printSStableMetadata(String fname, boolean scan) throws IOException {
Descriptor descriptor = Descriptor.fromFilename(fname);
Map<MetadataType, MetadataComponent> metadata = descriptor.getMetadataSerializer().deserialize(descriptor, EnumSet.allOf(MetadataType.class));
ValidationMetadata validation = (ValidationMetadata) metadata.get(MetadataType.VALIDATION);
StatsMetadata stats = (StatsMetadata) metadata.get(MetadataType.STATS);
CompactionMetadata compaction = (CompactionMetadata) metadata.get(MetadataType.COMPACTION);
CompressionMetadata compression = null;
File compressionFile = new File(descriptor.filenameFor(Component.COMPRESSION_INFO));
if (compressionFile.exists())
compression = CompressionMetadata.create(fname);
SerializationHeader.Component header = (SerializationHeader.Component) metadata.get(MetadataType.HEADER);
field("SSTable", descriptor);
if (scan && descriptor.version.getVersion().compareTo("ma") >= 0) {
printScannedOverview(descriptor, stats);
}
if (validation != null) {
field("Partitioner", validation.partitioner);
field("Bloom Filter FP chance", validation.bloomFilterFPChance);
}
if (stats != null) {
field("Minimum timestamp", stats.minTimestamp, toDateString(stats.minTimestamp, tsUnit));
field("Maximum timestamp", stats.maxTimestamp, toDateString(stats.maxTimestamp, tsUnit));
field("SSTable min local deletion time", stats.minLocalDeletionTime, deletion(stats.minLocalDeletionTime));
field("SSTable max local deletion time", stats.maxLocalDeletionTime, deletion(stats.maxLocalDeletionTime));
field("Compressor", compression != null ? compression.compressor().getClass().getName() : "-");
if (compression != null)
field("Compression ratio", stats.compressionRatio);
field("TTL min", stats.minTTL, toDurationString(stats.minTTL, TimeUnit.SECONDS));
field("TTL max", stats.maxTTL, toDurationString(stats.maxTTL, TimeUnit.SECONDS));
if (validation != null && header != null)
printMinMaxToken(descriptor, FBUtilities.newPartitioner(descriptor), header.getKeyType());
if (header != null && header.getClusteringTypes().size() == stats.minClusteringValues.size()) {
List<AbstractType<?>> clusteringTypes = header.getClusteringTypes();
List<ByteBuffer> minClusteringValues = stats.minClusteringValues;
List<ByteBuffer> maxClusteringValues = stats.maxClusteringValues;
String[] minValues = new String[clusteringTypes.size()];
String[] maxValues = new String[clusteringTypes.size()];
for (int i = 0; i < clusteringTypes.size(); i++) {
minValues[i] = clusteringTypes.get(i).getString(minClusteringValues.get(i));
maxValues[i] = clusteringTypes.get(i).getString(maxClusteringValues.get(i));
}
field("minClusteringValues", Arrays.toString(minValues));
field("maxClusteringValues", Arrays.toString(maxValues));
}
field("Estimated droppable tombstones", stats.getEstimatedDroppableTombstoneRatio((int) (currentTimeMillis() / 1000) - this.gc));
field("SSTable Level", stats.sstableLevel);
field("Repaired at", stats.repairedAt, toDateString(stats.repairedAt, TimeUnit.MILLISECONDS));
field("Pending repair", stats.pendingRepair);
field("Replay positions covered", stats.commitLogIntervals);
field("totalColumnsSet", stats.totalColumnsSet);
field("totalRows", stats.totalRows);
field("Estimated tombstone drop times", "");
TermHistogram estDropped = new TermHistogram(stats.estimatedTombstoneDropTime, "Drop Time", offset -> String.format("%d %s", offset, Util.wrapQuiet(toDateString(offset, TimeUnit.SECONDS), color)), String::valueOf);
estDropped.printHistogram(out, color, unicode);
field("Partition Size", "");
TermHistogram rowSize = new TermHistogram(stats.estimatedPartitionSize, "Size (bytes)", offset -> String.format("%d %s", offset, Util.wrapQuiet(toByteString(offset), color)), String::valueOf);
rowSize.printHistogram(out, color, unicode);
field("Column Count", "");
TermHistogram cellCount = new TermHistogram(stats.estimatedCellPerPartitionCount, "Columns", String::valueOf, String::valueOf);
cellCount.printHistogram(out, color, unicode);
}
if (compaction != null) {
field("Estimated cardinality", compaction.cardinalityEstimator.cardinality());
}
if (header != null) {
EncodingStats encodingStats = header.getEncodingStats();
AbstractType<?> keyType = header.getKeyType();
List<AbstractType<?>> clusteringTypes = header.getClusteringTypes();
Map<ByteBuffer, AbstractType<?>> staticColumns = header.getStaticColumns();
Map<String, String> statics = staticColumns.entrySet().stream().collect(Collectors.toMap(e -> UTF8Type.instance.getString(e.getKey()), e -> e.getValue().toString()));
Map<ByteBuffer, AbstractType<?>> regularColumns = header.getRegularColumns();
Map<String, String> regulars = regularColumns.entrySet().stream().collect(Collectors.toMap(e -> UTF8Type.instance.getString(e.getKey()), e -> e.getValue().toString()));
field("EncodingStats minTTL", encodingStats.minTTL, toDurationString(encodingStats.minTTL, TimeUnit.SECONDS));
field("EncodingStats minLocalDeletionTime", encodingStats.minLocalDeletionTime, toDateString(encodingStats.minLocalDeletionTime, TimeUnit.SECONDS));
field("EncodingStats minTimestamp", encodingStats.minTimestamp, toDateString(encodingStats.minTimestamp, tsUnit));
field("KeyType", keyType.toString());
field("ClusteringTypes", clusteringTypes.toString());
field("StaticColumns", FBUtilities.toString(statics));
field("RegularColumns", FBUtilities.toString(regulars));
field("IsTransient", stats.isTransient);
}
}
use of org.apache.cassandra.db.marshal.AbstractType in project cassandra by apache.
the class QueryProcessor method makeInternalOptions.
private static QueryOptions makeInternalOptions(CQLStatement prepared, Object[] values, ConsistencyLevel cl) {
if (prepared.getBindVariables().size() != values.length)
throw new IllegalArgumentException(String.format("Invalid number of values. Expecting %d but got %d", prepared.getBindVariables().size(), values.length));
List<ByteBuffer> boundValues = new ArrayList<>(values.length);
for (int i = 0; i < values.length; i++) {
Object value = values[i];
AbstractType type = prepared.getBindVariables().get(i).type;
boundValues.add(value instanceof ByteBuffer || value == null ? (ByteBuffer) value : type.decompose(value));
}
return QueryOptions.forInternalCalls(cl, boundValues);
}
use of org.apache.cassandra.db.marshal.AbstractType in project cassandra by apache.
the class CreateAggregateStatement method apply.
public Keyspaces apply(Keyspaces schema) {
if (ifNotExists && orReplace)
throw ire("Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives");
rawArgumentTypes.stream().filter(raw -> !raw.isTuple() && raw.isFrozen()).findFirst().ifPresent(t -> {
throw ire("Argument '%s' cannot be frozen; remove frozen<> modifier from '%s'", t, t);
});
if (!rawStateType.isTuple() && rawStateType.isFrozen())
throw ire("State type '%s' cannot be frozen; remove frozen<> modifier from '%s'", rawStateType, rawStateType);
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
/*
* Resolve the state function
*/
List<AbstractType<?>> argumentTypes = rawArgumentTypes.stream().map(t -> t.prepare(keyspaceName, keyspace.types).getType()).collect(toList());
AbstractType<?> stateType = rawStateType.prepare(keyspaceName, keyspace.types).getType();
List<AbstractType<?>> stateFunctionArguments = Lists.newArrayList(concat(singleton(stateType), argumentTypes));
Function stateFunction = keyspace.functions.find(stateFunctionName, stateFunctionArguments).orElseThrow(() -> ire("State function %s doesn't exist", stateFunctionString()));
if (stateFunction.isAggregate())
throw ire("State function %s isn't a scalar function", stateFunctionString());
if (!stateFunction.returnType().equals(stateType)) {
throw ire("State function %s return type must be the same as the first argument type - check STYPE, argument and return types", stateFunctionString());
}
/*
* Resolve the final function and return type
*/
Function finalFunction = null;
AbstractType<?> returnType = stateFunction.returnType();
if (null != finalFunctionName) {
finalFunction = keyspace.functions.find(finalFunctionName, singletonList(stateType)).orElse(null);
if (null == finalFunction)
throw ire("Final function %s doesn't exist", finalFunctionString());
if (finalFunction.isAggregate())
throw ire("Final function %s isn't a scalar function", finalFunctionString());
// override return type with that of the final function
returnType = finalFunction.returnType();
}
/*
* Validate initial condition
*/
ByteBuffer initialValue = null;
if (null != rawInitialValue) {
initialValue = Terms.asBytes(keyspaceName, rawInitialValue.toString(), stateType);
if (null != initialValue) {
try {
stateType.validate(initialValue);
} catch (MarshalException e) {
throw ire("Invalid value for INITCOND of type %s", stateType.asCQL3Type());
}
}
// Converts initcond to a CQL literal and parse it back to avoid another CASSANDRA-11064
String initialValueString = stateType.asCQL3Type().toCQLLiteral(initialValue, ProtocolVersion.CURRENT);
assert Objects.equal(initialValue, Terms.asBytes(keyspaceName, initialValueString, stateType));
if (Constants.NULL_LITERAL != rawInitialValue && UDHelper.isNullOrEmpty(stateType, initialValue))
throw ire("INITCOND must not be empty for all types except TEXT, ASCII, BLOB");
}
if (!((UDFunction) stateFunction).isCalledOnNullInput() && null == initialValue) {
throw ire("Cannot create aggregate '%s' without INITCOND because state function %s does not accept 'null' arguments", aggregateName, stateFunctionName);
}
/*
* Create or replace
*/
UDAggregate aggregate = new UDAggregate(new FunctionName(keyspaceName, aggregateName), argumentTypes, returnType, (ScalarFunction) stateFunction, (ScalarFunction) finalFunction, initialValue);
Function existingAggregate = keyspace.functions.find(aggregate.name(), argumentTypes).orElse(null);
if (null != existingAggregate) {
if (!existingAggregate.isAggregate())
throw ire("Aggregate '%s' cannot replace a function", aggregateName);
if (ifNotExists)
return schema;
if (!orReplace)
throw ire("Aggregate '%s' already exists", aggregateName);
if (!returnType.isCompatibleWith(existingAggregate.returnType())) {
throw ire("Cannot replace aggregate '%s', the new return type %s isn't compatible with the return type %s of existing function", aggregateName, returnType.asCQL3Type(), existingAggregate.returnType().asCQL3Type());
}
}
return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.functions.withAddedOrUpdated(aggregate)));
}
use of org.apache.cassandra.db.marshal.AbstractType in project cassandra by apache.
the class CreateViewStatement method apply.
public Keyspaces apply(Keyspaces schema) {
if (!DatabaseDescriptor.getMaterializedViewsEnabled())
throw ire("Materialized views are disabled. Enable in cassandra.yaml to use.");
/*
* Basic dependency validations
*/
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
if (keyspace.createReplicationStrategy().hasTransientReplicas())
throw new InvalidRequestException("Materialized views are not supported on transiently replicated keyspaces");
TableMetadata table = keyspace.tables.getNullable(tableName);
if (null == table)
throw ire("Base table '%s' doesn't exist", tableName);
if (keyspace.hasTable(viewName))
throw ire("Cannot create materialized view '%s' - a table with the same name already exists", viewName);
if (keyspace.hasView(viewName)) {
if (ifNotExists)
return schema;
throw new AlreadyExistsException(keyspaceName, viewName);
}
if (table.isCounter())
throw ire("Materialized views are not supported on counter tables");
if (table.isView())
throw ire("Materialized views cannot be created against other materialized views");
// Guardrails on table properties
Guardrails.tableProperties.guard(attrs.updatedProperties(), attrs::removeProperty, state);
// Guardrail to limit number of mvs per table
Iterable<ViewMetadata> tableViews = keyspace.views.forTable(table.id);
Guardrails.materializedViewsPerTable.guard(Iterables.size(tableViews) + 1, String.format("%s on table %s", viewName, table.name), state);
if (table.params.gcGraceSeconds == 0) {
throw ire("Cannot create materialized view '%s' for base table " + "'%s' with gc_grace_seconds of 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.", viewName, tableName);
}
/*
* Process SELECT clause
*/
Set<ColumnIdentifier> selectedColumns = new HashSet<>();
if (// SELECT *
rawColumns.isEmpty())
table.columns().forEach(c -> selectedColumns.add(c.name));
rawColumns.forEach(selector -> {
if (null != selector.alias)
throw ire("Cannot use aliases when defining a materialized view (got %s)", selector);
if (!(selector.selectable instanceof Selectable.RawIdentifier))
throw ire("Can only select columns by name when defining a materialized view (got %s)", selector.selectable);
// will throw IRE if the column doesn't exist in the base table
ColumnMetadata column = (ColumnMetadata) selector.selectable.prepare(table);
selectedColumns.add(column.name);
});
selectedColumns.stream().map(table::getColumn).filter(ColumnMetadata::isStatic).findAny().ifPresent(c -> {
throw ire("Cannot include static column '%s' in materialized view '%s'", c, viewName);
});
if (partitionKeyColumns.isEmpty())
throw ire("Must provide at least one partition key column for materialized view '%s'", viewName);
HashSet<ColumnIdentifier> primaryKeyColumns = new HashSet<>();
concat(partitionKeyColumns, clusteringColumns).forEach(name -> {
ColumnMetadata column = table.getColumn(name);
if (null == column || !selectedColumns.contains(name))
throw ire("Unknown column '%s' referenced in PRIMARY KEY for materialized view '%s'", name, viewName);
if (!primaryKeyColumns.add(name))
throw ire("Duplicate column '%s' in PRIMARY KEY clause for materialized view '%s'", name, viewName);
AbstractType<?> type = column.type;
if (type.isMultiCell()) {
if (type.isCollection())
throw ire("Invalid non-frozen collection type '%s' for PRIMARY KEY column '%s'", type, name);
else
throw ire("Invalid non-frozen user-defined type '%s' for PRIMARY KEY column '%s'", type, name);
}
if (type.isCounter())
throw ire("counter type is not supported for PRIMARY KEY column '%s'", name);
if (type.referencesDuration())
throw ire("duration type is not supported for PRIMARY KEY column '%s'", name);
});
// If we give a clustering order, we must explicitly do so for all aliases and in the order of the PK
if (!clusteringOrder.isEmpty() && !clusteringColumns.equals(new ArrayList<>(clusteringOrder.keySet())))
throw ire("Clustering key columns must exactly match columns in CLUSTERING ORDER BY directive");
/*
* We need to include all of the primary key columns from the base table in order to make sure that we do not
* overwrite values in the view. We cannot support "collapsing" the base table into a smaller number of rows in
* the view because if we need to generate a tombstone, we have no way of knowing which value is currently being
* used in the view and whether or not to generate a tombstone. In order to not surprise our users, we require
* that they include all of the columns. We provide them with a list of all of the columns left to include.
*/
List<ColumnIdentifier> missingPrimaryKeyColumns = Lists.newArrayList(filter(transform(table.primaryKeyColumns(), c -> c.name), c -> !primaryKeyColumns.contains(c)));
if (!missingPrimaryKeyColumns.isEmpty()) {
throw ire("Cannot create materialized view '%s' without primary key columns %s from base table '%s'", viewName, join(", ", transform(missingPrimaryKeyColumns, ColumnIdentifier::toString)), tableName);
}
Set<ColumnIdentifier> regularBaseTableColumnsInViewPrimaryKey = new HashSet<>(primaryKeyColumns);
transform(table.primaryKeyColumns(), c -> c.name).forEach(regularBaseTableColumnsInViewPrimaryKey::remove);
if (regularBaseTableColumnsInViewPrimaryKey.size() > 1) {
throw ire("Cannot include more than one non-primary key column in materialized view primary key (got %s)", join(", ", transform(regularBaseTableColumnsInViewPrimaryKey, ColumnIdentifier::toString)));
}
/*
* Process WHERE clause
*/
if (whereClause.containsTokenRelations())
throw new InvalidRequestException("Cannot use token relation when defining a materialized view");
if (whereClause.containsCustomExpressions())
throw ire("WHERE clause for materialized view '%s' cannot contain custom index expressions", viewName);
StatementRestrictions restrictions = new StatementRestrictions(StatementType.SELECT, table, whereClause, VariableSpecifications.empty(), false, false, true, true);
List<ColumnIdentifier> nonRestrictedPrimaryKeyColumns = Lists.newArrayList(filter(primaryKeyColumns, name -> !restrictions.isRestricted(table.getColumn(name))));
if (!nonRestrictedPrimaryKeyColumns.isEmpty()) {
throw ire("Primary key columns %s must be restricted with 'IS NOT NULL' or otherwise", join(", ", transform(nonRestrictedPrimaryKeyColumns, ColumnIdentifier::toString)));
}
// See CASSANDRA-13798
Set<ColumnMetadata> restrictedNonPrimaryKeyColumns = restrictions.nonPKRestrictedColumns(false);
if (!restrictedNonPrimaryKeyColumns.isEmpty() && !Boolean.getBoolean("cassandra.mv.allow_filtering_nonkey_columns_unsafe")) {
throw ire("Non-primary key columns can only be restricted with 'IS NOT NULL' (got: %s restricted illegally)", join(",", transform(restrictedNonPrimaryKeyColumns, ColumnMetadata::toString)));
}
/*
* Validate WITH params
*/
attrs.validate();
if (attrs.hasOption(TableParams.Option.DEFAULT_TIME_TO_LIVE)) {
throw ire("Cannot set default_time_to_live for a materialized view. " + "Data in a materialized view always expire at the same time than " + "the corresponding data in the parent table.");
}
/*
* Build the thing
*/
TableMetadata.Builder builder = TableMetadata.builder(keyspaceName, viewName);
if (attrs.hasProperty(TableAttributes.ID))
builder.id(attrs.getId());
builder.params(attrs.asNewTableParams()).kind(TableMetadata.Kind.VIEW);
partitionKeyColumns.forEach(name -> builder.addPartitionKeyColumn(name, getType(table, name)));
clusteringColumns.forEach(name -> builder.addClusteringColumn(name, getType(table, name)));
selectedColumns.stream().filter(name -> !primaryKeyColumns.contains(name)).forEach(name -> builder.addRegularColumn(name, getType(table, name)));
ViewMetadata view = new ViewMetadata(table.id, table.name, rawColumns.isEmpty(), whereClause, builder.build());
view.metadata.validate();
return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.views.with(view)));
}
use of org.apache.cassandra.db.marshal.AbstractType in project cassandra by apache.
the class CreateTypeStatement method apply.
public Keyspaces apply(Keyspaces schema) {
KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
if (null == keyspace)
throw ire("Keyspace '%s' doesn't exist", keyspaceName);
UserType existingType = keyspace.types.getNullable(bytes(typeName));
if (null != existingType) {
if (ifNotExists)
return schema;
throw ire("A user type with name '%s' already exists", typeName);
}
Set<FieldIdentifier> usedNames = new HashSet<>();
for (FieldIdentifier name : fieldNames) if (!usedNames.add(name))
throw ire("Duplicate field name '%s' in type '%s'", name, typeName);
for (CQL3Type.Raw type : rawFieldTypes) {
if (type.isCounter())
throw ire("A user type cannot contain counters");
if (type.isUDT() && !type.isFrozen())
throw ire("A user type cannot contain non-frozen UDTs");
}
List<AbstractType<?>> fieldTypes = rawFieldTypes.stream().map(t -> t.prepare(keyspaceName, keyspace.types).getType()).collect(toList());
UserType udt = new UserType(keyspaceName, bytes(typeName), fieldNames, fieldTypes, true);
return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.types.with(udt)));
}
Aggregations