You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2011/07/19 23:29:40 UTC

svn commit: r1148547 - in /cassandra/branches/cassandra-0.8: CHANGES.txt src/java/org/apache/cassandra/cql/Cql.g src/java/org/apache/cassandra/cql/DeleteStatement.java test/system/test_cql.py

Author: jbellis
Date: Tue Jul 19 21:29:39 2011
New Revision: 1148547

URL: http://svn.apache.org/viewvc?rev=1148547&view=rev
Log:
respect client timestamp on full row deletions
patch by slebresne; reviewed by pyaskevich for CASSANDRA-2912

Modified:
    cassandra/branches/cassandra-0.8/CHANGES.txt
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java
    cassandra/branches/cassandra-0.8/test/system/test_cql.py

Modified: cassandra/branches/cassandra-0.8/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/CHANGES.txt?rev=1148547&r1=1148546&r2=1148547&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.8/CHANGES.txt Tue Jul 19 21:29:39 2011
@@ -1,4 +1,7 @@
 0.8.2
+ * CQL: 
+   - include only one row per unique key for IN queries (CASSANDRA-2717)
+   - respect client timestamp on full row deletions (CASSANDRA-2912)
  * improve thread-safety in StreamOutSession (CASSANDRA-2792)
  * allow deleting a row and updating indexed columns in it in the
    same mutation (CASSANDRA-2773)
@@ -32,8 +35,6 @@
  * fix updating KS with durable_writes=false (CASSANDRA-2907)
  * add simplified facade to SSTableWriter for bulk loading use
    (CASSANDRA-2911)
- * CQL: include only one row per unique key for IN queries
-   (CASSANDRA-2717)
  * fix re-using index CF sstable names after drop/recreate (CASSANDRA-2872)
 
 

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g?rev=1148547&r1=1148546&r2=1148547&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g Tue Jul 19 21:29:39 2011
@@ -226,9 +226,17 @@ usingClause[Attributes attrs]
     : K_USING usingClauseObjective[attrs] ( K_AND? usingClauseObjective[attrs] )*
     ;
 
-usingClauseObjective[Attributes attrs]
+usingClauseDelete[Attributes attrs]
+    : K_USING usingClauseDeleteObjective[attrs] ( K_AND? usingClauseDeleteObjective[attrs] )*
+    ;
+
+usingClauseDeleteObjective[Attributes attrs]
     : K_CONSISTENCY K_LEVEL  { attrs.setConsistencyLevel(ConsistencyLevel.valueOf($K_LEVEL.text)); }
     | K_TIMESTAMP ts=INTEGER { attrs.setTimestamp(Long.valueOf($ts.text)); }
+    ;
+
+usingClauseObjective[Attributes attrs]
+    : usingClauseDeleteObjective[attrs]
     | K_TTL t=INTEGER        { attrs.setTimeToLive(Integer.parseInt($t.text)); }
     ;
 
@@ -319,22 +327,24 @@ updateStatement returns [UpdateStatement
  */
 deleteStatement returns [DeleteStatement expr]
     : {
-          ConsistencyLevel cLevel = null;
+          Attributes attrs = new Attributes();
           List<Term> keyList = null;
           List<Term> columnsList = Collections.emptyList();
       }
       K_DELETE
           ( cols=termList { columnsList = $cols.items; })?
           K_FROM columnFamily=( IDENT | STRING_LITERAL | INTEGER )
-          ( K_USING K_CONSISTENCY K_LEVEL { cLevel = ConsistencyLevel.valueOf($K_LEVEL.text); } )?
+          ( usingClauseDelete[attrs] )?
           K_WHERE ( key_alias=term ('=' key=term           { keyList = Collections.singletonList(key); }
                                    | K_IN '(' keys=termList { keyList = $keys.items; } ')')
                   )?
       {
-          return new DeleteStatement(columnsList, $columnFamily.text, key_alias.getText(), cLevel, keyList);
+          return new DeleteStatement(columnsList, $columnFamily.text, key_alias.getText(), keyList, attrs);
       }
     ;
 
+
+
 /** CREATE KEYSPACE <KEYSPACE> WITH attr1 = value1 AND attr2 = value2; */
 createKeyspaceStatement returns [CreateKeyspaceStatement expr]
     : {

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java?rev=1148547&r1=1148546&r2=1148547&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java Tue Jul 19 21:29:39 2011
@@ -47,9 +47,9 @@ public class DeleteStatement extends Abs
     private List<Term> columns;
     private List<Term> keys;
     
-    public DeleteStatement(List<Term> columns, String columnFamily, String keyName, ConsistencyLevel cLevel, List<Term> keys)
+    public DeleteStatement(List<Term> columns, String columnFamily, String keyName, List<Term> keys, Attributes attrs)
     {
-        super(columnFamily, keyName, cLevel, null, 0);
+        super(columnFamily, keyName, attrs);
 
         this.columns = columns;
         this.keys = keys;
@@ -107,7 +107,7 @@ public class DeleteStatement extends Abs
         AbstractType comparator = metadata.getComparatorFor(null);
 
         if (columns.size() < 1) // No columns, delete the row
-            mutation.delete(new QueryPath(columnFamily), System.currentTimeMillis());
+            mutation.delete(new QueryPath(columnFamily), (timestamp == null) ? getTimestamp() : timestamp);
         else    // Delete specific columns
         {
             for (Term column : columns)

Modified: cassandra/branches/cassandra-0.8/test/system/test_cql.py
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/test/system/test_cql.py?rev=1148547&r1=1148546&r2=1148547&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/test/system/test_cql.py (original)
+++ cassandra/branches/cassandra-0.8/test/system/test_cql.py Tue Jul 19 21:29:39 2011
@@ -1050,6 +1050,68 @@ class TestCql(ThriftTester):
         r = cursor.fetchone()
         assert len(r) == 1, "expected 0 results, got %d" % len(r)
 
+    def test_delete_with_timestamp(self):
+        "delete statement should support setting timestamp"
+        cursor = init()
+        cursor.compression = 'NONE'
+
+        # insert to the StandardString1
+        cursor.execute("UPDATE StandardString1 USING TIMESTAMP 10 SET name = 'name here' WHERE KEY = 'TimestampedUser3'")
+
+        # try to read it
+        cursor.execute("SELECT * FROM StandardString1 WHERE KEY = 'TimestampedUser3'")
+        assert cursor.rowcount == 1, "expected 1 results, got %d" % cursor.rowcount
+        colnames = [col_d[0] for col_d in cursor.description]
+
+        assert colnames[1] == "name", \
+               "unrecognized name '%s'" % colnames[1]
+
+        r = cursor.fetchone()
+        assert r[1] == "name here", \
+               "unrecognized value '%s'" % r[1]
+
+        # DELETE with a lower TIMESTAMP
+        cursor.execute("DELETE 'name here' FROM StandardString1 USING TIMESTAMP 3 WHERE KEY = 'TimestampedUser3'")
+
+        # try to read it
+        cursor.execute("SELECT * FROM StandardString1 WHERE KEY = 'TimestampedUser3'")
+        assert cursor.rowcount == 1, "expected 1 results, got %d" % cursor.rowcount
+        colnames = [col_d[0] for col_d in cursor.description]
+
+        assert len(colnames) == 2, "expected 2 columns, got %d" % len(colnames)
+        assert colnames[1] == "name", \
+               "unrecognized name '%s'" % colnames[1]
+
+        r = cursor.fetchone()
+        assert r[1] == "name here", \
+               "unrecognized value '%s'" % r[1]
+
+        # now DELETE the whole row with a lower TIMESTAMP
+        cursor.execute("DELETE FROM StandardString1 USING TIMESTAMP 3 WHERE KEY = 'TimestampedUser3'")
+
+        # try to read it
+        cursor.execute("SELECT * FROM StandardString1 WHERE KEY = 'TimestampedUser3'")
+        assert cursor.rowcount == 1, "expected 1 results, got %d" % cursor.rowcount
+        colnames = [col_d[0] for col_d in cursor.description]
+
+        assert len(colnames) == 2, "expected 2 columns, got %d" % len(colnames)
+        assert colnames[1] == "name", \
+               "unrecognized name '%s'" % colnames[1]
+
+        r = cursor.fetchone()
+        assert r[1] == "name here", \
+               "unrecognized value '%s'" % r[1]
+
+        # now DELETE the row with a greater TIMESTAMP
+        cursor.execute("DELETE FROM StandardString1 USING TIMESTAMP 15 WHERE KEY = 'TimestampedUser3'")
+        # try to read it
+        cursor.execute("SELECT * FROM StandardString1 WHERE KEY = 'TimestampedUser3'")
+        assert cursor.rowcount == 1, "expected 1 results, got %d" % cursor.rowcount
+        colnames = [col_d[0] for col_d in cursor.description]
+
+        assert len(colnames) == 1, "expected only the KEY column, got %d" % len(colnames)
+        assert colnames[0] == "KEY", "unrecognized name '%s'" % colnames[0]
+
     def test_alter_table_statement(self):
         "test ALTER statement"
         cursor = init()