Merge branch 'cassandra-3.0' into cassandra-3.11

This commit is contained in:
Aleksey Yeshchenko 2020-07-27 16:11:50 +01:00
commit c61f3902ca
3 changed files with 43 additions and 0 deletions

View File

@ -1,6 +1,7 @@
3.11.8
* Frozen RawTuple is not annotated with frozen in the toString method (CASSANDRA-15857)
Merged from 3.0:
* Forbid altering UDTs used in partition keys (CASSANDRA-15933)
* Fix empty/null json string representation (CASSANDRA-15896)
Merged from 2.2:
* Fix CQL parsing of collections when the column type is reversed (CASSANDRA-15814)

View File

@ -31,6 +31,10 @@ import org.apache.cassandra.service.MigrationManager;
import org.apache.cassandra.service.QueryState;
import org.apache.cassandra.transport.Event;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
public abstract class AlterTypeStatement extends SchemaAlteringStatement
{
protected final UTName name;
@ -262,12 +266,31 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement
if (addType.referencesUserType(toUpdate.getNameAsString()))
throw new InvalidRequestException(String.format("Cannot add new field %s of type %s to type %s as this would create a circular reference", fieldName, type, name));
Collection<CFMetaData> tablesWithTypeInPartitionKey = findTablesReferencingTypeInPartitionKey(ksm, name.getStringTypeName());
if (!tablesWithTypeInPartitionKey.isEmpty())
{
String message =
String.format("Cannot add new field %s of type %s to user type %s.%s as the type is being used in partition key by the following tables: %s",
fieldName, type, ksm.name, toUpdate.getNameAsString(),
String.join(", ", transform(tablesWithTypeInPartitionKey, table -> table.ksName + '.' + table.cfName)));
throw new InvalidRequestException(message);
}
List<AbstractType<?>> newTypes = new ArrayList<>(toUpdate.size() + 1);
newTypes.addAll(toUpdate.fieldTypes());
newTypes.add(addType);
return new UserType(toUpdate.keyspace, toUpdate.name, newNames, newTypes, toUpdate.isMultiCell());
}
private static Collection<CFMetaData> findTablesReferencingTypeInPartitionKey(KeyspaceMetadata keyspace, String userTypeName)
{
Collection<CFMetaData> tables = new ArrayList<>();
filter(keyspace.tablesAndViews(),
table -> any(table.partitionKeyColumns(), column -> column.type.referencesUserType(userTypeName)))
.forEach(tables::add);
return tables;
}
}
private static class Renames extends AlterTypeStatement

View File

@ -547,4 +547,23 @@ public class AlterTest extends CQLTester
execute("ALTER TABLE %s ALTER value1 TYPE 'org.apache.cassandra.db.marshal.BytesType'");
}
@Test
public void testAlterTypeUsedInPartitionKey() throws Throwable
{
// frozen UDT used directly in a partition key
String type1 = createType("CREATE TYPE %s (v1 int)");
String table1 = createTable("CREATE TABLE %s (pk frozen<" + type1 + ">, val int, PRIMARY KEY(pk));");
// frozen UDT used in a frozen UDT used in a partition key
String type2 = createType("CREATE TYPE %s (v1 frozen<" + type1 + ">, v2 frozen<" + type1 + ">)");
String table2 = createTable("CREATE TABLE %s (pk frozen<" + type2 + ">, val int, PRIMARY KEY(pk));");
// frozen UDT used in a frozen collection used in a partition key
String table3 = createTable("CREATE TABLE %s (pk frozen<list<frozen<" + type1 + ">>>, val int, PRIMARY KEY(pk));");
// assert that ALTER fails and that the error message contains all the names of the table referencing it
assertInvalidMessage(table1, format("ALTER TYPE %s.%s ADD v2 int;", keyspace(), type1));
assertInvalidMessage(table2, format("ALTER TYPE %s.%s ADD v2 int;", keyspace(), type1));
assertInvalidMessage(table3, format("ALTER TYPE %s.%s ADD v2 int;", keyspace(), type1));
}
}