You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2016/06/21 14:34:05 UTC

[1/4] cassandra git commit: Remove distinction between non-existing static columns and existing but null in LWTs

Repository: cassandra
Updated Branches:
  refs/heads/trunk 5382f4ec3 -> 448389207


Remove distinction between non-existing static columns and existing but null in LWTs

Path by Alex Petrov; reviewed by Benjamin Lerer for CASSANDRA-9842


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

Branch: refs/heads/trunk
Commit: 85f2bbfd1c6803977ecc1c2053527363078bce22
Parents: a56bc16
Author: Alex Petrov <ol...@gmail.com>
Authored: Tue Jun 21 16:22:23 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:22:23 2016 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cql3/statements/ModificationStatement.java  |   5 +-
 .../apache/cassandra/service/StorageProxy.java  |   5 +-
 .../operations/InsertUpdateIfConditionTest.java | 291 ++++++++++++++++++-
 4 files changed, 298 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 64cfdaa..7944967 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.1.15
+ * Remove distinction between non-existing static columns and existing but null in LWTs (CASSANDRA-9842)
  * Support mlockall on IBM POWER arch (CASSANDRA-11576)
  * Cache local ranges when calculating repair neighbors (CASSANDRA-11933)
  * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
index a9f65e1..f84188a 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -697,10 +697,11 @@ public abstract class ModificationStatement implements CQLStatement
 
         Row row = readCommand.getRow(keyspace);
         ColumnFamily current = row.cf;
+        if (current == null)
+            current = ArrayBackedSortedColumns.factory.create(metadata);
+
         if (!request.appliesTo(current))
         {
-            if (current == null)
-                current = ArrayBackedSortedColumns.factory.create(metadata);
             return current;
         }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/src/java/org/apache/cassandra/service/StorageProxy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java b/src/java/org/apache/cassandra/service/StorageProxy.java
index 58a2874..845a732 100644
--- a/src/java/org/apache/cassandra/service/StorageProxy.java
+++ b/src/java/org/apache/cassandra/service/StorageProxy.java
@@ -233,12 +233,15 @@ public class StorageProxy implements StorageProxyMBean
                                                                   ? ConsistencyLevel.LOCAL_QUORUM
                                                                   : ConsistencyLevel.QUORUM);
                 ColumnFamily current = rows.get(0).cf;
+                if (current == null)
+                    current = ArrayBackedSortedColumns.factory.create(metadata);
+
                 if (!request.appliesTo(current))
                 {
                     Tracing.trace("CAS precondition does not match current values {}", current);
                     // We should not return null as this means success
                     casWriteMetrics.conditionNotMet.inc();
-                    return current == null ? ArrayBackedSortedColumns.factory.create(metadata) : current;
+                    return current;
                 }
 
                 // finish the paxos round w/ the desired updates

http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index 05ba09d..900cc7d 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@ -140,7 +140,7 @@ public class InsertUpdateIfConditionTest extends CQLTester
     @Test
     public void testConditionalDelete() throws Throwable
     {
-        createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int,)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int)");
 
         assertRows(execute("DELETE FROM %s WHERE k=1 IF EXISTS"), row(false));
 
@@ -981,4 +981,293 @@ public class InsertUpdateIfConditionTest extends CQLTester
         execute("DROP TYPE IF EXISTS mytype");
         assertEmpty(execute("SELECT type_name from system.schema_usertypes where keyspace_name = ? and type_name = ?", KEYSPACE, "mytype"));
     }
+
+    @Test
+    public void testConditionalUpdatesOnStaticColumns() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+        // pre-existing row
+        execute("INSERT INTO %s (a, b, s, d) values (6, 6, 100, 'a')");
+        assertRows(execute("UPDATE %s SET s = 6 WHERE a = 6 IF s = 100"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+                   row(6, 6, 6, "a"));
+
+        // pre-existing row with null in the static column
+        execute("INSERT INTO %s (a, b, d) values (7, 7, 'a')");
+        assertRows(execute("UPDATE %s SET s = 7 WHERE a = 7 IF s = NULL"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+                   row(7, 7, 7, "a"));
+
+        // deleting row before CAS
+        execute("DELETE FROM %s WHERE a = 8;");
+        assertRows(execute("UPDATE %s SET s = 8 WHERE a = 8 IF s = NULL"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 8"),
+                   row(8, null, 8, null));
+    }
+
+    @Test
+    public void testConditionalUpdatesWithNullValues() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+        // pre-populate, leave out static column
+        for (int i = 1; i <= 5; i++)
+            execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+
+        conditionalUpdatesWithNonExistingOrNullValues();
+
+        // rejected: IN doesn't contain null
+        assertRows(execute("UPDATE %s SET s = 30 WHERE a = 3 IF s IN (10,20,30)"),
+                   row(false));
+        assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+                   row(3, 3, null, null));
+
+        // rejected: comparing number with NULL always returns false
+        for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+        {
+            assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+                       row(false));
+            assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                       row(5, 5, null, null));
+        }
+
+    }
+
+    @Test
+    public void testConditionalUpdatesWithNonExistingValues() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+        conditionalUpdatesWithNonExistingOrNullValues();
+
+        // rejected: IN doesn't contain null
+        assertRows(execute("UPDATE %s SET s = 3 WHERE a = 3 IF s IN (10,20,30)"),
+                   row(false));
+        assertEmpty(execute("SELECT a, s, d FROM %s WHERE a = 3"));
+
+        // rejected: comparing number with NULL always returns false
+        for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+        {
+            assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+                       row(false));
+            assertEmpty(execute("SELECT * FROM %s WHERE a = 5"));
+        }
+    }
+
+    private void conditionalUpdatesWithNonExistingOrNullValues() throws Throwable
+    {
+        assertRows(execute("UPDATE %s SET s = 1 WHERE a = 1 IF s = NULL"),
+                   row(true));
+        assertRows(execute("SELECT a, s, d FROM %s WHERE a = 1"),
+                   row(1, 1, null));
+
+        assertRows(execute("UPDATE %s SET s = 2 WHERE a = 2 IF s IN (10,20,NULL)"),
+                   row(true));
+        assertRows(execute("SELECT a, s, d FROM %s WHERE a = 2"),
+                   row(2, 2, null));
+
+        assertRows(execute("UPDATE %s SET s = 4 WHERE a = 4 IF s != 4"),
+                   row(true));
+        assertRows(execute("SELECT a, s, d FROM %s WHERE a = 4"),
+                   row(4, 4, null));
+    }
+
+    @Test
+    public void testConditionalUpdatesWithNullValuesWithBatch() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+        // pre-populate, leave out static column
+        for (int i = 1; i <= 6; i++)
+            execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+
+        testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+
+        // rejected: comparing number with null value always returns false
+        for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+        {
+            assertRows(execute("BEGIN BATCH\n"
+                               + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 40, 'a');\n"
+                               + "UPDATE %1$s SET s = 30 WHERE a = 3 IF s " + operator + " 5;\n"
+                               + "APPLY BATCH"),
+                       row(false));
+            assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+                       row(3, 3, null, null));
+        }
+
+        // rejected: IN doesn't contain null
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 70, 'a');\n"
+                           + "UPDATE %1$s SET s = 60 WHERE a = 6 IF s IN (1,2,3);\n"
+                           + "APPLY BATCH"),
+                   row(false));
+        assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+                   row(6, 6, null, null));
+
+    }
+
+    @Test
+    public void testConditionalUpdatesWithNonExistingValuesWithBatch() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+        testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+
+        // rejected: comparing number with non-existing value always returns false
+        for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+        {
+            assertRows(execute("BEGIN BATCH\n"
+                               + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 3, 'a');\n"
+                               + "UPDATE %1$s SET s = 3 WHERE a = 3 IF s " + operator + " 5;\n"
+                               + "APPLY BATCH"),
+                       row(false));
+            assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+        }
+
+        // rejected: IN doesn't contain null
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 6, 'a');\n"
+                           + "UPDATE %1$s SET s = 7 WHERE a = 6 IF s IN (1,2,3);\n"
+                           + "APPLY BATCH"),
+                   row(false));
+        assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+    }
+
+    private void testConditionalUpdatesWithNonExistingOrNullValuesWithBatch() throws Throwable
+    {
+        // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, d) values (2, 2, 'a');\n"
+                           + "UPDATE %1$s SET s = 2 WHERE a = 2 IF s = null;\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+                   row(2, 2, 2, "a"));
+
+        // applied: lwt condition is executed before INSERT, update is applied after it
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s, d) values (4, 4, 4, 'a');\n"
+                           + "UPDATE %1$s SET s = 5 WHERE a = 4 IF s = null;\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+                   row(4, 4, 5, "a"));
+
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s, d) values (5, 5, 5, 'a');\n"
+                           + "UPDATE %1$s SET s = 6 WHERE a = 5 IF s IN (1,2,null);\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                   row(5, 5, 6, "a"));
+
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s, d) values (7, 7, 7, 'a');\n"
+                           + "UPDATE %1$s SET s = 8 WHERE a = 7 IF s != 7;\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+                   row(7, 7, 8, "a"));
+    }
+
+    @Test
+    public void testConditionalDeleteWithNullValues() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+
+        for (int i = 1; i <= 5; i++)
+            execute("INSERT INTO %s (a, b, s1, s2, v) VALUES (?, ?, ?, ?, ?)", i, i, i, null, i);
+
+        assertRows(execute("DELETE s1 FROM %s WHERE a = 1 IF s2 = NULL"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 1"),
+                   row(1, 1, null, null, 1));
+
+        // rejected: IN doesn't contain null
+        assertRows(execute("DELETE s1 FROM %s WHERE a = 2 IF s2 IN (10,20,30)"),
+                   row(false, null));
+        assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+                   row(2, 2, 2, null, 2));
+
+        assertRows(execute("DELETE s1 FROM %s WHERE a = 3 IF s2 IN (NULL,20,30)"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+                   row(3, 3, null, null, 3));
+
+        assertRows(execute("DELETE s1 FROM %s WHERE a = 4 IF s2 != 4"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+                   row(4, 4, null, null, 4));
+
+        // rejected: comparing number with NULL always returns false
+        for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+        {
+            assertRows(execute("DELETE s1 FROM %s WHERE a = 5 IF s2 " + operator + " 3"),
+                       row(false, null));
+            assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                       row(5, 5, 5, null, 5));
+        }
+    }
+
+    @Test
+    public void testConditionalDeletesWithNonExistingValuesWithBatch() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+
+        // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s1, v) values (2, 2, 2, 2);\n"
+                           + "DELETE s1 FROM %1$s WHERE a = 2 IF s2 = null;\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+                   row(2, 2, null, null, 2));
+
+        // rejected: comparing number with non-existing value always returns false
+        for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+        {
+            assertRows(execute("BEGIN BATCH\n"
+                               + "INSERT INTO %1$s (a, b, s1, v) values (3, 3, 3, 3);\n"
+                               + "DELETE s1 FROM %1$s WHERE a = 3 IF s2 " + operator + " 5;\n"
+                               + "APPLY BATCH"),
+                       row(false));
+            assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+        }
+
+        // rejected: IN doesn't contain null
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s1, v) values (6, 6, 6, 6);\n"
+                           + "DELETE s1 FROM %1$s WHERE a = 6 IF s2 IN (1,2,3);\n"
+                           + "APPLY BATCH"),
+                   row(false));
+        assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s1, v) values (4, 4, 4, 4);\n"
+                           + "DELETE s1 FROM %1$s WHERE a = 4 IF s2 = null;\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+                   row(4, 4, null, null, 4));
+
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s1, v) VALUES (5, 5, 5, 5);\n"
+                           + "DELETE s1 FROM %1$s WHERE a = 5 IF s1 IN (1,2,null);\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                   row(5, 5, null, null, 5));
+
+        assertRows(execute("BEGIN BATCH\n"
+                           + "INSERT INTO %1$s (a, b, s1, v) values (7, 7, 7, 7);\n"
+                           + "DELETE s1 FROM %1$s WHERE a = 7 IF s2 != 7;\n"
+                           + "APPLY BATCH"),
+                   row(true));
+        assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+                   row(7, 7, null, null, 7));
+    }
 }


[3/4] cassandra git commit: Merge branch cassandra-2.2 into cassandra-3.0

Posted by bl...@apache.org.
Merge branch cassandra-2.2 into cassandra-3.0


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

Branch: refs/heads/trunk
Commit: 723a143c9d71ba8b3450cad8a0ad178f133a3869
Parents: b657223 5a09627
Author: Benjamin Lerer <b....@gmail.com>
Authored: Tue Jun 21 16:28:25 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:30:06 2016 +0200

----------------------------------------------------------------------
 .../operations/InsertUpdateIfConditionTest.java | 290 +++++++++++++++++++
 1 file changed, 290 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/723a143c/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index 2d59a11,fc6cc2e..a1ee4f8
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@@ -23,10 -23,8 +23,11 @@@ import org.junit.Test
  import org.apache.cassandra.cql3.CQLTester;
  import org.apache.cassandra.exceptions.InvalidRequestException;
  import org.apache.cassandra.exceptions.SyntaxException;
 +import org.apache.cassandra.schema.SchemaKeyspace;
  
 +import static java.lang.String.format;
  import static org.junit.Assert.assertEquals;
++import static org.junit.Assert.assertThat;
  import static org.junit.Assert.assertTrue;
  
  public class InsertUpdateIfConditionTest extends CQLTester
@@@ -1018,10 -979,295 +1019,299 @@@
  
          // drop and confirm
          execute("DROP TYPE IF EXISTS mytype");
 -        assertEmpty(execute("SELECT type_name from system.schema_usertypes where keyspace_name = ? and type_name = ?", KEYSPACE, "mytype"));
 +        assertEmpty(execute(format("SELECT type_name from %s.%s where keyspace_name = ? and type_name = ?",
 +                                   SchemaKeyspace.NAME,
 +                                   SchemaKeyspace.TYPES),
 +                            KEYSPACE,
 +                            "mytype"));
      }
+ 
+     @Test
+     public void testConditionalUpdatesOnStaticColumns() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+ 
+         // pre-existing row
+         execute("INSERT INTO %s (a, b, s, d) values (6, 6, 100, 'a')");
+         assertRows(execute("UPDATE %s SET s = 6 WHERE a = 6 IF s = 100"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+                    row(6, 6, 6, "a"));
+ 
+         // pre-existing row with null in the static column
+         execute("INSERT INTO %s (a, b, d) values (7, 7, 'a')");
+         assertRows(execute("UPDATE %s SET s = 7 WHERE a = 7 IF s = NULL"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+                    row(7, 7, 7, "a"));
+ 
+         // deleting row before CAS
+         execute("DELETE FROM %s WHERE a = 8;");
+         assertRows(execute("UPDATE %s SET s = 8 WHERE a = 8 IF s = NULL"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 8"),
+                    row(8, null, 8, null));
+     }
+ 
+     @Test
+     public void testConditionalUpdatesWithNullValues() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+ 
+         // pre-populate, leave out static column
+         for (int i = 1; i <= 5; i++)
+             execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+ 
+         conditionalUpdatesWithNonExistingOrNullValues();
+ 
+         // rejected: IN doesn't contain null
+         assertRows(execute("UPDATE %s SET s = 30 WHERE a = 3 IF s IN (10,20,30)"),
+                    row(false));
+         assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+                    row(3, 3, null, null));
+ 
+         // rejected: comparing number with NULL always returns false
+         for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+         {
+             assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+                        row(false));
+             assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                        row(5, 5, null, null));
+         }
+ 
+     }
+ 
+     @Test
+     public void testConditionalUpdatesWithNonExistingValues() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+ 
+         conditionalUpdatesWithNonExistingOrNullValues();
+ 
+         // rejected: IN doesn't contain null
+         assertRows(execute("UPDATE %s SET s = 3 WHERE a = 3 IF s IN (10,20,30)"),
+                    row(false));
+         assertEmpty(execute("SELECT a, s, d FROM %s WHERE a = 3"));
+ 
+         // rejected: comparing number with NULL always returns false
+         for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+         {
+             assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+                        row(false));
+             assertEmpty(execute("SELECT * FROM %s WHERE a = 5"));
+         }
+     }
+ 
+     private void conditionalUpdatesWithNonExistingOrNullValues() throws Throwable
+     {
+         assertRows(execute("UPDATE %s SET s = 1 WHERE a = 1 IF s = NULL"),
+                    row(true));
+         assertRows(execute("SELECT a, s, d FROM %s WHERE a = 1"),
+                    row(1, 1, null));
+ 
+         assertRows(execute("UPDATE %s SET s = 2 WHERE a = 2 IF s IN (10,20,NULL)"),
+                    row(true));
+         assertRows(execute("SELECT a, s, d FROM %s WHERE a = 2"),
+                    row(2, 2, null));
+ 
+         assertRows(execute("UPDATE %s SET s = 4 WHERE a = 4 IF s != 4"),
+                    row(true));
+         assertRows(execute("SELECT a, s, d FROM %s WHERE a = 4"),
+                    row(4, 4, null));
+     }
+ 
+     @Test
+     public void testConditionalUpdatesWithNullValuesWithBatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+ 
+         // pre-populate, leave out static column
+         for (int i = 1; i <= 6; i++)
+             execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+ 
+         testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+ 
+         // rejected: comparing number with null value always returns false
+         for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+         {
+             assertRows(execute("BEGIN BATCH\n"
+                                + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 40, 'a');\n"
+                                + "UPDATE %1$s SET s = 30 WHERE a = 3 IF s " + operator + " 5;\n"
+                                + "APPLY BATCH"),
+                        row(false));
+             assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+                        row(3, 3, null, null));
+         }
+ 
+         // rejected: IN doesn't contain null
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 70, 'a');\n"
+                            + "UPDATE %1$s SET s = 60 WHERE a = 6 IF s IN (1,2,3);\n"
+                            + "APPLY BATCH"),
+                    row(false));
+         assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+                    row(6, 6, null, null));
+ 
+     }
+ 
+     @Test
+     public void testConditionalUpdatesWithNonExistingValuesWithBatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+ 
+         testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+ 
+         // rejected: comparing number with non-existing value always returns false
+         for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+         {
+             assertRows(execute("BEGIN BATCH\n"
+                                + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 3, 'a');\n"
+                                + "UPDATE %1$s SET s = 3 WHERE a = 3 IF s " + operator + " 5;\n"
+                                + "APPLY BATCH"),
+                        row(false));
+             assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+         }
+ 
+         // rejected: IN doesn't contain null
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 6, 'a');\n"
+                            + "UPDATE %1$s SET s = 7 WHERE a = 6 IF s IN (1,2,3);\n"
+                            + "APPLY BATCH"),
+                    row(false));
+         assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+     }
+ 
+     private void testConditionalUpdatesWithNonExistingOrNullValuesWithBatch() throws Throwable
+     {
+         // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, d) values (2, 2, 'a');\n"
+                            + "UPDATE %1$s SET s = 2 WHERE a = 2 IF s = null;\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+                    row(2, 2, 2, "a"));
+ 
+         // applied: lwt condition is executed before INSERT, update is applied after it
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s, d) values (4, 4, 4, 'a');\n"
+                            + "UPDATE %1$s SET s = 5 WHERE a = 4 IF s = null;\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+                    row(4, 4, 5, "a"));
+ 
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s, d) values (5, 5, 5, 'a');\n"
+                            + "UPDATE %1$s SET s = 6 WHERE a = 5 IF s IN (1,2,null);\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                    row(5, 5, 6, "a"));
+ 
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s, d) values (7, 7, 7, 'a');\n"
+                            + "UPDATE %1$s SET s = 8 WHERE a = 7 IF s != 7;\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+                    row(7, 7, 8, "a"));
+     }
+ 
+     @Test
+     public void testConditionalDeleteWithNullValues() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+ 
+         for (int i = 1; i <= 5; i++)
+             execute("INSERT INTO %s (a, b, s1, s2, v) VALUES (?, ?, ?, ?, ?)", i, i, i, null, i);
+ 
+         assertRows(execute("DELETE s1 FROM %s WHERE a = 1 IF s2 = NULL"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 1"),
+                    row(1, 1, null, null, 1));
+ 
+         // rejected: IN doesn't contain null
+         assertRows(execute("DELETE s1 FROM %s WHERE a = 2 IF s2 IN (10,20,30)"),
 -                   row(false, null));
++                   row(false));
+         assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+                    row(2, 2, 2, null, 2));
+ 
+         assertRows(execute("DELETE s1 FROM %s WHERE a = 3 IF s2 IN (NULL,20,30)"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+                    row(3, 3, null, null, 3));
+ 
+         assertRows(execute("DELETE s1 FROM %s WHERE a = 4 IF s2 != 4"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+                    row(4, 4, null, null, 4));
+ 
+         // rejected: comparing number with NULL always returns false
+         for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+         {
+             assertRows(execute("DELETE s1 FROM %s WHERE a = 5 IF s2 " + operator + " 3"),
 -                       row(false, null));
++                       row(false));
+             assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                        row(5, 5, 5, null, 5));
+         }
+     }
+ 
+     @Test
+     public void testConditionalDeletesWithNonExistingValuesWithBatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+ 
+         // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s1, v) values (2, 2, 2, 2);\n"
+                            + "DELETE s1 FROM %1$s WHERE a = 2 IF s2 = null;\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+                    row(2, 2, null, null, 2));
+ 
+         // rejected: comparing number with non-existing value always returns false
+         for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+         {
+             assertRows(execute("BEGIN BATCH\n"
+                                + "INSERT INTO %1$s (a, b, s1, v) values (3, 3, 3, 3);\n"
+                                + "DELETE s1 FROM %1$s WHERE a = 3 IF s2 " + operator + " 5;\n"
+                                + "APPLY BATCH"),
+                        row(false));
+             assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+         }
+ 
+         // rejected: IN doesn't contain null
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s1, v) values (6, 6, 6, 6);\n"
+                            + "DELETE s1 FROM %1$s WHERE a = 6 IF s2 IN (1,2,3);\n"
+                            + "APPLY BATCH"),
+                    row(false));
+         assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+ 
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s1, v) values (4, 4, 4, 4);\n"
+                            + "DELETE s1 FROM %1$s WHERE a = 4 IF s2 = null;\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+                    row(4, 4, null, null, 4));
+ 
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s1, v) VALUES (5, 5, 5, 5);\n"
+                            + "DELETE s1 FROM %1$s WHERE a = 5 IF s1 IN (1,2,null);\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+                    row(5, 5, null, null, 5));
+ 
+         assertRows(execute("BEGIN BATCH\n"
+                            + "INSERT INTO %1$s (a, b, s1, v) values (7, 7, 7, 7);\n"
+                            + "DELETE s1 FROM %1$s WHERE a = 7 IF s2 != 7;\n"
+                            + "APPLY BATCH"),
+                    row(true));
+         assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+                    row(7, 7, null, null, 7));
+     }
  }


[2/4] cassandra git commit: Merge branch cassandra-2.1 into cassandra-2.2

Posted by bl...@apache.org.
Merge branch cassandra-2.1 into cassandra-2.2


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

Branch: refs/heads/trunk
Commit: 5a096274dc592c35efe0dfaa12bf4bc40b02402b
Parents: 68398ad 85f2bbf
Author: Benjamin Lerer <b....@gmail.com>
Authored: Tue Jun 21 16:25:23 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:25:23 2016 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |   5 +
 .../cql3/statements/ModificationStatement.java  |   5 +-
 .../apache/cassandra/service/StorageProxy.java  |   5 +-
 .../operations/InsertUpdateIfConditionTest.java | 291 ++++++++++++++++++-
 4 files changed, 302 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index ef993fe,7944967..fe4728d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,32 -1,5 +1,37 @@@
++<<<<<<< HEAD
 +2.2.7
 + * RandomAccessReader: call isEOF() only when rebuffering, not for every read operation (CASSANDRA-12013)
 + * Don't send erroneous NEW_NODE notifications on restart (CASSANDRA-11038)
 + * StorageService shutdown hook should use a volatile variable (CASSANDRA-11984)
 + * Persist local metadata earlier in startup sequence (CASSANDRA-11742)
 + * Run CommitLog tests with different compression settings (CASSANDRA-9039)
 + * cqlsh: fix tab completion for case-sensitive identifiers (CASSANDRA-11664)
 + * Avoid showing estimated key as -1 in tablestats (CASSANDRA-11587)
 + * Fix possible race condition in CommitLog.recover (CASSANDRA-11743)
 + * Enable client encryption in sstableloader with cli options (CASSANDRA-11708)
 + * Possible memory leak in NIODataInputStream (CASSANDRA-11867)
 + * Fix commit log replay after out-of-order flush completion (CASSANDRA-9669)
 + * Add seconds to cqlsh tracing session duration (CASSANDRA-11753)
 + * Prohibit Reverse Counter type as part of the PK (CASSANDRA-9395)
 + * cqlsh: correctly handle non-ascii chars in error messages (CASSANDRA-11626)
 + * Exit JVM if JMX server fails to startup (CASSANDRA-11540)
 + * Produce a heap dump when exiting on OOM (CASSANDRA-9861)
 + * Avoid read repairing purgeable tombstones on range slices (CASSANDRA-11427)
 + * Restore ability to filter on clustering columns when using a 2i (CASSANDRA-11510)
 + * JSON datetime formatting needs timezone (CASSANDRA-11137)
 + * Fix is_dense recalculation for Thrift-updated tables (CASSANDRA-11502)
 + * Remove unnescessary file existence check during anticompaction (CASSANDRA-11660)
 + * Add missing files to debian packages (CASSANDRA-11642)
 + * Avoid calling Iterables::concat in loops during ModificationStatement::getFunctions (CASSANDRA-11621)
 + * cqlsh: COPY FROM should use regular inserts for single statement batches and
 +   report errors correctly if workers processes crash on initialization (CASSANDRA-11474)
 + * Always close cluster with connection in CqlRecordWriter (CASSANDRA-11553)
 + * Fix slice queries on ordered COMPACT tables (CASSANDRA-10988)
 +Merged from 2.1:
++=======
+ 2.1.15
+  * Remove distinction between non-existing static columns and existing but null in LWTs (CASSANDRA-9842)
++>>>>>>> asf/cassandra-2.1
   * Support mlockall on IBM POWER arch (CASSANDRA-11576)
   * Cache local ranges when calculating repair neighbors (CASSANDRA-11933)
   * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/src/java/org/apache/cassandra/service/StorageProxy.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------


[4/4] cassandra git commit: Merge branch cassandra-3.0 into trunk

Posted by bl...@apache.org.
Merge branch cassandra-3.0 into trunk


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

Branch: refs/heads/trunk
Commit: 44838920709e0333ec105c299fa8cbb1f0905f93
Parents: 5382f4e 723a143
Author: Benjamin Lerer <b....@gmail.com>
Authored: Tue Jun 21 16:33:12 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:33:25 2016 +0200

----------------------------------------------------------------------
 .../operations/InsertUpdateIfConditionTest.java | 290 +++++++++++++++++++
 1 file changed, 290 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/44838920/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------