diff --git a/CHANGES.txt b/CHANGES.txt index 7b8fde184b..36a980c339 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,7 @@ 3.11.17 * Fix NPE when using udfContext in UDF after a restart of a node (CASSANDRA-18739) Merged from 3.0: + * Make alternation of a user type validate the same way as creation of a user type does (CASSANDRA-18585) * Backport of CASSANDRA-16905 Further restrict schema column drop/recreate conversions (CASSANDRA-18760) * CQLSH emits a warning when the server version doesn't match (CASSANDRA-18745) * Fix missing speculative retries in tablestats (CASSANDRA-18767) diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java index d0e2f33979..c8af0e9dfd 100644 --- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java @@ -255,6 +255,12 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement protected UserType makeUpdatedType(UserType toUpdate, KeyspaceMetadata ksm) throws InvalidRequestException { + if (type.isCounter()) + throw new InvalidRequestException("A user type cannot contain counters"); + + if (type.isUDT() && !type.isFrozen()) + throw new InvalidRequestException("A user type cannot contain non-frozen UDTs"); + if (toUpdate.fieldPosition(fieldName) >= 0) throw new InvalidRequestException(String.format("Cannot add new field %s to type %s: a field of the same name already exists", fieldName, name)); diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java index b611a52f53..07504aa5cd 100644 --- a/test/unit/org/apache/cassandra/cql3/CQLTester.java +++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java @@ -574,14 +574,20 @@ public abstract class CQLTester protected String createType(String query) { - String typeName = "type_" + seqNumber.getAndIncrement(); + String typeName = createTypeName(); String fullQuery = String.format(query, KEYSPACE + "." + typeName); - types.add(typeName); logger.info(fullQuery); schemaChange(fullQuery); return typeName; } + protected String createTypeName() + { + String typeName = String.format("type_%02d", seqNumber.getAndIncrement()); + types.add(typeName); + return typeName; + } + protected String createFunctionName(String keyspace) { return String.format("%s.function_%02d", keyspace, seqNumber.getAndIncrement()); diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java index 646484c9a1..12a4025e66 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java @@ -133,6 +133,10 @@ public class UserTypesTest extends CQLTester assertInvalidMessage("A user type cannot contain non-frozen UDTs", "CREATE TYPE " + KEYSPACE + ".wrong (a int, b " + myType + ")"); + String ut1 = createType("CREATE TYPE %s (a int)"); + assertInvalidMessage("A user type cannot contain non-frozen UDTs", + "ALTER TYPE " + KEYSPACE + "." + ut1 + " ADD b " + myType); + // referencing a UDT in another keyspace assertInvalidMessage("Statement on keyspace " + KEYSPACE + " cannot refer to a user type in keyspace otherkeyspace;" + " user types can only be used in the keyspace they are defined in", @@ -477,6 +481,20 @@ public class UserTypesTest extends CQLTester execute("SELECT addresses FROM %s WHERE id = ? ", userID_1); } + @Test + public void testCreateTypeWithUndesiredFieldType() throws Throwable + { + String typeName = createTypeName(); + assertInvalidMessage("A user type cannot contain counters", "CREATE TYPE " + typeWithKs(typeName) + " (f counter)"); + } + + @Test + public void testAlterTypeWithUndesiredFieldType() throws Throwable + { + String typeName = createType("CREATE TYPE %s (a int)"); + assertInvalidMessage("A user type cannot contain counters", "ALTER TYPE " + typeWithKs(typeName) + " ADD f counter"); + } + /** * Test user type test that does a little more nesting, * migrated from cql_tests.py:TestCQL.more_user_types_test()