Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 dab0e31ba -> fb606dd41


Fix UPDATE queries with empty IN restrictions

patch by Benjamin Lerer; reviewed by Alex Petrov for CASSANDRA-13152


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

Branch: refs/heads/cassandra-3.0
Commit: fb606dd41c9f14324749efc1344421237c36a6db
Parents: dab0e31
Author: Benjamin Lerer <[email protected]>
Authored: Tue Feb 7 10:35:48 2017 +0100
Committer: Benjamin Lerer <[email protected]>
Committed: Tue Feb 7 10:35:48 2017 +0100

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../cql3/statements/ModificationStatement.java  |  4 ++
 .../cql3/validation/operations/DeleteTest.java  | 54 ++++++++++++++++++++
 .../cql3/validation/operations/UpdateTest.java  | 53 ++++++++++++++++++-
 4 files changed, 111 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/fb606dd4/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 1a90b1f..4387019 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.11
+ * Fix UPDATE queries with empty IN restrictions (CASSANDRA-13152)
  * Abort or retry on failed hints delivery (CASSANDRA-13124)
  * Fix handling of partition with partition-level deletion plus
    live rows in sstabledump (CASSANDRA-13177)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fb606dd4/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 acfa16b..1722f02 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -657,6 +657,10 @@ public abstract class ModificationStatement implements 
CQLStatement
         {
             NavigableSet<Clustering> clusterings = createClustering(options);
 
+            // If some of the restrictions were unspecified (e.g. empty IN 
restrictions) we do not need to do anything.
+            if (restrictions.hasClusteringColumnsRestriction() && 
clusterings.isEmpty())
+                return;
+
             UpdateParameters params = makeUpdateParameters(keys, clusterings, 
options, local, now);
 
             for (ByteBuffer key : keys)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fb606dd4/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java 
b/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
index 18a6ca3..09098ac 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
@@ -28,11 +28,14 @@ import org.apache.commons.lang3.StringUtils;
 import org.junit.Test;
 
 import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.Keyspace;
 
 import static org.apache.cassandra.utils.ByteBufferUtil.EMPTY_BYTE_BUFFER;
 import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
 import static org.apache.commons.lang3.StringUtils.isEmpty;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 public class DeleteTest extends CQLTester
 {
@@ -1247,4 +1250,55 @@ public class DeleteTest extends CQLTester
                    row(1, 1, 1, 3, 3),
                    row(1, 1, 1, 4, 4));
     }
+
+    /**
+     * Test for CASSANDRA-13152
+     */
+    @Test
+    public void testThatDeletesWithEmptyInRestrictionDoNotCreateMutations() 
throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY 
(a,b))");
+
+        execute("DELETE FROM %s WHERE a IN ();");
+        execute("DELETE FROM %s WHERE a IN () AND b IN ();");
+        execute("DELETE FROM %s WHERE a IN () AND b = 1;");
+        execute("DELETE FROM %s WHERE a = 1 AND b IN ();");
+
+        assertTrue("The memtable should be empty but is not", 
isMemtableEmpty());
+
+        createTable("CREATE TABLE %s (a int, b int, c int, d int, s int 
static, PRIMARY KEY ((a,b), c))");
+
+        execute("DELETE FROM %s WHERE a = 1 AND b = 1 AND c IN ();");
+        execute("DELETE FROM %s WHERE a = 1 AND b IN () AND c IN ();");
+        execute("DELETE FROM %s WHERE a IN () AND b IN () AND c IN ();");
+        execute("DELETE FROM %s WHERE a IN () AND b = 1 AND c IN ();");
+        execute("DELETE FROM %s WHERE a IN () AND b IN () AND c = 1;");
+
+        assertTrue("The memtable should be empty but is not", 
isMemtableEmpty());
+
+        createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, 
PRIMARY KEY ((a,b), c, d))");
+
+        execute("DELETE FROM %s WHERE a = 1 AND b = 1 AND c IN ();");
+        execute("DELETE FROM %s WHERE a = 1 AND b = 1 AND c = 1 AND d IN ();");
+        execute("DELETE FROM %s WHERE a = 1 AND b = 1 AND c IN () AND d IN 
();");
+        execute("DELETE FROM %s WHERE a = 1 AND b IN () AND c IN () AND d IN 
();");
+        execute("DELETE FROM %s WHERE a IN () AND b IN () AND c IN () AND d IN 
();");
+        execute("DELETE FROM %s WHERE a IN () AND b IN () AND c IN () AND d = 
1;");
+        execute("DELETE FROM %s WHERE a IN () AND b IN () AND c = 1 AND d = 
1;");
+        execute("DELETE FROM %s WHERE a IN () AND b IN () AND c = 1 AND d IN 
();");
+        execute("DELETE FROM %s WHERE a IN () AND b = 1");
+
+        assertTrue("The memtable should be empty but is not", 
isMemtableEmpty());
+    }
+
+    /**
+     * Checks if the memtable is empty or not
+     * @return {@code true} if the memtable is empty, {@code false} otherwise.
+     */
+    private boolean isMemtableEmpty()
+    {
+        Keyspace keyspace = Keyspace.open(KEYSPACE);
+        ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(currentTable());
+        return cfs.metric.allMemtablesLiveDataSize.getValue() == 0;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/fb606dd4/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java 
b/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
index 0d81fa3..a49f828 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
@@ -20,11 +20,15 @@ package org.apache.cassandra.cql3.validation.operations;
 
 import java.util.Arrays;
 
+import org.junit.Assert;
 import org.junit.Test;
 
 import static org.apache.commons.lang3.StringUtils.isEmpty;
+import static org.junit.Assert.assertTrue;
+
 import org.apache.cassandra.cql3.CQLTester;
-import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.Keyspace;
 
 public class UpdateTest extends CQLTester
 {
@@ -557,4 +561,51 @@ public class UpdateTest extends CQLTester
                    row(1,1,1,3,3),
                    row(1,1,1,4,4));
     }
+
+    /**
+     * Test for CASSANDRA-13152
+     */
+    @Test
+    public void testThatUpdatesWithEmptyInRestrictionDoNotCreateMutations() 
throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY 
(a,b))");
+
+        execute("UPDATE %s SET c = 100 WHERE a IN () AND b = 1;");
+        execute("UPDATE %s SET c = 100 WHERE a = 1 AND b IN ();");
+
+        assertTrue("The memtable should be empty but is not", 
isMemtableEmpty());
+
+        createTable("CREATE TABLE %s (a int, b int, c int, d int, s int 
static, PRIMARY KEY ((a,b), c))");
+
+        execute("UPDATE %s SET d = 100 WHERE a = 1 AND b = 1 AND c IN ();");
+        execute("UPDATE %s SET d = 100 WHERE a = 1 AND b IN () AND c IN ();");
+        execute("UPDATE %s SET d = 100 WHERE a IN () AND b IN () AND c IN 
();");
+        execute("UPDATE %s SET d = 100 WHERE a IN () AND b IN () AND c = 1;");
+        execute("UPDATE %s SET d = 100 WHERE a IN () AND b = 1 AND c IN ();");
+
+        assertTrue("The memtable should be empty but is not", 
isMemtableEmpty());
+
+        createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, 
PRIMARY KEY ((a,b), c, d))");
+
+        execute("UPDATE %s SET e = 100 WHERE a = 1 AND b = 1 AND c = 1 AND d 
IN ();");
+        execute("UPDATE %s SET e = 100 WHERE a = 1 AND b = 1 AND c IN () AND d 
IN ();");
+        execute("UPDATE %s SET e = 100 WHERE a = 1 AND b IN () AND c IN () AND 
d IN ();");
+        execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c IN () 
AND d IN ();");
+        execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c IN () 
AND d = 1;");
+        execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c = 1 AND 
d = 1;");
+        execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c = 1 AND 
d IN ();");
+
+        assertTrue("The memtable should be empty but is not", 
isMemtableEmpty());
+    }
+
+    /**
+     * Checks if the memtable is empty or not
+     * @return {@code true} if the memtable is empty, {@code false} otherwise.
+     */
+    private boolean isMemtableEmpty()
+    {
+        Keyspace keyspace = Keyspace.open(KEYSPACE);
+        ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(currentTable());
+        return cfs.metric.allMemtablesLiveDataSize.getValue() == 0;
+    }
 }

Reply via email to