From 4ab31d34c86d1b387098dd7934b11c659c763416 Mon Sep 17 00:00:00 2001 From: Roman Mushchinski Date: Mon, 21 Aug 2023 16:33:46 +0200 Subject: [PATCH] Make alternation of a user type validate the same way as creation of a user type does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit patch by Roman Mushchinski; reviewed by Stefan Miklosovic and Andres de la Peña for CASSANDRA-18585 --- CHANGES.txt | 1 + .../cql3/statements/AlterTypeStatement.java | 4 +++ .../org/apache/cassandra/cql3/CQLTester.java | 10 ++++++-- .../validation/entities/UserTypesTest.java | 25 +++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3383f14564..244a908aac 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.30 + * 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 0f506f74a5..80a4c67e62 100644 --- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java @@ -271,6 +271,10 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement newNames.add(fieldName.bytes); AbstractType addType = type.prepare(keyspace()).getType(); + + if (addType.isCounter()) + throw new InvalidRequestException("A user type cannot contain counters"); + 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)); diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java index fe8ed5b9c3..58240e8b10 100644 --- a/test/unit/org/apache/cassandra/cql3/CQLTester.java +++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java @@ -568,14 +568,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 68c0b8c87b..24e152aa1f 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java @@ -419,6 +419,31 @@ 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 + public void testInvalidAlterUDTStatements() throws Throwable + { + String typename = createType("CREATE TYPE %s (a int)"); + String myType = KEYSPACE + '.' + typename; + + String ut1 = createType("CREATE TYPE %s (a int)"); + assertInvalidMessage("Non-frozen User-Defined types are not supported, please use frozen<>", + "ALTER TYPE " + KEYSPACE + "." + ut1 + " ADD b " + myType); + } + /** * Test user type test that does a little more nesting, * migrated from cql_tests.py:TestCQL.more_user_types_test()