From c4c3048b13ca446966d79cce6499b8f826ac61a0 Mon Sep 17 00:00:00 2001 From: Maxim Muzafarov Date: Sun, 12 Jul 2026 18:56:28 +0200 Subject: [PATCH] Allow unreserved keywords as user and identity names in USER and IDENTITY statements patch by Maxim Muzafarov; reviewed by Dmitry Konstantinov for CASSANDRA-21510 --- CHANGES.txt | 1 + src/antlr/Parser.g | 2 ++ .../cassandra/cql3/ReservedKeywordsTest.java | 33 ++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index e90d69096b..f788a3228f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 6.0-alpha2 + * Allow unreserved keywords as user and identity names in USER and IDENTITY statements (CASSANDRA-21510) * Reduce allocations in DefaultQueryOptions (CASSANDRA-21467) * Coordinator load-shedding returns OverloadedException without setting streamId, misrouting query responses (CASSANDRA-21508) * Reduce number of scheduledTasks on metric id release in ThreadLocalMetrics (CASSANDRA-21475) diff --git a/src/antlr/Parser.g b/src/antlr/Parser.g index 8794d00d02..c459716406 100644 --- a/src/antlr/Parser.g +++ b/src/antlr/Parser.g @@ -2363,12 +2363,14 @@ vector_type returns [CQL3Type.Raw vt] username : IDENT | STRING_LITERAL + | unreserved_keyword | QUOTED_NAME { addRecognitionError("Quoted strings are are not supported for user names and USER is deprecated, please use ROLE");} ; identity : IDENT | STRING_LITERAL + | unreserved_keyword | QUOTED_NAME { addRecognitionError("Quoted strings are are not supported for identity");} ; diff --git a/test/unit/org/apache/cassandra/cql3/ReservedKeywordsTest.java b/test/unit/org/apache/cassandra/cql3/ReservedKeywordsTest.java index ef7a4b7ec2..0278a1d111 100644 --- a/test/unit/org/apache/cassandra/cql3/ReservedKeywordsTest.java +++ b/test/unit/org/apache/cassandra/cql3/ReservedKeywordsTest.java @@ -68,11 +68,42 @@ public class ReservedKeywordsTest asserts.assertAll(); } + /** + * Legacy USER and IDENTITY statements must accept unreserved keywords as names, just like + * role statements do ({@code roleName} accepts {@code unreserved_keyword}). Otherwise adding + * a new keyword to the grammar breaks existing deployments with a user or identity of that name. + */ + @Test + public void testUnreservedKeywordsAsUserNameAndIdentity() + { + SoftAssertions asserts = new SoftAssertions(); + for (var f : Cql_Lexer.class.getDeclaredFields()) + { + if (!Modifier.isStatic(f.getModifiers())) continue; + if (!f.getName().startsWith("K_")) continue; + String keyword = f.getName().replaceFirst("K_", ""); + if (ReservedKeywords.isReserved(keyword)) continue; + + for (String statement : new String[]{ "DROP USER %s", "DROP IDENTITY %s" }) + { + asserts.assertThat(parses(String.format(statement, keyword))) + .describedAs(String.format(statement, keyword)) + .isTrue(); + } + } + asserts.assertAll(); + } + private static boolean isAllowed(String keyword) + { + return parses(String.format("ALTER TABLE ks.t ADD %s TEXT", keyword)); + } + + private static boolean parses(String cql) { try { - QueryProcessor.parseStatement(String.format("ALTER TABLE ks.t ADD %s TEXT", keyword)); + QueryProcessor.parseStatement(cql); return true; } catch (SyntaxException ignore)