From 3819c51584d33f124e3554fd4487817dd878c49c Mon Sep 17 00:00:00 2001 From: Shalni Sundram Date: Thu, 2 Oct 2025 10:39:30 -0700 Subject: [PATCH 1/7] add identity mapping grammars in cql3handling for ADD DROP autocomplete --- pylib/cqlshlib/cql3handling.py | 11 +++ .../test/test_identity_mappings_completion.py | 72 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 pylib/cqlshlib/test/test_identity_mappings_completion.py diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py index 3697aa4888c2..49697f059a19 100644 --- a/pylib/cqlshlib/cql3handling.py +++ b/pylib/cqlshlib/cql3handling.py @@ -286,6 +286,7 @@ def dequote_value(cqlword): | | | + | | | | @@ -294,6 +295,7 @@ def dequote_value(cqlword): | | | + | | | | @@ -1749,6 +1751,7 @@ def rolename_completer(ctxt, cass): "ON" cf= ; ''' + explain_completion('createTriggerStatement', 'class', '\'fully qualified class name\'') @@ -1765,6 +1768,14 @@ def drop_trigger_completer(ctxt, cass): return list(map(maybe_escape_name, names)) +syntax_rules += r''' + ::= "ADD" "USER" ("IF" "NOT" "EXISTS")? + "TO" "ROLE" + ; + ::= "DROP" "USER" ("IF" "EXISTS")? + ; +''' + # END SYNTAX/COMPLETION RULE DEFINITIONS CqlRuleSet.append_rules(syntax_rules) diff --git a/pylib/cqlshlib/test/test_identity_mappings_completion.py b/pylib/cqlshlib/test/test_identity_mappings_completion.py new file mode 100644 index 000000000000..beb5190b885c --- /dev/null +++ b/pylib/cqlshlib/test/test_identity_mappings_completion.py @@ -0,0 +1,72 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .test_cqlsh_completion import CqlshCompletionCase + + +class TestIdentityMappingsCompletion(CqlshCompletionCase): + + """ + Autcomplete Tests for ADD and DROP Identity Mappings for @cql3handling.py + """ + + def add_test_user_autocomplete(self): + self.trycompletions('ADD U', immediate='SER ') + + + def add_test_exists_autocomplete(self): + self.trycompletions('ADD USER IF ', immediate='NOT EXISTS ') + self.trycompletions('ADD USER IF NOT ', immediate='EXISTS ') + + def test_expect_str_literal_add_autocomplete(self): + self.trycompletions('ADD USER ', + choices=['', '', 'IF']) + + def add_test_to_autocomplete(self): + self.trycompletions("ADD USER 'alice@example.com' ", immediate='TO ') + self.trycompletions("ADD USER 'alice@example.com' T", immediate='O ') + + def add_test_role_autocomplete(self): + self.trycompletions("ADD USER 'alice@example.com' TO ", immediate='ROLE ') + self.trycompletions("ADD USER 'alice@example.com' TO R", immediate='OLE ') + + def add_test_rolename_autocomplete(self): + self.trycompletions("ADD USER 'alice@example.com' TO ROLE ", + choices=['', ''], + other_choices_ok=True) + + def add_test_complete_user_full_statement(self): + self.trycompletions("ADD USER IF NOT EXISTS 'alice@example.com' TO ROLE data_engineer ", + choices=[';']) + + def drop_test_autocomplete(self): + self.trycompletions('DROP ', + choices=['AGGREGATE', 'COLUMNFAMILY', 'FUNCTION', + 'INDEX', 'KEYSPACE', 'ROLE', 'TABLE', + 'TRIGGER', 'TYPE', 'USER', 'MATERIALIZED']) + + def drop_test_user_autcomplete(self): + self.trycompletions('DROP USER ', + choices=['', '', 'IF']) + + def drop_test_exists(self): + self.trycompletions('DROP USER IF ', immediate='EXISTS ') + self.trycompletions('DROP USER IF EXISTS ', + choices=['', '']) + + def test_complete_drop_user_statement_end(self): + self.trycompletions("DROP USER 'alice@example.com' ", choices=[';']) + self.trycompletions("DROP USER IF EXISTS 'alice@example.com' ", choices=[';']) \ No newline at end of file From 8007fc36481705da762c101c5264b664abd9b69f Mon Sep 17 00:00:00 2001 From: Shalni Sundram Date: Thu, 2 Oct 2025 13:53:33 -0700 Subject: [PATCH 2/7] change USER to IDENTITY for identityMapping autocompletes --- pylib/cqlshlib/cql3handling.py | 4 +- .../test/test_identity_mappings_completion.py | 55 +++++++++---------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py index 49697f059a19..3a61bb8ff5a1 100644 --- a/pylib/cqlshlib/cql3handling.py +++ b/pylib/cqlshlib/cql3handling.py @@ -1769,10 +1769,10 @@ def drop_trigger_completer(ctxt, cass): syntax_rules += r''' - ::= "ADD" "USER" ("IF" "NOT" "EXISTS")? + ::= "ADD" "IDENTITY" ("IF" "NOT" "EXISTS")? "TO" "ROLE" ; - ::= "DROP" "USER" ("IF" "EXISTS")? + ::= "DROP" "IDENTITY" ("IF" "EXISTS")? ; ''' diff --git a/pylib/cqlshlib/test/test_identity_mappings_completion.py b/pylib/cqlshlib/test/test_identity_mappings_completion.py index beb5190b885c..3b1c813d6984 100644 --- a/pylib/cqlshlib/test/test_identity_mappings_completion.py +++ b/pylib/cqlshlib/test/test_identity_mappings_completion.py @@ -23,50 +23,49 @@ class TestIdentityMappingsCompletion(CqlshCompletionCase): Autcomplete Tests for ADD and DROP Identity Mappings for @cql3handling.py """ - def add_test_user_autocomplete(self): - self.trycompletions('ADD U', immediate='SER ') + def test_identity_autocomplete_add(self): + self.trycompletions('ADD I', immediate='DENTITY ') + def test_exists_autocomplete_add(self): + self.trycompletions('ADD IDENTITY IF ', immediate='NOT EXISTS ') + self.trycompletions('ADD IDENTITY IF NOT ', immediate='EXISTS ') - def add_test_exists_autocomplete(self): - self.trycompletions('ADD USER IF ', immediate='NOT EXISTS ') - self.trycompletions('ADD USER IF NOT ', immediate='EXISTS ') - - def test_expect_str_literal_add_autocomplete(self): - self.trycompletions('ADD USER ', + def test_expect_str_literal_autocomplete_add(self): + self.trycompletions('ADD IDENTITY ', choices=['', '', 'IF']) - def add_test_to_autocomplete(self): - self.trycompletions("ADD USER 'alice@example.com' ", immediate='TO ') - self.trycompletions("ADD USER 'alice@example.com' T", immediate='O ') + def test_TO_autocomplete_add(self): + self.trycompletions("ADD IDENTITY 'alice@example.com' ", immediate='TO ROLE ') + self.trycompletions("ADD IDENTITY 'alice@example.com' T", immediate='O ROLE ') - def add_test_role_autocomplete(self): - self.trycompletions("ADD USER 'alice@example.com' TO ", immediate='ROLE ') - self.trycompletions("ADD USER 'alice@example.com' TO R", immediate='OLE ') + def test_role_autocomplete_add(self): + self.trycompletions("ADD IDENTITY 'alice@example.com' TO ", immediate='ROLE ') + self.trycompletions("ADD IDENTITY 'alice@example.com' TO R", immediate='OLE ') - def add_test_rolename_autocomplete(self): - self.trycompletions("ADD USER 'alice@example.com' TO ROLE ", + def test_rolename_autocomplete_add(self): + self.trycompletions("ADD IDENTITY 'alice@example.com' TO ROLE ", choices=['', ''], other_choices_ok=True) - def add_test_complete_user_full_statement(self): - self.trycompletions("ADD USER IF NOT EXISTS 'alice@example.com' TO ROLE data_engineer ", + def test_complete_user_full_statement_add(self): + self.trycompletions("ADD IDENTITY IF NOT EXISTS 'alice@example.com' TO ROLE data_engineer ", choices=[';']) - def drop_test_autocomplete(self): + def test_autocomplete_drop(self): self.trycompletions('DROP ', choices=['AGGREGATE', 'COLUMNFAMILY', 'FUNCTION', 'INDEX', 'KEYSPACE', 'ROLE', 'TABLE', - 'TRIGGER', 'TYPE', 'USER', 'MATERIALIZED']) + 'TRIGGER', 'TYPE', 'USER', 'MATERIALIZED', 'IDENTITY']) - def drop_test_user_autcomplete(self): - self.trycompletions('DROP USER ', + def test_identity_autcomplete_drop(self): + self.trycompletions('DROP IDENTITY ', choices=['', '', 'IF']) - def drop_test_exists(self): - self.trycompletions('DROP USER IF ', immediate='EXISTS ') - self.trycompletions('DROP USER IF EXISTS ', + def test_exists_str_literal_drop(self): + self.trycompletions('DROP IDENTITY IF ', immediate='EXISTS ') + self.trycompletions('DROP IDENTITY IF EXISTS ', choices=['', '']) - def test_complete_drop_user_statement_end(self): - self.trycompletions("DROP USER 'alice@example.com' ", choices=[';']) - self.trycompletions("DROP USER IF EXISTS 'alice@example.com' ", choices=[';']) \ No newline at end of file + def test_complete_drop_IDENTITY_statement_end(self): + self.trycompletions("DROP IDENTITY 'alice@example.com' ", choices=[';']) + self.trycompletions("DROP IDENTITY IF EXISTS 'alice@example.com' ", choices=[';']) \ No newline at end of file From 09303597034af528c544bc9c1fb083c99cb33529 Mon Sep 17 00:00:00 2001 From: Shalni Sundram Date: Mon, 6 Oct 2025 10:41:10 -0700 Subject: [PATCH 3/7] consolidate identity tests into test_cqlsh_completion.py --- pylib/cqlshlib/test/test_cqlsh_completion.py | 45 +++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py b/pylib/cqlshlib/test/test_cqlsh_completion.py index 80a4def238c1..2aafad844289 100644 --- a/pylib/cqlshlib/test/test_cqlsh_completion.py +++ b/pylib/cqlshlib/test/test_cqlsh_completion.py @@ -166,7 +166,7 @@ class TestCqlshCompletion(CqlshCompletionCase): cqlver = '3.1.6' def test_complete_on_empty_string(self): - self.trycompletions('', choices=('?', 'ALTER', 'BEGIN', 'CAPTURE', 'CONSISTENCY', + self.trycompletions('', choices=('?', 'ADD', 'ALTER', 'BEGIN', 'CAPTURE', 'CONSISTENCY', 'COPY', 'CREATE', 'DEBUG', 'DELETE', 'DESC', 'DESCRIBE', 'DROP', 'GRANT', 'HELP', 'INSERT', 'LIST', 'LOGIN', 'PAGING', 'REVOKE', 'SELECT', 'SHOW', 'SOURCE', 'TRACING', 'ELAPSED', 'EXPAND', 'SERIAL', 'TRUNCATE', @@ -613,7 +613,7 @@ def test_complete_in_string_literals(self): def test_complete_in_drop(self): self.trycompletions('DR', immediate='OP ') self.trycompletions('DROP ', - choices=['AGGREGATE', 'COLUMNFAMILY', 'FUNCTION', + choices=['AGGREGATE', 'COLUMNFAMILY', 'FUNCTION', 'IDENTITY', 'INDEX', 'KEYSPACE', 'ROLE', 'TABLE', 'TRIGGER', 'TYPE', 'USER', 'MATERIALIZED']) @@ -1048,12 +1048,12 @@ def test_complete_in_use(self): 'system_virtual_schema', 'system_cluster_metadata']) def test_complete_in_create_index(self): - self.trycompletions('CREATE I', immediate='NDEX ') + self.trycompletions('CREATE IN', immediate='DEX ') self.trycompletions('CREATE INDEX ', choices=['', 'IF', 'ON']) self.trycompletions('CREATE INDEX example ', immediate='ON ') def test_complete_in_drop_index(self): - self.trycompletions('DROP I', immediate='NDEX ') + self.trycompletions('DROP IN', immediate='DEX ') def test_complete_in_alter_keyspace(self): self.trycompletions('ALTER KEY', 'SPACE ') @@ -1184,9 +1184,15 @@ def test_complete_in_alter_type(self): self.trycompletions('ALTER TYPE IF EXISTS new_type ADD IF NOT EXISTS ', choices=['']) self.trycompletions('ALTER TYPE IF EXISTS new_type RENAME ', choices=['IF', '', '']) + # USER checks + def test_complete_in_create_user(self): + self.trycompletions('CREATE USER ', choices=['', 'IF']) + self.trycompletions('CREATE USER IF ', immediate='NOT EXISTS ') + def test_complete_in_alter_user(self): self.trycompletions('ALTER USER ', choices=['', 'IF', '', '']) + # ROLE checks def test_complete_in_create_role(self): self.trycompletions('CREATE ROLE ', choices=['', 'IF']) self.trycompletions('CREATE ROLE IF ', immediate='NOT EXISTS ') @@ -1205,18 +1211,43 @@ def test_complete_in_alter_role(self): self.trycompletions('ALTER ROLE foo WITH ACCESS TO ', choices=['ALL', 'DATACENTERS']) self.trycompletions('ALTER ROLE foo WITH ACCESS FROM ', choices=['ALL', 'CIDRS']) - def test_complete_in_create_user(self): - self.trycompletions('CREATE USER ', choices=['', 'IF']) - self.trycompletions('CREATE USER IF ', immediate='NOT EXISTS ') def test_complete_in_drop_role(self): self.trycompletions('DROP ROLE ', choices=['', 'IF', '']) + + # IDENTITY checks + def test_complete_in_add_identity(self): + self.trycompletions('ADD ID', immediate='ENTITY ') + self.trycompletions('ADD IDENTITY IF ', immediate='NOT EXISTS ') + self.trycompletions('ADD IDENTITY IF NOT ', immediate='EXISTS ') + self.trycompletions('ADD IDENTITY ', + choices=['', '', 'IF']) + self.trycompletions("ADD IDENTITY 'alice@example.com' TO R", immediate='OLE ') + self.trycompletions("ADD IDENTITY 'alice@example.com' ", immediate='TO ROLE ') + self.trycompletions("ADD IDENTITY 'alice@example.com' TO ROLE ", + choices=['', ''], other_choices_ok=True) + self.trycompletions("ADD IDENTITY IF NOT EXISTS 'alice@example.com' TO ROLE data_engineer ", + choices=[';']) + + def test_complete_in_drop_identity(self): + self.trycompletions('DROP IDENTITY ', + choices=['', '', 'IF']) + self.trycompletions('DROP IDENTITY IF ', immediate='EXISTS ') + self.trycompletions('DROP IDENTITY IF EXISTS ', + choices=['', '']) + self.trycompletions("DROP IDENTITY 'alice@example.com' ", choices=[';']) + self.trycompletions("DROP IDENTITY IF EXISTS 'alice@example.com' ", choices=[';']) + def test_complete_in_list(self): self.trycompletions('LIST ', choices=['ALL', 'AUTHORIZE', 'DESCRIBE', 'EXECUTE', 'ROLES', 'USERS', 'ALTER', 'CREATE', 'DROP', 'MODIFY', 'SELECT', 'UNMASK', 'SELECT_MASKED', 'SUPERUSERS']) + def test_complete_drop_end(self): + self.trycompletions("DROP USER 'alice@example.com' ", choices=[';']) + self.trycompletions("DROP USER IF EXISTS 'alice@example.com' ", choices=[';']) + # Non-CQL Shell Commands def test_complete_in_capture(self): From 55959b94d1df6d788de69433b00ab96f9d049b09 Mon Sep 17 00:00:00 2001 From: Shalni Sundram Date: Mon, 6 Oct 2025 10:55:21 -0700 Subject: [PATCH 4/7] add NOT EXISTS completion test to test_cqlsh_completion.py --- pylib/cqlshlib/test/test_cqlsh_completion.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py b/pylib/cqlshlib/test/test_cqlsh_completion.py index 2aafad844289..352c5516443d 100644 --- a/pylib/cqlshlib/test/test_cqlsh_completion.py +++ b/pylib/cqlshlib/test/test_cqlsh_completion.py @@ -1227,6 +1227,8 @@ def test_complete_in_add_identity(self): self.trycompletions("ADD IDENTITY 'alice@example.com' ", immediate='TO ROLE ') self.trycompletions("ADD IDENTITY 'alice@example.com' TO ROLE ", choices=['', ''], other_choices_ok=True) + self.trycompletions("ADD IDENTITY 'alice@example.com' TO ROLE data_engineer ", + choices=[';']) self.trycompletions("ADD IDENTITY IF NOT EXISTS 'alice@example.com' TO ROLE data_engineer ", choices=[';']) From 5a78cfd87d73f454e87f96cbafc03fa2d085e309 Mon Sep 17 00:00:00 2001 From: Shalni Sundram <55000893+shalnisundram@users.noreply.github.com> Date: Mon, 6 Oct 2025 10:58:47 -0700 Subject: [PATCH 5/7] Delete pylib/cqlshlib/test/test_identity_mappings_completion.py --- .../test/test_identity_mappings_completion.py | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 pylib/cqlshlib/test/test_identity_mappings_completion.py diff --git a/pylib/cqlshlib/test/test_identity_mappings_completion.py b/pylib/cqlshlib/test/test_identity_mappings_completion.py deleted file mode 100644 index 3b1c813d6984..000000000000 --- a/pylib/cqlshlib/test/test_identity_mappings_completion.py +++ /dev/null @@ -1,71 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .test_cqlsh_completion import CqlshCompletionCase - - -class TestIdentityMappingsCompletion(CqlshCompletionCase): - - """ - Autcomplete Tests for ADD and DROP Identity Mappings for @cql3handling.py - """ - - def test_identity_autocomplete_add(self): - self.trycompletions('ADD I', immediate='DENTITY ') - - def test_exists_autocomplete_add(self): - self.trycompletions('ADD IDENTITY IF ', immediate='NOT EXISTS ') - self.trycompletions('ADD IDENTITY IF NOT ', immediate='EXISTS ') - - def test_expect_str_literal_autocomplete_add(self): - self.trycompletions('ADD IDENTITY ', - choices=['', '', 'IF']) - - def test_TO_autocomplete_add(self): - self.trycompletions("ADD IDENTITY 'alice@example.com' ", immediate='TO ROLE ') - self.trycompletions("ADD IDENTITY 'alice@example.com' T", immediate='O ROLE ') - - def test_role_autocomplete_add(self): - self.trycompletions("ADD IDENTITY 'alice@example.com' TO ", immediate='ROLE ') - self.trycompletions("ADD IDENTITY 'alice@example.com' TO R", immediate='OLE ') - - def test_rolename_autocomplete_add(self): - self.trycompletions("ADD IDENTITY 'alice@example.com' TO ROLE ", - choices=['', ''], - other_choices_ok=True) - - def test_complete_user_full_statement_add(self): - self.trycompletions("ADD IDENTITY IF NOT EXISTS 'alice@example.com' TO ROLE data_engineer ", - choices=[';']) - - def test_autocomplete_drop(self): - self.trycompletions('DROP ', - choices=['AGGREGATE', 'COLUMNFAMILY', 'FUNCTION', - 'INDEX', 'KEYSPACE', 'ROLE', 'TABLE', - 'TRIGGER', 'TYPE', 'USER', 'MATERIALIZED', 'IDENTITY']) - - def test_identity_autcomplete_drop(self): - self.trycompletions('DROP IDENTITY ', - choices=['', '', 'IF']) - - def test_exists_str_literal_drop(self): - self.trycompletions('DROP IDENTITY IF ', immediate='EXISTS ') - self.trycompletions('DROP IDENTITY IF EXISTS ', - choices=['', '']) - - def test_complete_drop_IDENTITY_statement_end(self): - self.trycompletions("DROP IDENTITY 'alice@example.com' ", choices=[';']) - self.trycompletions("DROP IDENTITY IF EXISTS 'alice@example.com' ", choices=[';']) \ No newline at end of file From ee5eeb5af7058d7d3e0fcbc5471a6b7621707540 Mon Sep 17 00:00:00 2001 From: Shalni Sundram Date: Mon, 6 Oct 2025 17:59:08 -0700 Subject: [PATCH 6/7] add more ADD, DROP tests, correct identies in test_cqlsh_completion.py --- pylib/cqlshlib/cql3handling.py | 7 ++-- pylib/cqlshlib/test/test_cqlsh_completion.py | 37 ++++++++++---------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py index 3a61bb8ff5a1..362e84b27485 100644 --- a/pylib/cqlshlib/cql3handling.py +++ b/pylib/cqlshlib/cql3handling.py @@ -1769,11 +1769,10 @@ def drop_trigger_completer(ctxt, cass): syntax_rules += r''' - ::= "ADD" "IDENTITY" ("IF" "NOT" "EXISTS")? - "TO" "ROLE" - ; + ::= "ADD" "IDENTITY" ("IF" "NOT" "EXISTS")? "TO" "ROLE" + ; ::= "DROP" "IDENTITY" ("IF" "EXISTS")? - ; + ; ''' # END SYNTAX/COMPLETION RULE DEFINITIONS diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py b/pylib/cqlshlib/test/test_cqlsh_completion.py index 352c5516443d..f2c89857e145 100644 --- a/pylib/cqlshlib/test/test_cqlsh_completion.py +++ b/pylib/cqlshlib/test/test_cqlsh_completion.py @@ -1048,7 +1048,7 @@ def test_complete_in_use(self): 'system_virtual_schema', 'system_cluster_metadata']) def test_complete_in_create_index(self): - self.trycompletions('CREATE IN', immediate='DEX ') + self.trycompletions('CREATE I', immediate='NDEX ') self.trycompletions('CREATE INDEX ', choices=['', 'IF', 'ON']) self.trycompletions('CREATE INDEX example ', immediate='ON ') @@ -1184,15 +1184,9 @@ def test_complete_in_alter_type(self): self.trycompletions('ALTER TYPE IF EXISTS new_type ADD IF NOT EXISTS ', choices=['']) self.trycompletions('ALTER TYPE IF EXISTS new_type RENAME ', choices=['IF', '', '']) - # USER checks - def test_complete_in_create_user(self): - self.trycompletions('CREATE USER ', choices=['', 'IF']) - self.trycompletions('CREATE USER IF ', immediate='NOT EXISTS ') - def test_complete_in_alter_user(self): self.trycompletions('ALTER USER ', choices=['', 'IF', '', '']) - # ROLE checks def test_complete_in_create_role(self): self.trycompletions('CREATE ROLE ', choices=['', 'IF']) self.trycompletions('CREATE ROLE IF ', immediate='NOT EXISTS ') @@ -1211,45 +1205,50 @@ def test_complete_in_alter_role(self): self.trycompletions('ALTER ROLE foo WITH ACCESS TO ', choices=['ALL', 'DATACENTERS']) self.trycompletions('ALTER ROLE foo WITH ACCESS FROM ', choices=['ALL', 'CIDRS']) + def test_complete_in_create_user(self): + self.trycompletions('CREATE USER ', choices=['', 'IF']) + self.trycompletions('CREATE USER IF ', immediate='NOT EXISTS ') def test_complete_in_drop_role(self): self.trycompletions('DROP ROLE ', choices=['', 'IF', '']) - # IDENTITY checks def test_complete_in_add_identity(self): + self.trycompletions('A', choices=['ADD', 'ALTER']) + self.trycompletions('AD', immediate='D IDENTITY ') self.trycompletions('ADD ID', immediate='ENTITY ') self.trycompletions('ADD IDENTITY IF ', immediate='NOT EXISTS ') self.trycompletions('ADD IDENTITY IF NOT ', immediate='EXISTS ') self.trycompletions('ADD IDENTITY ', choices=['', '', 'IF']) - self.trycompletions("ADD IDENTITY 'alice@example.com' TO R", immediate='OLE ') - self.trycompletions("ADD IDENTITY 'alice@example.com' ", immediate='TO ROLE ') - self.trycompletions("ADD IDENTITY 'alice@example.com' TO ROLE ", + self.trycompletions("ADD IDENTITY 'testIdentifier' TO R", immediate='OLE ') + self.trycompletions("ADD IDENTITY 'testIdentifier' ", immediate='TO ROLE ') + self.trycompletions("ADD IDENTITY 'testIdentifier' TO ROLE ", choices=['', ''], other_choices_ok=True) - self.trycompletions("ADD IDENTITY 'alice@example.com' TO ROLE data_engineer ", + self.trycompletions("ADD IDENTITY 'testIdentifier' TO ROLE cassandra ", choices=[';']) - self.trycompletions("ADD IDENTITY IF NOT EXISTS 'alice@example.com' TO ROLE data_engineer ", + self.trycompletions("ADD IDENTITY IF NOT EXISTS 'stestIdentifier' TO ROLE cassandra ", choices=[';']) def test_complete_in_drop_identity(self): + self.trycompletions('D', choices=['DESCRIBE', 'DEBUG', 'DESC', 'DROP', 'DELETE']) + self.trycompletions('DR', immediate='OP ') + self.trycompletions('DRO', immediate='P ') + self.trycompletions('DROP ID', immediate='ENTITY ') + self.trycompletions('DROP', choices=' ') self.trycompletions('DROP IDENTITY ', choices=['', '', 'IF']) self.trycompletions('DROP IDENTITY IF ', immediate='EXISTS ') self.trycompletions('DROP IDENTITY IF EXISTS ', choices=['', '']) - self.trycompletions("DROP IDENTITY 'alice@example.com' ", choices=[';']) - self.trycompletions("DROP IDENTITY IF EXISTS 'alice@example.com' ", choices=[';']) + self.trycompletions("DROP IDENTITY 'testIdentifier' ", choices=[';']) + self.trycompletions("DROP IDENTITY IF EXISTS 'testIdentifier' ", choices=[';']) def test_complete_in_list(self): self.trycompletions('LIST ', choices=['ALL', 'AUTHORIZE', 'DESCRIBE', 'EXECUTE', 'ROLES', 'USERS', 'ALTER', 'CREATE', 'DROP', 'MODIFY', 'SELECT', 'UNMASK', 'SELECT_MASKED', 'SUPERUSERS']) - def test_complete_drop_end(self): - self.trycompletions("DROP USER 'alice@example.com' ", choices=[';']) - self.trycompletions("DROP USER IF EXISTS 'alice@example.com' ", choices=[';']) - # Non-CQL Shell Commands def test_complete_in_capture(self): From c434d9a5132f028f3c62ae7e368b651e2e19ec12 Mon Sep 17 00:00:00 2001 From: Shalni Sundram Date: Wed, 8 Oct 2025 14:38:56 -0700 Subject: [PATCH 7/7] include ADD keyword in test_complete_in_insert() choices set in test_cqlsh_completion.py --- pylib/cqlshlib/test/test_cqlsh_completion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py b/pylib/cqlshlib/test/test_cqlsh_completion.py index f2c89857e145..643f30539006 100644 --- a/pylib/cqlshlib/test/test_cqlsh_completion.py +++ b/pylib/cqlshlib/test/test_cqlsh_completion.py @@ -288,7 +288,7 @@ def test_complete_in_insert(self): self.trycompletions( ("INSERT INTO twenty_rows_composite_table (a, b, c) " "VALUES ( 'eggs', 'sausage', 'spam');"), - choices=['?', 'ALTER', 'BEGIN', 'CAPTURE', 'CONSISTENCY', 'COPY', + choices=['?', 'ADD', 'ALTER', 'BEGIN', 'CAPTURE', 'CONSISTENCY', 'COPY', 'CREATE', 'DEBUG', 'DELETE', 'DESC', 'DESCRIBE', 'DROP', 'ELAPSED', 'EXPAND', 'GRANT', 'HELP', 'INSERT', 'LIST', 'LOGIN', 'PAGING', 'REVOKE', 'SELECT', 'SHOW', 'SOURCE', 'SERIAL', 'TRACING',