From 5a63858d0d9896baab66b12f2d83f424e5c0fbfa Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Thu, 13 Sep 2012 14:01:41 -0500 Subject: [PATCH] cqlsh: suggesting cql3 to cql2 users when they get an error and their statement appears to parse for cql 2, and vice versa. Patch by paul cannon, reviewed by brandonwilliams for CASSANDRA-4454 --- bin/cqlsh | 23 +++++++++++++++++++++++ pylib/cqlshlib/pylexotron.py | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/bin/cqlsh b/bin/cqlsh index 65f1003f90..30e6505965 100755 --- a/bin/cqlsh +++ b/bin/cqlsh @@ -1027,6 +1027,18 @@ class Shell(cmd.Cmd): if trynum > self.num_retries: return False time.sleep(1*trynum) + except cql.ProgrammingError, err: + self.printerr(str(err)) + # try reparsing as cql3; if successful, suggest -3 + if self.cqlver_atleast(3): + if self.parseable_as_cql2(statement): + self.printerr("Perhaps you meant to use CQL 2? Try using" + " the -2 option when starting cqlsh.") + else: + if self.parseable_as_cql3(statement): + self.printerr("Perhaps you meant to use CQL 3? Try using" + " the -3 option when starting cqlsh.") + return False except CQL_ERRORS, err: self.printerr(str(err)) return False @@ -1041,6 +1053,17 @@ class Shell(cmd.Cmd): self.print_result(self.cursor) return True + # these next two functions are not guaranteed perfect; just checks if the + # statement parses fully according to cqlsh's own understanding of the + # grammar. Changes to the language in Cassandra frequently don't get + # updated in cqlsh right away. + + def parseable_as_cql3(self, statement): + return cql3handling.CqlRuleSet.lex_and_whole_match(statement) is not None + + def parseable_as_cql2(self, statement): + return cqlhandling.CqlRuleSet.lex_and_whole_match(statement) is not None + def determine_decoder_for(self, cfname, ksname=None): decoder = ErrorHandlingSchemaDecoder if ksname is None: diff --git a/pylib/cqlshlib/pylexotron.py b/pylib/cqlshlib/pylexotron.py index 0534c87042..e66d2a0cb6 100644 --- a/pylib/cqlshlib/pylexotron.py +++ b/pylib/cqlshlib/pylexotron.py @@ -446,6 +446,10 @@ class ParsingRuleSet: def lex_and_parse(self, text, startsymbol='Start'): return self.parse(startsymbol, self.lex(text), init_bindings={'*SRC*': text}) + def lex_and_whole_match(self, text, startsymbol='Start'): + tokens = self.lex(text) + return self.whole_match(startsymbol, tokens, srcstr=text) + def complete(self, startsymbol, tokens, init_bindings=None): if init_bindings is None: init_bindings = {}