Repository: cassandra
Updated Branches:
  refs/heads/trunk f6ef8ef4d -> 9a4f6bdf0


cqlsh: Fix handling of CAS statement results

Patch by Tyler Hobbs; reviewed by Aleksey Yeschenko for CASSANDRA-7671


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/d586ea89
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/d586ea89
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/d586ea89

Branch: refs/heads/trunk
Commit: d586ea89800ddbba38eea3bd08e2d107bf765344
Parents: f36d1b5
Author: Tyler Hobbs <ty...@datastax.com>
Authored: Thu Aug 21 11:54:47 2014 -0500
Committer: Tyler Hobbs <ty...@datastax.com>
Committed: Thu Aug 21 11:54:47 2014 -0500

----------------------------------------------------------------------
 CHANGES.txt                    |  1 +
 bin/cqlsh                      | 34 ++++++++++++++++++----------------
 pylib/cqlshlib/cql3handling.py | 13 +++++++++++--
 pylib/cqlshlib/pylexotron.py   |  4 +++-
 4 files changed, 33 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/d586ea89/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 2320653..11ec7ff 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.1.1
+ * (cqlsh) Fix handling of CAS statement results (CASSANDRA-7671)
  * (cqlsh) COPY TO/FROM improvements (CASSANDRA-7405)
  * Support list index operations with conditions (CASSANDRA-7499)
  * Add max live/tombstoned cells to nodetool cfstats output (CASSANDRA-7731)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d586ea89/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 340566d..b633e93 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -585,13 +585,13 @@ class Shell(cmd.Cmd):
             self.decoding_errors.append(err)
             return format_value(err, self.output_codec.name, 
addcolor=self.color)
 
-    def myformat_colname(self, name, cfMetaData = None):
+    def myformat_colname(self, name, table_meta=None):
         column_colors = COLUMN_NAME_COLORS.copy()
         # check column role and color appropriately
-        if cfMetaData:
-            if name in [col.name for col in cfMetaData.partition_key]:
+        if table_meta:
+            if name in [col.name for col in table_meta.partition_key]:
                 column_colors.default_factory = lambda : RED
-            elif name in [col.name for col in cfMetaData.clustering_key]:
+            elif name in [col.name for col in table_meta.clustering_key]:
                 column_colors.default_factory = lambda : CYAN
         return self.myformat_value(name, colormap=column_colors)
 
@@ -913,6 +913,12 @@ class Shell(cmd.Cmd):
 
         return result
 
+    def parse_for_table_meta(self, query_string):
+        parsed = cqlruleset.cql_parse(query_string)[1]
+        ks =  self.cql_unprotect_name(parsed.get_binding('ksname', None))
+        cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
+        return self.get_table_meta(ks, cf)
+
     def perform_simple_statement(self, statement, with_default_limit=False):
         if not statement:
             return False
@@ -930,25 +936,21 @@ class Shell(cmd.Cmd):
                 return False
 
         if statement.query_string[:6].lower() == 'select' or 
statement.query_string.lower().startswith("list"):
-            parsed = cqlruleset.cql_parse(statement.query_string)[1]
-            ks =  self.cql_unprotect_name(parsed.get_binding('ksname', None))
-            cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
-            cfMetaData = self.get_table_meta(ks, cf)
-            self.print_result(rows, with_default_limit, cfMetaData)
+            self.print_result(rows, with_default_limit, 
self.parse_for_table_meta(statement.query_string))
         elif rows:
             # CAS INSERT/UPDATE
             self.writeresult("")
-            self.print_static_result(rows)
+            self.print_static_result(rows, 
self.parse_for_table_meta(statement.query_string))
         self.flush_output()
         return True
 
-    def print_result(self, rows, with_default_limit, cfMetaData):
+    def print_result(self, rows, with_default_limit, table_meta):
         self.decoding_errors = []
 
         self.writeresult("")
         if rows:
             rows = list(rows)  # this may be an iterator if the result is 
large enough to page
-        self.print_static_result(rows, cfMetaData)
+        self.print_static_result(rows, table_meta)
         self.writeresult("(%d rows)" % len(rows or []))
 
         if self.decoding_errors:
@@ -965,16 +967,16 @@ class Shell(cmd.Cmd):
                                  % DEFAULT_SELECT_LIMIT, color=RED)
                 self.writeresult("")
 
-    def print_static_result(self, rows, cfMetaData):
+    def print_static_result(self, rows, table_meta):
         if not rows:
             # print header only
-            colnames = cfMetaData.columns.keys()  # full header
-            formatted_names = [self.myformat_colname(name, cfMetaData) for 
name in colnames]
+            colnames = table_meta.columns.keys()  # full header
+            formatted_names = [self.myformat_colname(name, table_meta) for 
name in colnames]
             self.print_formatted_result(formatted_names, None)
             return
 
         colnames = rows[0].keys()
-        formatted_names = [self.myformat_colname(name, cfMetaData) for name in 
colnames]
+        formatted_names = [self.myformat_colname(name, table_meta) for name in 
colnames]
         formatted_values = [map(self.myformat_value, row.values()) for row in 
rows]
 
         if self.expand_enabled:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d586ea89/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 0888d64..e4ef67b 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -185,6 +185,7 @@ JUNK ::= /([ 
\t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ;
          | <blobLiteral>
          | <collectionLiteral>
          | <functionName> <functionArguments>
+         | "NULL"
          ;
 
 <functionArguments> ::= "(" ( <term> ( "," <term> )* )? ")"
@@ -673,6 +674,7 @@ syntax_rules += r'''
                                    ( "," [colname]=<cident> )* ")"
                       "VALUES" "(" [newval]=<term> valcomma="," [newval]=<term>
                                    ( valcomma="," [newval]=<term> )* 
valcomma=")"
+                      ( "IF" "NOT" "EXISTS")?
                       ( "USING" [insertopt]=<usingOption>
                                 ( "AND" [insertopt]=<usingOption> )* )?
                     ;
@@ -741,13 +743,19 @@ syntax_rules += r'''
                                   ( "AND" [updateopt]=<usingOption> )* )?
                         "SET" <assignment> ( "," <assignment> )*
                         "WHERE" <whereClause>
+                        ( "IF" <conditions> )?
                     ;
 <assignment> ::= updatecol=<cident>
-                    ( "=" update_rhs=( <value> | <cident> )
+                    ( "=" update_rhs=( <term> | <cident> )
                                 ( counterop=( "+" | "-" ) inc=<wholenumber>
-                                | listadder="+" listcol=<cident> )
+                                | listadder="+" listcol=<cident> )?
                     | indexbracket="[" <term> "]" "=" <term> )
                ;
+<conditions> ::=  <condition> ( "AND" <condition> )*
+               ;
+<condition> ::= <cident> ( "[" <term> "]" )? ( ( "=" | "<" | ">" | "<=" | ">=" 
| "!=" ) <term>
+                                             | "IN" "(" <term> ( "," <term> )* 
")")
+              ;
 '''
 
 @completer_for('updateStatement', 'updateopt')
@@ -819,6 +827,7 @@ syntax_rules += r'''
                         "FROM" cf=<columnFamilyName>
                         ( "USING" [delopt]=<deleteOption> )?
                         "WHERE" <whereClause>
+                        ( "IF" ( "EXISTS" | <conditions> ) )?
                     ;
 <deleteSelector> ::= delcol=<cident> ( memberbracket="[" memberselector=<term> 
"]" )?
                    ;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d586ea89/pylib/cqlshlib/pylexotron.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/pylexotron.py b/pylib/cqlshlib/pylexotron.py
index ad283df..b4ac36f 100644
--- a/pylib/cqlshlib/pylexotron.py
+++ b/pylib/cqlshlib/pylexotron.py
@@ -14,7 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from functools import partial
 import re
 from .saferscanner import SaferScanner
 
@@ -24,6 +23,9 @@ class LexingError(Exception):
         bad_char = len(rulestr) - len(unmatched)
         linenum = rulestr[:bad_char].count('\n') + 1
         charnum = len(rulestr[:bad_char].rsplit('\n', 1)[-1]) + 1
+        snippet_start = max(0, min(len(rulestr), bad_char - 10))
+        snippet_end = max(0, min(len(rulestr), bad_char + 10))
+        msg += " (Error at: '...%s...')" % 
(rulestr[snippet_start:snippet_end],)
         raise cls(linenum, charnum, msg)
 
     def __init__(self, linenum, charnum, msg='Lexing error'):

Reply via email to