From 1528798a5bb36187cf2b952b5b5a8b0982d262fb Mon Sep 17 00:00:00 2001 From: yziadeh Date: Tue, 3 Jan 2023 16:11:06 -0500 Subject: [PATCH] Add tests for CQL and cqlsh quote escaping Patch by Yaman Ziadeh; Reviewed by Paulo Motta and Brandom Williams for CASSANDRA-15458 --- pylib/cqlshlib/test/test_cqlsh_completion.py | 6 +-- pylib/cqlshlib/test/test_cqlsh_output.py | 48 +++++++++++++++++++ pylib/cqlshlib/test/test_keyspace_init.cql | 25 ++++++++-- .../validation/operations/SelectTest.java | 36 ++++++++++++++ 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py b/pylib/cqlshlib/test/test_cqlsh_completion.py index 6126566368..416e15ee69 100644 --- a/pylib/cqlshlib/test/test_cqlsh_completion.py +++ b/pylib/cqlshlib/test/test_cqlsh_completion.py @@ -574,7 +574,7 @@ class TestCqlshCompletion(CqlshCompletionCase): def test_complete_in_drop_type(self): self.trycompletions('DROP TYPE ', choices=['IF', 'system_views.', 'tags', 'system_traces.', 'system_distributed.', - 'phone_number', 'band_info_type', 'address', 'system.', 'system_schema.', + 'phone_number', 'quote_udt', 'band_info_type', 'address', 'system.', 'system_schema.', 'system_auth.', 'system_virtual_schema.', self.cqlsh.keyspace + '.' ]) @@ -951,7 +951,7 @@ class TestCqlshCompletion(CqlshCompletionCase): self.trycompletions('ALTER TABLE ', choices=['IF', 'twenty_rows_table', 'ascii_with_special_chars', 'users', 'has_all_types', 'system.', - 'empty_composite_table', 'empty_table', + 'empty_composite_table', 'escape_quotes', 'empty_table', 'system_auth.', 'undefined_values_table', 'dynamic_columns', 'twenty_rows_composite_table', @@ -971,7 +971,7 @@ class TestCqlshCompletion(CqlshCompletionCase): self.trycompletions('ALTER TYPE I', immediate='F EXISTS ') self.trycompletions('ALTER TYPE ', choices=['IF', 'system_views.', 'tags', 'system_traces.', 'system_distributed.', - 'phone_number', 'band_info_type', 'address', 'system.', 'system_schema.', + 'phone_number', 'quote_udt', 'band_info_type', 'address', 'system.', 'system_schema.', 'system_auth.', 'system_virtual_schema.', self.cqlsh.keyspace + '.' ]) self.trycompletions('ALTER TYPE IF EXISTS new_type ADD ', choices=['', 'IF']) diff --git a/pylib/cqlshlib/test/test_cqlsh_output.py b/pylib/cqlshlib/test/test_cqlsh_output.py index e8961f6321..9c4bbca49c 100644 --- a/pylib/cqlshlib/test/test_cqlsh_output.py +++ b/pylib/cqlshlib/test/test_cqlsh_output.py @@ -915,3 +915,51 @@ class TestCqlshOutput(BaseTestCase): row_headers = [s for s in output.splitlines() if "@ Row" in s] row_ids = [int(s.split(' ')[2]) for s in row_headers] self.assertEqual([i for i in range(1, 21)], row_ids) + + def test_quoted_output_text_in_map(self): + ks = get_keyspace() + + query = "SELECT text_data FROM " + ks + ".escape_quotes;" + output, result = testcall_cqlsh(prompt=None, env=self.default_env, + tty=False, input=query) + self.assertEqual(0, result) + self.assertEqual(output.splitlines()[3].strip(), "I'm newb") + + query = "SELECT map_data FROM " + ks + ".escape_quotes;" + output, result = testcall_cqlsh(prompt=None, env=self.default_env, + tty=False, input=query) + self.assertEqual(0, result) + self.assertEqual(output.splitlines()[3].strip(), "{1: 'I''m newb'}") + + def test_quoted_output_text_in_simple_collections(self): + ks = get_keyspace() + + # Sets + query = "SELECT set_data FROM " + ks + ".escape_quotes;" + output, result = testcall_cqlsh(prompt=None, env=self.default_env, + tty=False, input=query) + self.assertEqual(0, result) + self.assertEqual(output.splitlines()[3].strip(), "{'I''m newb'}") + + # Lists + query = "SELECT list_data FROM " + ks + ".escape_quotes;" + output, result = testcall_cqlsh(prompt=None, env=self.default_env, + tty=False, input=query) + self.assertEqual(0, result) + self.assertEqual(output.splitlines()[3].strip(), "['I''m newb']") + + # Tuples + query = "SELECT tuple_data FROM " + ks + ".escape_quotes;" + output, result = testcall_cqlsh(prompt=None, env=self.default_env, + tty=False, input=query) + self.assertEqual(0, result) + self.assertEqual(output.splitlines()[3].strip(), "(1, 'I''m newb')") + + def test_quoted_output_text_in_udts(self): + ks = get_keyspace() + + query = "SELECT udt_data FROM " + ks + ".escape_quotes;" + output, result = testcall_cqlsh(prompt=None, env=self.default_env, + tty=False, input=query) + self.assertEqual(0, result) + self.assertEqual(output.splitlines()[3].strip(), "{data: 'I''m newb'}") \ No newline at end of file diff --git a/pylib/cqlshlib/test/test_keyspace_init.cql b/pylib/cqlshlib/test/test_keyspace_init.cql index 3b9278ac0a..a100d346bf 100644 --- a/pylib/cqlshlib/test/test_keyspace_init.cql +++ b/pylib/cqlshlib/test/test_keyspace_init.cql @@ -279,26 +279,26 @@ values ( CREATE FUNCTION fBestband ( input double ) RETURNS NULL ON NULL INPUT - RETURNS text + RETURNS text LANGUAGE java AS 'return "Iron Maiden";'; CREATE FUNCTION fBestsong ( input double ) RETURNS NULL ON NULL INPUT - RETURNS text + RETURNS text LANGUAGE java AS 'return "Revelations";'; CREATE FUNCTION fMax(current int, candidate int) CALLED ON NULL INPUT - RETURNS int - LANGUAGE java + RETURNS int + LANGUAGE java AS 'if (current == null) return candidate; else return Math.max(current, candidate);' ; CREATE FUNCTION fMin(current int, candidate int) CALLED ON NULL INPUT RETURNS int - LANGUAGE java + LANGUAGE java AS 'if (current == null) return candidate; else return Math.min(current, candidate);' ; CREATE AGGREGATE aggMax(int) @@ -311,3 +311,18 @@ CREATE AGGREGATE aggMin(int) STYPE int INITCOND null; +CREATE TYPE quote_udt ( + data text +); + +CREATE TABLE escape_quotes ( + id int PRIMARY KEY, + text_data text, + map_data map, + set_data set, + list_data list, + tuple_data tuple, + udt_data frozen +); + +INSERT INTO escape_quotes (id, text_data, map_data, set_data, list_data, tuple_data, udt_data) values(1, 'I''m newb', {1:'I''m newb'}, {'I''m newb'}, ['I''m newb'], (1, 'I''m newb'), {data: 'I''m newb'}); \ No newline at end of file diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java index 7bbaa855f1..7bb20977c9 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java @@ -3191,4 +3191,40 @@ public class SelectTest extends CQLTester execute("INSERT INTO %s (k1, k2) VALUES (uuid(), 'k2')"); assertRowCount(execute("SELECT system.token(k1, k2) FROM %s"), 1); } + + @Test + public void testQuotedMapTextData() throws Throwable + { + createTable("CREATE TABLE " + KEYSPACE + ".t1 (id int, data text, PRIMARY KEY (id))"); + createTable("CREATE TABLE " + KEYSPACE + ".t2 (id int, data map, PRIMARY KEY (id))"); + + execute("INSERT INTO " + KEYSPACE + ".t1 (id, data) VALUES (1, 'I''m newb')"); + execute("INSERT INTO " + KEYSPACE + ".t2 (id, data) VALUES (1, {1:'I''m newb'})"); + + assertRows(execute("SELECT data FROM " + KEYSPACE + ".t1"), row("I'm newb")); + assertRows(execute("SELECT data FROM " + KEYSPACE + ".t2"), row( map(1, "I'm newb"))); + } + + @Test + public void testQuotedSimpleCollectionsData() throws Throwable + { + createTable("CREATE TABLE " + KEYSPACE + ".t3 (id int, set_data set, list_data list, tuple_data tuple, PRIMARY KEY (id))"); + + execute("INSERT INTO " + KEYSPACE + ".t3 (id, set_data, list_data, tuple_data) values(1, {'I''m newb'}, ['I''m newb'], (1, 'I''m newb'))"); + + assertRows(execute("SELECT set_data FROM " + KEYSPACE + ".t3"), row(set("I'm newb"))); + assertRows(execute("SELECT list_data FROM " + KEYSPACE + ".t3"), row(list("I'm newb"))); + assertRows(execute("SELECT tuple_data FROM " + KEYSPACE + ".t3"), row(tuple(1, "I'm newb"))); + } + + @Test + public void testQuotedUDTData() throws Throwable + { + createType("CREATE TYPE " + KEYSPACE + ".random (data text)"); + createTable("CREATE TABLE " + KEYSPACE + ".t4 (id int, udt_data frozen, PRIMARY KEY (id))"); + + execute("INSERT INTO " + KEYSPACE + ".t4 (id, udt_data) values(1, {data: 'I''m newb'})"); + + assertRows(execute("SELECT udt_data FROM " + KEYSPACE + ".t4"), row(userType("random", "I'm newb"))); + } }