in src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java [320:402]
private void addColumn(KeyspaceMetadata keyspace,
TableMetadata table,
Column column,
boolean ifColumnNotExists,
TableMetadata.Builder tableBuilder,
Views.Builder viewsBuilder)
{
ColumnIdentifier name = column.name;
AbstractType<?> type = column.type.prepare(keyspaceName, keyspace.types).getType();
boolean isStatic = column.isStatic;
ColumnMask mask = column.mask == null ? null : column.mask.prepare(keyspaceName, tableName, name, type, keyspace.userFunctions);
ColumnConstraints columnConstraints = column.constraints == null ? ColumnConstraints.NO_OP : column.constraints.prepare(name);
if (null != tableBuilder.getColumn(name)) {
if (!ifColumnNotExists)
throw ire("Column with name '%s' already exists", name);
return;
}
if (type.isCounter() && (table.params.transactionalMode.accordIsEnabled || table.params.transactionalMigrationFrom.migratingFromAccord()))
throw ire(format(ACCORD_COUNTER_COLUMN_UNSUPPORTED, keyspaceName, tableName, table.params.transactionalMode, table.params.transactionalMigrationFrom));
if (table.isCompactTable())
throw ire("Cannot add new column to a COMPACT STORAGE table");
if (isStatic && table.clusteringColumns().isEmpty())
throw ire("Static columns are only useful (and thus allowed) if the table has at least one clustering column");
// check for nested non-frozen UDTs or collections in a non-frozen UDT
if (type.isUDT() && type.isMultiCell())
{
for (AbstractType<?> fieldType : ((UserType) type).fieldTypes())
{
if (fieldType.isMultiCell())
throw ire("Non-frozen UDTs with nested non-frozen collections are not supported for column " + column.name);
}
}
ColumnMetadata droppedColumn = table.getDroppedColumn(name.bytes);
if (null != droppedColumn)
{
// After #8099, not safe to re-add columns of incompatible types - until *maybe* deser logic with dropped
// columns is pushed deeper down the line. The latter would still be problematic in cases of schema races.
if (!type.isSerializationCompatibleWith(droppedColumn.type))
{
throw ire("Cannot re-add previously dropped column '%s' of type %s, incompatible with previous type %s",
name,
type.asCQL3Type(),
droppedColumn.type.asCQL3Type());
}
if (droppedColumn.isStatic() != isStatic)
{
throw ire("Cannot re-add previously dropped column '%s' of kind %s, incompatible with previous kind %s",
name,
isStatic ? ColumnMetadata.Kind.STATIC : ColumnMetadata.Kind.REGULAR,
droppedColumn.kind);
}
// Cannot re-add a dropped counter column. See #7831.
if (table.isCounter())
throw ire("Cannot re-add previously dropped counter column %s", name);
}
if (isStatic)
tableBuilder.addStaticColumn(name, type, mask, columnConstraints);
else
tableBuilder.addRegularColumn(name, type, mask, columnConstraints);
if (!isStatic)
{
for (ViewMetadata view : keyspace.views.forTable(table.id))
{
if (view.includeAllColumns)
{
ColumnMetadata viewColumn = ColumnMetadata.regularColumn(view.metadata, name.bytes, type, ColumnMetadata.NO_UNIQUE_ID)
.withNewMask(mask)
.withNewColumnConstraints(columnConstraints);
viewsBuilder.put(viewsBuilder.get(view.name()).withAddedRegularColumn(viewColumn));
}
}
}
}