diff --git a/CHANGES.txt b/CHANGES.txt index 19c81ed8e7..c5e70c6edc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.0.14 + * Fix text containing "/*" being interpreted as multiline comment in cqlsh (CASSANDRA-17667) * Fix indexing of a frozen collection that is the clustering key and reversed (CASSANDRA-19889) * Emit error when altering a table with non-frozen UDTs with nested non-frozen collections the same way as done upon table creation (CASSANDRA-19925) * Safer handling of out-of-range tokens (CASSANDRA-13704) diff --git a/bin/cqlsh.py b/bin/cqlsh.py index dddbd397fa..51a46c7982 100755 --- a/bin/cqlsh.py +++ b/bin/cqlsh.py @@ -509,7 +509,6 @@ class Shell(cmd.Cmd): self.statement = StringIO() self.lineno = 1 - self.in_comment = False self.prompt = '' if stdin is None: @@ -915,30 +914,12 @@ class Shell(cmd.Cmd): self.reset_statement() print('') - def strip_comment_blocks(self, statementtext): - comment_block_in_literal_string = re.search('["].*[/][*].*[*][/].*["]', statementtext) - if not comment_block_in_literal_string: - result = re.sub('[/][*].*[*][/]', "", statementtext) - if '*/' in result and '/*' not in result and not self.in_comment: - raise SyntaxError("Encountered comment block terminator without being in comment block") - if '/*' in result: - result = re.sub('[/][*].*', "", result) - self.in_comment = True - if '*/' in result: - result = re.sub('.*[*][/]', "", result) - self.in_comment = False - if self.in_comment and not re.findall('[/][*]|[*][/]', statementtext): - result = '' - return result - return statementtext - def onecmd(self, statementtext): """ Returns true if the statement is complete and was handled (meaning it can be reset). """ statementtext = ensure_text(statementtext) - statementtext = self.strip_comment_blocks(statementtext) try: statements, endtoken_escaped = cqlruleset.cql_split_statements(statementtext) except pylexotron.LexingError as e: diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py index c45b310215..3d1b16386f 100644 --- a/pylib/cqlshlib/cql3handling.py +++ b/pylib/cqlshlib/cql3handling.py @@ -162,7 +162,9 @@ syntax_rules = r''' ::= [statements]= ";" ; -# the order of these terminal productions is significant: +# The order of these terminal productions is significant. The input string is matched to the rule +# specified first in the grammar. + ::= /\n/ ; JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ; @@ -172,6 +174,12 @@ JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ; ::= /'([^']|'')*'/ ; ::= /\$\$(?:(?!\$\$).)*\$\$/; ::= /"([^"]|"")*"/ ; + +::= /\$\$(?:(?!\$\$).)*/ ; + ::= /'([^']|'')*/ ; + ::= /"([^"]|"")*/ ; + ::= /[/][*].*$/ ; + ::= /-?[0-9]+\.[0-9]+/ ; ::= /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ ; ::= /0x[0-9a-f]+/ ; @@ -189,11 +197,6 @@ JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ; | "false" ; -::= /\$\$(?:(?!\$\$).)*/ ; - ::= /'([^']|'')*/ ; - ::= /"([^"]|"")*/ ; - ::= /[/][*].*$/ ; - ::= | | diff --git a/pylib/cqlshlib/test/test_cql_parsing.py b/pylib/cqlshlib/test/test_cql_parsing.py index 8631d7aee6..43952a8d7f 100644 --- a/pylib/cqlshlib/test/test_cql_parsing.py +++ b/pylib/cqlshlib/test/test_cql_parsing.py @@ -771,6 +771,31 @@ class TestCqlParsing(TestCase): ('"/*MyTable*/"', 'quotedName'), (';', 'endtoken')]) + parsed = parse_cqlsh_statements(''' + INSERT into a (key,c1,c2) VALUES ('aKey','v1*/','/v2/*/v3'); + ''') + + self.assertSequenceEqual(tokens_with_types(parsed), + [('INSERT', 'reserved_identifier'), + ('into', 'reserved_identifier'), + ('a', 'identifier'), + ('(', 'op'), + ('key', 'identifier'), + (',', 'op'), + ('c1', 'identifier'), + (',', 'op'), + ('c2', 'identifier'), + (')', 'op'), + ('VALUES', 'identifier'), + ('(', 'op'), + ("'aKey'", 'quotedStringLiteral'), + (',', 'op'), + ("'v1*/'", 'quotedStringLiteral'), + (',', 'op'), + ("'/v2/*/v3'", 'quotedStringLiteral'), + (')', 'op'), + (';', 'endtoken')]) + parse_cqlsh_statements(''' */ SELECT FROM "MyTable"; ''')