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

[1/7] cassandra git commit: Allow LWT operation on static column with only partition keys

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 0d5984b9d -> a91219e12
  refs/heads/trunk b2352189f -> bdd8e8ade


Allow LWT operation on static column with only partition keys

Patch by Carl Yeksigian, reviewed by Benjamin Lerer for CASSANDRA-10532


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

Branch: refs/heads/cassandra-3.0
Commit: 1d2d0749a8b72c4c8cdd5b85b210157e8d7d6a41
Parents: 72acbcd
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Jun 14 08:32:26 2016 -0400
Committer: Carl Yeksigian <ca...@apache.org>
Committed: Tue Jun 14 08:32:26 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cql3/statements/DeleteStatement.java        |  37 +++---
 .../cql3/statements/ModificationStatement.java  |  14 ++-
 .../operations/InsertUpdateIfConditionTest.java | 113 +++++++++++++++++++
 4 files changed, 150 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index ebcc90c..7d70902 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.1.15
+ * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
  * Create interval tree over canonical sstables to avoid missing sstables during streaming (CASSANDRA-11886)
  * cqlsh COPY FROM: shutdown parent cluster after forking, to avoid corrupting SSL connections (CASSANDRA-11749)
  * Updated cqlsh Python driver to fix DESCRIBE problem for legacy tables (CASSANDRA-11055)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
index 33c61e7..d8fa467 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
@@ -50,15 +50,6 @@ public class DeleteStatement extends ModificationStatement
     {
         List<Operation> deletions = getOperations();
 
-        if (prefix.size() < cfm.clusteringColumns().size() && !deletions.isEmpty())
-        {
-            // In general, we can't delete specific columns if not all clustering columns have been specified.
-            // However, if we delete only static colums, it's fine since we won't really use the prefix anyway.
-            for (Operation deletion : deletions)
-                if (!deletion.column.isStatic())
-                    throw new InvalidRequestException(String.format("Primary key column '%s' must be specified in order to delete column '%s'", getFirstEmptyKey().name, deletion.column.name));
-        }
-
         if (deletions.isEmpty())
         {
             // We delete the slice selected by the prefix.
@@ -88,19 +79,39 @@ public class DeleteStatement extends ModificationStatement
 
     protected void validateWhereClauseForConditions() throws InvalidRequestException
     {
-        Iterator<ColumnDefinition> iterator = Iterators.concat(cfm.partitionKeyColumns().iterator(), cfm.clusteringColumns().iterator());
+        boolean onlyHasConditionsOnStaticColumns = hasStaticConditions() && !hasRegularConditions();
+
+        // In general, we can't delete specific columns if not all clustering columns have been specified.
+        // However, if we delete only static colums, it's fine since we won't really use the prefix anyway.
+        Iterator<ColumnDefinition> iterator = appliesOnlyToStaticColumns()
+                                              ? cfm.partitionKeyColumns().iterator()
+                                              : Iterators.concat(cfm.partitionKeyColumns().iterator(), cfm.clusteringColumns().iterator());
         while (iterator.hasNext())
         {
             ColumnDefinition def = iterator.next();
             Restriction restriction = processedKeys.get(def.name);
             if (restriction == null || !(restriction.isEQ() || restriction.isIN()))
             {
+                if (onlyHasConditionsOnStaticColumns)
+                {
+                    for (Operation oper : getOperations())
+                    {
+                        if (!oper.column.isStatic())
+                        {
+                            throw new InvalidRequestException(String.format("Primary key column '%s' must be specified in order to delete column '%s'",
+                                                                            def.name,
+                                                                            oper.column.name));
+                        }
+                    }
+                }
+
                 throw new InvalidRequestException(
-                        String.format("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order " +
-                                      "to use IF conditions, but column '%s' is not restricted", def.name));
+                        String.format("DELETE statements must restrict all %s KEY columns with equality relations in order " +
+                                      "to use IF conditions%s, but column '%s' is not restricted",
+                                      onlyHasConditionsOnStaticColumns ? "PARTITION" : "PRIMARY",
+                                      onlyHasConditionsOnStaticColumns ? " on static columns" : "", def.name));
             }
         }
-
     }
 
     public static class Parsed extends ModificationStatement.Parsed

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/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 75a3b40..a9f65e1 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -211,6 +211,16 @@ public abstract class ModificationStatement implements CQLStatement
         return ifExists;
     }
 
+    public boolean hasStaticConditions()
+    {
+        return staticConditions != null && !staticConditions.isEmpty();
+    }
+
+    public boolean hasRegularConditions()
+    {
+        return columnConditions != null && !columnConditions.isEmpty();
+    }
+
     private void addKeyValues(ColumnDefinition def, Restriction values) throws InvalidRequestException
     {
         if (def.kind == ColumnDefinition.Kind.CLUSTERING_COLUMN)
@@ -364,7 +374,7 @@ public abstract class ModificationStatement implements CQLStatement
      * Checks that the modification only apply to static columns.
      * @return <code>true</code> if the modification only apply to static columns, <code>false</code> otherwise.
      */
-    private boolean appliesOnlyToStaticColumns()
+    protected boolean appliesOnlyToStaticColumns()
     {
         return setsStaticColumns && !appliesToRegularColumns();
     }
@@ -373,7 +383,7 @@ public abstract class ModificationStatement implements CQLStatement
      * Checks that the modification apply to regular columns.
      * @return <code>true</code> if the modification apply to regular columns, <code>false</code> otherwise.
      */
-    private boolean appliesToRegularColumns()
+    protected boolean appliesToRegularColumns()
     {
         // If we have regular operations, this applies to regular columns.
         // Otherwise, if the statement is a DELETE and columnOperations is empty, this means we have no operations,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/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 e94011b..05ba09d 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@ -311,6 +311,119 @@ public class InsertUpdateIfConditionTest extends CQLTester
     }
 
     /**
+     * Test CASSANDRA-10532
+     */
+    @Test
+    public void testStaticColumnsCasDelete() throws Throwable
+    {
+        createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+        execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 2), row(false, 1));
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 1), row(true));
+
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, null, 2),
+                   row(1, 3, null, 4),
+                   row(1, 5, null, 6),
+                   row(1, 7, null, 8));
+        execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+
+        assertInvalidMessage("DELETE statements must restrict all PARTITION KEY columns with equality relations in order " +
+                             "to use IF conditions on static columns, but column 'pk' is not restricted",
+                             "DELETE static_col FROM %s WHERE ck = ? IF static_col = ?", 1, 1);
+
+        assertInvalidMessage("Invalid restriction on clustering column ck since the DELETE statement modifies only static columns",
+                             "DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF static_col = ?", 1, 1, 1);
+
+        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
+                             "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 1);
+
+        // Same query but with an invalid condition
+        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
+                             "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 2);
+
+        // DELETE of an underspecified PRIMARY KEY should not succeed if static is not only restriction
+        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order " +
+                             "to use IF conditions, but column 'ck' is not restricted",
+                             "DELETE static_col FROM %s WHERE pk = ? IF value = ? AND static_col = ?", 1, 2, 1);
+
+        assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 2), row(false, 2, 1));
+        assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 1), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 1, null),
+                   row(1, 3, 1, 4),
+                   row(1, 5, 1, 6),
+                   row(1, 7, 1, 8));
+
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 10), row(false, 6));
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 6), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, null, null),
+                   row(1, 3, null, 4),
+                   row(1, 5, null, 6),
+                   row(1, 7, null, 8));
+    }
+
+    @Test
+    public void testStaticColumnsCasUpdate() throws Throwable
+    {
+        createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+        execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 3, 1, 2), row(false, 1));
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 2, 1, 1), row(true));
+
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 2, 2),
+                   row(1, 3, 2, 4),
+                   row(1, 5, 2, 6),
+                   row(1, 7, 2, 8));
+
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part pk",
+                             "UPDATE %s SET static_col = ? WHERE ck = ? IF static_col = ?", 3, 1, 1);
+
+        assertInvalidMessage("Invalid restriction on clustering column ck since the UPDATE statement modifies only static columns",
+                             "UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF static_col = ?", 3, 1, 1, 1);
+
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
+                             "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 2);
+
+        // Same query but with an invalid condition
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
+                             "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 1);
+
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
+                             "UPDATE %s SET static_col = ? WHERE pk = ? IF value = ? AND static_col = ?", 3, 1, 4, 2);
+
+        assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 3, 1, 1, 3, 2), row(false, 2, 2));
+        assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 1, 2, 2), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 2, 1),
+                   row(1, 3, 2, 4),
+                   row(1, 5, 2, 6),
+                   row(1, 7, 2, 8));
+
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 3, 1, 1, 2), row(false, 1));
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 1, 1, 1, 1), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 1, 1),
+                   row(1, 3, 1, 4),
+                   row(1, 5, 1, 6),
+                   row(1, 7, 1, 8));
+    }
+
+    /**
      * Migrated from cql_tests.py:TestCQL.bug_6069_test()
      */
     @Test


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

Posted by ca...@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/bdd8e8ad
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/bdd8e8ad
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/bdd8e8ad

Branch: refs/heads/trunk
Commit: bdd8e8ade7914a6ab04297763b4329102f6fcfc9
Parents: b235218 a91219e
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Jun 14 10:35:09 2016 -0400
Committer: Carl Yeksigian <ca...@apache.org>
Committed: Tue Jun 14 10:35:09 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cql3/statements/DeleteStatement.java        |  15 ++-
 .../operations/InsertUpdateIfConditionTest.java | 120 ++++++++++++++++++-
 3 files changed, 128 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/bdd8e8ad/CHANGES.txt
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/bdd8e8ad/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------

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


[2/7] cassandra git commit: Allow LWT operation on static column with only partition keys

Posted by ca...@apache.org.
Allow LWT operation on static column with only partition keys

Patch by Carl Yeksigian, reviewed by Benjamin Lerer for CASSANDRA-10532


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

Branch: refs/heads/trunk
Commit: 1d2d0749a8b72c4c8cdd5b85b210157e8d7d6a41
Parents: 72acbcd
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Jun 14 08:32:26 2016 -0400
Committer: Carl Yeksigian <ca...@apache.org>
Committed: Tue Jun 14 08:32:26 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cql3/statements/DeleteStatement.java        |  37 +++---
 .../cql3/statements/ModificationStatement.java  |  14 ++-
 .../operations/InsertUpdateIfConditionTest.java | 113 +++++++++++++++++++
 4 files changed, 150 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index ebcc90c..7d70902 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.1.15
+ * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
  * Create interval tree over canonical sstables to avoid missing sstables during streaming (CASSANDRA-11886)
  * cqlsh COPY FROM: shutdown parent cluster after forking, to avoid corrupting SSL connections (CASSANDRA-11749)
  * Updated cqlsh Python driver to fix DESCRIBE problem for legacy tables (CASSANDRA-11055)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
index 33c61e7..d8fa467 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
@@ -50,15 +50,6 @@ public class DeleteStatement extends ModificationStatement
     {
         List<Operation> deletions = getOperations();
 
-        if (prefix.size() < cfm.clusteringColumns().size() && !deletions.isEmpty())
-        {
-            // In general, we can't delete specific columns if not all clustering columns have been specified.
-            // However, if we delete only static colums, it's fine since we won't really use the prefix anyway.
-            for (Operation deletion : deletions)
-                if (!deletion.column.isStatic())
-                    throw new InvalidRequestException(String.format("Primary key column '%s' must be specified in order to delete column '%s'", getFirstEmptyKey().name, deletion.column.name));
-        }
-
         if (deletions.isEmpty())
         {
             // We delete the slice selected by the prefix.
@@ -88,19 +79,39 @@ public class DeleteStatement extends ModificationStatement
 
     protected void validateWhereClauseForConditions() throws InvalidRequestException
     {
-        Iterator<ColumnDefinition> iterator = Iterators.concat(cfm.partitionKeyColumns().iterator(), cfm.clusteringColumns().iterator());
+        boolean onlyHasConditionsOnStaticColumns = hasStaticConditions() && !hasRegularConditions();
+
+        // In general, we can't delete specific columns if not all clustering columns have been specified.
+        // However, if we delete only static colums, it's fine since we won't really use the prefix anyway.
+        Iterator<ColumnDefinition> iterator = appliesOnlyToStaticColumns()
+                                              ? cfm.partitionKeyColumns().iterator()
+                                              : Iterators.concat(cfm.partitionKeyColumns().iterator(), cfm.clusteringColumns().iterator());
         while (iterator.hasNext())
         {
             ColumnDefinition def = iterator.next();
             Restriction restriction = processedKeys.get(def.name);
             if (restriction == null || !(restriction.isEQ() || restriction.isIN()))
             {
+                if (onlyHasConditionsOnStaticColumns)
+                {
+                    for (Operation oper : getOperations())
+                    {
+                        if (!oper.column.isStatic())
+                        {
+                            throw new InvalidRequestException(String.format("Primary key column '%s' must be specified in order to delete column '%s'",
+                                                                            def.name,
+                                                                            oper.column.name));
+                        }
+                    }
+                }
+
                 throw new InvalidRequestException(
-                        String.format("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order " +
-                                      "to use IF conditions, but column '%s' is not restricted", def.name));
+                        String.format("DELETE statements must restrict all %s KEY columns with equality relations in order " +
+                                      "to use IF conditions%s, but column '%s' is not restricted",
+                                      onlyHasConditionsOnStaticColumns ? "PARTITION" : "PRIMARY",
+                                      onlyHasConditionsOnStaticColumns ? " on static columns" : "", def.name));
             }
         }
-
     }
 
     public static class Parsed extends ModificationStatement.Parsed

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/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 75a3b40..a9f65e1 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -211,6 +211,16 @@ public abstract class ModificationStatement implements CQLStatement
         return ifExists;
     }
 
+    public boolean hasStaticConditions()
+    {
+        return staticConditions != null && !staticConditions.isEmpty();
+    }
+
+    public boolean hasRegularConditions()
+    {
+        return columnConditions != null && !columnConditions.isEmpty();
+    }
+
     private void addKeyValues(ColumnDefinition def, Restriction values) throws InvalidRequestException
     {
         if (def.kind == ColumnDefinition.Kind.CLUSTERING_COLUMN)
@@ -364,7 +374,7 @@ public abstract class ModificationStatement implements CQLStatement
      * Checks that the modification only apply to static columns.
      * @return <code>true</code> if the modification only apply to static columns, <code>false</code> otherwise.
      */
-    private boolean appliesOnlyToStaticColumns()
+    protected boolean appliesOnlyToStaticColumns()
     {
         return setsStaticColumns && !appliesToRegularColumns();
     }
@@ -373,7 +383,7 @@ public abstract class ModificationStatement implements CQLStatement
      * Checks that the modification apply to regular columns.
      * @return <code>true</code> if the modification apply to regular columns, <code>false</code> otherwise.
      */
-    private boolean appliesToRegularColumns()
+    protected boolean appliesToRegularColumns()
     {
         // If we have regular operations, this applies to regular columns.
         // Otherwise, if the statement is a DELETE and columnOperations is empty, this means we have no operations,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1d2d0749/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 e94011b..05ba09d 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@ -311,6 +311,119 @@ public class InsertUpdateIfConditionTest extends CQLTester
     }
 
     /**
+     * Test CASSANDRA-10532
+     */
+    @Test
+    public void testStaticColumnsCasDelete() throws Throwable
+    {
+        createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+        execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 2), row(false, 1));
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 1), row(true));
+
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, null, 2),
+                   row(1, 3, null, 4),
+                   row(1, 5, null, 6),
+                   row(1, 7, null, 8));
+        execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+
+        assertInvalidMessage("DELETE statements must restrict all PARTITION KEY columns with equality relations in order " +
+                             "to use IF conditions on static columns, but column 'pk' is not restricted",
+                             "DELETE static_col FROM %s WHERE ck = ? IF static_col = ?", 1, 1);
+
+        assertInvalidMessage("Invalid restriction on clustering column ck since the DELETE statement modifies only static columns",
+                             "DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF static_col = ?", 1, 1, 1);
+
+        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
+                             "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 1);
+
+        // Same query but with an invalid condition
+        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
+                             "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 2);
+
+        // DELETE of an underspecified PRIMARY KEY should not succeed if static is not only restriction
+        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order " +
+                             "to use IF conditions, but column 'ck' is not restricted",
+                             "DELETE static_col FROM %s WHERE pk = ? IF value = ? AND static_col = ?", 1, 2, 1);
+
+        assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 2), row(false, 2, 1));
+        assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 1), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 1, null),
+                   row(1, 3, 1, 4),
+                   row(1, 5, 1, 6),
+                   row(1, 7, 1, 8));
+
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 10), row(false, 6));
+        assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 6), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, null, null),
+                   row(1, 3, null, 4),
+                   row(1, 5, null, 6),
+                   row(1, 7, null, 8));
+    }
+
+    @Test
+    public void testStaticColumnsCasUpdate() throws Throwable
+    {
+        createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+        execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+        execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 3, 1, 2), row(false, 1));
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 2, 1, 1), row(true));
+
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 2, 2),
+                   row(1, 3, 2, 4),
+                   row(1, 5, 2, 6),
+                   row(1, 7, 2, 8));
+
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part pk",
+                             "UPDATE %s SET static_col = ? WHERE ck = ? IF static_col = ?", 3, 1, 1);
+
+        assertInvalidMessage("Invalid restriction on clustering column ck since the UPDATE statement modifies only static columns",
+                             "UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF static_col = ?", 3, 1, 1, 1);
+
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
+                             "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 2);
+
+        // Same query but with an invalid condition
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
+                             "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 1);
+
+        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
+                             "UPDATE %s SET static_col = ? WHERE pk = ? IF value = ? AND static_col = ?", 3, 1, 4, 2);
+
+        assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 3, 1, 1, 3, 2), row(false, 2, 2));
+        assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 1, 2, 2), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 2, 1),
+                   row(1, 3, 2, 4),
+                   row(1, 5, 2, 6),
+                   row(1, 7, 2, 8));
+
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 3, 1, 1, 2), row(false, 1));
+        assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 1, 1, 1, 1), row(true));
+        assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                   row(1, 1, 1, 1),
+                   row(1, 3, 1, 4),
+                   row(1, 5, 1, 6),
+                   row(1, 7, 1, 8));
+    }
+
+    /**
      * Migrated from cql_tests.py:TestCQL.bug_6069_test()
      */
     @Test


[5/7] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by ca...@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/a91219e1
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/a91219e1
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/a91219e1

Branch: refs/heads/trunk
Commit: a91219e12459c86899ab59f8f6706afbbdbc5f89
Parents: 0d5984b 52a827b
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Jun 14 10:34:13 2016 -0400
Committer: Carl Yeksigian <ca...@apache.org>
Committed: Tue Jun 14 10:34:13 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../restrictions/StatementRestrictions.java     |   8 +-
 .../cql3/statements/DeleteStatement.java        |  15 ++-
 .../operations/InsertUpdateIfConditionTest.java | 120 ++++++++++++++++++-
 4 files changed, 132 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 8a04077,d0ca37f..2c42c94
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,29 -1,5 +1,30 @@@
 -2.2.7
 +3.0.8
 + * Add TimeWindowCompactionStrategy (CASSANDRA-9666)
 +Merged from 2.2:
   * StorageService shutdown hook should use a volatile variable (CASSANDRA-11984)
 +Merged from 2.1:
++ * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
 + * Create interval tree over canonical sstables to avoid missing sstables during streaming (CASSANDRA-11886)
 + * cqlsh COPY FROM: shutdown parent cluster after forking, to avoid corrupting SSL connections (CASSANDRA-11749)
 +
 +
 +3.0.7
 + * Fix legacy serialization of Thrift-generated non-compound range tombstones
 +   when communicating with 2.x nodes (CASSANDRA-11930)
 + * Fix Directories instantiations where CFS.initialDirectories should be used (CASSANDRA-11849)
 + * Avoid referencing DatabaseDescriptor in AbstractType (CASSANDRA-11912)
 + * Fix sstables not being protected from removal during index build (CASSANDRA-11905)
 + * cqlsh: Suppress stack trace from Read/WriteFailures (CASSANDRA-11032)
 + * Remove unneeded code to repair index summaries that have
 +   been improperly down-sampled (CASSANDRA-11127)
 + * Avoid WriteTimeoutExceptions during commit log replay due to materialized
 +   view lock contention (CASSANDRA-11891)
 + * Prevent OOM failures on SSTable corruption, improve tests for corruption detection (CASSANDRA-9530)
 + * Use CFS.initialDirectories when clearing snapshots (CASSANDRA-11705)
 + * Allow compaction strategies to disable early open (CASSANDRA-11754)
 + * Refactor Materialized View code (CASSANDRA-11475)
 + * Update Java Driver (CASSANDRA-11615)
 +Merged from 2.2:
   * 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)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
index 6ee554e,5b7c58d..ae0c9c4
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@@ -773,19 -601,8 +773,19 @@@ public final class StatementRestriction
          checkFalse(selectsOnlyStaticColumns, "Queries using 2ndary indexes don't support selecting only static columns");
      }
  
 -    public void reverse()
 +    /**
 +     * Checks that all the primary key columns (partition key and clustering columns) are restricted by an equality
 +     * relation ('=' or 'IN').
 +     *
 +     * @return <code>true</code> if all the primary key columns are restricted by an equality relation.
 +     */
 +    public boolean hasAllPKColumnsRestrictedByEqualities()
      {
 -        clusteringColumnsRestrictions = new ReversedPrimaryKeyRestrictions(clusteringColumnsRestrictions);
 +        return !isPartitionKeyRestrictionsOnToken()
-                 && !hasUnrestrictedPartitionKeyComponents()
-                 && (partitionKeyRestrictions.isEQ() || partitionKeyRestrictions.isIN())
-                 && !hasUnrestrictedClusteringColumns()
-                 && (clusteringColumnsRestrictions.isEQ() || clusteringColumnsRestrictions.isIN());
++               && !hasUnrestrictedPartitionKeyComponents()
++               && (partitionKeyRestrictions.isEQ() || partitionKeyRestrictions.isIN())
++               && !hasUnrestrictedClusteringColumns()
++               && (clusteringColumnsRestrictions.isEQ() || clusteringColumnsRestrictions.isIN());
      }
 +
  }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
index daeecfe,397928d..4888b43
--- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
@@@ -149,26 -150,10 +149,33 @@@ public class DeleteStatement extends Mo
  
                  Operation op = deletion.prepare(cfm.ksName, def);
                  op.collectMarkerSpecification(boundNames);
 -                stmt.addOperation(op);
 +                operations.add(op);
 +            }
 +
 +            StatementRestrictions restrictions = newRestrictions(cfm,
 +                                                                 boundNames,
 +                                                                 operations,
 +                                                                 whereClause,
 +                                                                 conditions);
 +
 +            DeleteStatement stmt = new DeleteStatement(boundNames.size(),
 +                                                       cfm,
 +                                                       operations,
 +                                                       restrictions,
 +                                                       conditions,
 +                                                       attrs);
 +
-             if (stmt.hasConditions())
-                 checkTrue(restrictions.hasAllPKColumnsRestrictedByEqualities(),
-                           "DELETE statements must restrict all PRIMARY KEY columns with equality relations" +
-                           " in order to use IF conditions");
++            if (stmt.hasConditions() && !restrictions.hasAllPKColumnsRestrictedByEqualities())
++            {
++                checkFalse(operations.appliesToRegularColumns(),
++                           "DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns");
++
++                // All primary keys must be specified, unless this has static column restrictions
++                checkFalse(conditions.appliesToRegularColumns(),
++                           "DELETE statements must restrict all PRIMARY KEY columns with equality relations" +
++                           " in order to use IF condition on non static columns");
+             }
+ 
 -            stmt.processWhereClause(whereClause, boundNames);
              return stmt;
          }
      }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index ade80bb,ca19a51..2d59a11
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@@ -188,25 -175,11 +188,25 @@@ public class InsertUpdateIfConditionTes
          assertRows(execute("DELETE FROM %s WHERE k='k' AND i=0 IF EXISTS"), row(false));
  
          // CASSANDRA-6430
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
 -        assertInvalid("DELETE FROM %s WHERE k = 'k' IF EXISTS");
 -        assertInvalid("DELETE FROM %s WHERE k = 'k' IF v = 'foo'");
 -        assertInvalid("DELETE FROM %s WHERE i = 0 IF EXISTS");
 -        assertInvalid("DELETE FROM %s WHERE k = 0 AND i > 0 IF EXISTS");
 -        assertInvalid("DELETE FROM %s WHERE k = 0 AND i > 0 IF v = 'foo'");
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' IF EXISTS");
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' IF v = 'foo'");
 +        assertInvalidMessage("Some partition key parts are missing: k",
 +                             "DELETE FROM %s WHERE i = 0 IF EXISTS");
 +
 +        assertInvalidMessage("Invalid INTEGER constant (0) for \"k\" of type text",
 +                             "DELETE FROM %s WHERE k = 0 AND i > 0 IF EXISTS");
 +        assertInvalidMessage("Invalid INTEGER constant (0) for \"k\" of type text",
 +                             "DELETE FROM %s WHERE k = 0 AND i > 0 IF v = 'foo'");
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' AND i > 0 IF EXISTS");
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' AND i > 0 IF v = 'foo'");
 +        assertInvalidMessage("IN on the clustering key columns is not supported with conditional deletions",
 +                             "DELETE FROM %s WHERE k = 'k' AND i IN (0, 1) IF v = 'foo'");
 +        assertInvalidMessage("IN on the clustering key columns is not supported with conditional deletions",
 +                             "DELETE FROM %s WHERE k = 'k' AND i IN (0, 1) IF EXISTS");
  
          createTable("CREATE TABLE %s(k int, s int static, i int, v text, PRIMARY KEY(k, i))");
          execute("INSERT INTO %s (k, s, i, v) VALUES ( 1, 1, 2, '1')");
@@@ -338,6 -311,119 +338,118 @@@
      }
  
      /**
+      * Test CASSANDRA-10532
+      */
+     @Test
+     public void testStaticColumnsCasDelete() throws Throwable
+     {
+         createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+         execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+ 
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 2), row(false, 1));
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 1), row(true));
+ 
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, null, 2),
+                    row(1, 3, null, 4),
+                    row(1, 5, null, 6),
+                    row(1, 7, null, 8));
+         execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+ 
 -        assertInvalidMessage("DELETE statements must restrict all PARTITION KEY columns with equality relations in order " +
 -                             "to use IF conditions on static columns, but column 'pk' is not restricted",
++        assertInvalidMessage("Some partition key parts are missing: pk",
+                              "DELETE static_col FROM %s WHERE ck = ? IF static_col = ?", 1, 1);
+ 
 -        assertInvalidMessage("Invalid restriction on clustering column ck since the DELETE statement modifies only static columns",
++        assertInvalidMessage("Invalid restrictions on clustering columns since the DELETE statement modifies only static columns",
+                              "DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF static_col = ?", 1, 1, 1);
+ 
 -        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
+                              "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 1);
+ 
+         // Same query but with an invalid condition
 -        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
+                              "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 2);
+ 
+         // DELETE of an underspecified PRIMARY KEY should not succeed if static is not only restriction
 -        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order " +
 -                             "to use IF conditions, but column 'ck' is not restricted",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations" +
++                             " in order to use IF condition on non static columns",
+                              "DELETE static_col FROM %s WHERE pk = ? IF value = ? AND static_col = ?", 1, 2, 1);
+ 
+         assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 2), row(false, 2, 1));
+         assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 1), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 1, null),
+                    row(1, 3, 1, 4),
+                    row(1, 5, 1, 6),
+                    row(1, 7, 1, 8));
+ 
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 10), row(false, 6));
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 6), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, null, null),
+                    row(1, 3, null, 4),
+                    row(1, 5, null, 6),
+                    row(1, 7, null, 8));
+     }
+ 
+     @Test
+     public void testStaticColumnsCasUpdate() throws Throwable
+     {
+         createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+         execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+ 
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 3, 1, 2), row(false, 1));
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 2, 1, 1), row(true));
+ 
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 2, 2),
+                    row(1, 3, 2, 4),
+                    row(1, 5, 2, 6),
+                    row(1, 7, 2, 8));
+ 
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part pk",
++        assertInvalidMessage("Some partition key parts are missing: pk",
+                              "UPDATE %s SET static_col = ? WHERE ck = ? IF static_col = ?", 3, 1, 1);
+ 
 -        assertInvalidMessage("Invalid restriction on clustering column ck since the UPDATE statement modifies only static columns",
++        assertInvalidMessage("Invalid restrictions on clustering columns since the UPDATE statement modifies only static columns",
+                              "UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF static_col = ?", 3, 1, 1, 1);
+ 
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
++        assertInvalidMessage("Some clustering keys are missing: ck",
+                              "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 2);
+ 
+         // Same query but with an invalid condition
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
++        assertInvalidMessage("Some clustering keys are missing: ck",
+                              "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 1);
+ 
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
++        assertInvalidMessage("Some clustering keys are missing: ck",
+                              "UPDATE %s SET static_col = ? WHERE pk = ? IF value = ? AND static_col = ?", 3, 1, 4, 2);
+ 
+         assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 3, 1, 1, 3, 2), row(false, 2, 2));
+         assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 1, 2, 2), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 2, 1),
+                    row(1, 3, 2, 4),
+                    row(1, 5, 2, 6),
+                    row(1, 7, 2, 8));
+ 
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 3, 1, 1, 2), row(false, 1));
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 1, 1, 1, 1), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 1, 1),
+                    row(1, 3, 1, 4),
+                    row(1, 5, 1, 6),
+                    row(1, 7, 1, 8));
+     }
+ 
+     /**
       * Migrated from cql_tests.py:TestCQL.bug_6069_test()
       */
      @Test


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

Posted by ca...@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/52a827b4
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/52a827b4
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/52a827b4

Branch: refs/heads/cassandra-3.0
Commit: 52a827b4d22edc4506adfbe83345216bc725d57f
Parents: 05f8a00 1d2d074
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Jun 14 08:55:58 2016 -0400
Committer: Carl Yeksigian <ca...@apache.org>
Committed: Tue Jun 14 08:55:58 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cql3/statements/DeleteStatement.java        |  37 +++---
 .../cql3/statements/ModificationStatement.java  |  14 ++-
 .../operations/InsertUpdateIfConditionTest.java | 113 +++++++++++++++++++
 4 files changed, 150 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/52a827b4/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 491f72a,7d70902..d0ca37f
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,32 -1,8 +1,33 @@@
 -2.1.15
 +2.2.7
 + * 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:
+  * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
   * Create interval tree over canonical sstables to avoid missing sstables during streaming (CASSANDRA-11886)
   * cqlsh COPY FROM: shutdown parent cluster after forking, to avoid corrupting SSL connections (CASSANDRA-11749)
 - * Updated cqlsh Python driver to fix DESCRIBE problem for legacy tables (CASSANDRA-11055)
   * cqlsh: apply current keyspace to source command (CASSANDRA-11152)
   * Backport CASSANDRA-11578 (CASSANDRA-11750)
   * Clear out parent repair session if repair coordinator dies (CASSANDRA-11824)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/52a827b4/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------

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

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


[3/7] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ca...@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/52a827b4
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/52a827b4
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/52a827b4

Branch: refs/heads/trunk
Commit: 52a827b4d22edc4506adfbe83345216bc725d57f
Parents: 05f8a00 1d2d074
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Jun 14 08:55:58 2016 -0400
Committer: Carl Yeksigian <ca...@apache.org>
Committed: Tue Jun 14 08:55:58 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cql3/statements/DeleteStatement.java        |  37 +++---
 .../cql3/statements/ModificationStatement.java  |  14 ++-
 .../operations/InsertUpdateIfConditionTest.java | 113 +++++++++++++++++++
 4 files changed, 150 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/52a827b4/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 491f72a,7d70902..d0ca37f
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,32 -1,8 +1,33 @@@
 -2.1.15
 +2.2.7
 + * 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:
+  * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
   * Create interval tree over canonical sstables to avoid missing sstables during streaming (CASSANDRA-11886)
   * cqlsh COPY FROM: shutdown parent cluster after forking, to avoid corrupting SSL connections (CASSANDRA-11749)
 - * Updated cqlsh Python driver to fix DESCRIBE problem for legacy tables (CASSANDRA-11055)
   * cqlsh: apply current keyspace to source command (CASSANDRA-11152)
   * Backport CASSANDRA-11578 (CASSANDRA-11750)
   * Clear out parent repair session if repair coordinator dies (CASSANDRA-11824)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/52a827b4/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------

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

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


[6/7] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by ca...@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/a91219e1
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/a91219e1
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/a91219e1

Branch: refs/heads/cassandra-3.0
Commit: a91219e12459c86899ab59f8f6706afbbdbc5f89
Parents: 0d5984b 52a827b
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Jun 14 10:34:13 2016 -0400
Committer: Carl Yeksigian <ca...@apache.org>
Committed: Tue Jun 14 10:34:13 2016 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../restrictions/StatementRestrictions.java     |   8 +-
 .../cql3/statements/DeleteStatement.java        |  15 ++-
 .../operations/InsertUpdateIfConditionTest.java | 120 ++++++++++++++++++-
 4 files changed, 132 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 8a04077,d0ca37f..2c42c94
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,29 -1,5 +1,30 @@@
 -2.2.7
 +3.0.8
 + * Add TimeWindowCompactionStrategy (CASSANDRA-9666)
 +Merged from 2.2:
   * StorageService shutdown hook should use a volatile variable (CASSANDRA-11984)
 +Merged from 2.1:
++ * Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
 + * Create interval tree over canonical sstables to avoid missing sstables during streaming (CASSANDRA-11886)
 + * cqlsh COPY FROM: shutdown parent cluster after forking, to avoid corrupting SSL connections (CASSANDRA-11749)
 +
 +
 +3.0.7
 + * Fix legacy serialization of Thrift-generated non-compound range tombstones
 +   when communicating with 2.x nodes (CASSANDRA-11930)
 + * Fix Directories instantiations where CFS.initialDirectories should be used (CASSANDRA-11849)
 + * Avoid referencing DatabaseDescriptor in AbstractType (CASSANDRA-11912)
 + * Fix sstables not being protected from removal during index build (CASSANDRA-11905)
 + * cqlsh: Suppress stack trace from Read/WriteFailures (CASSANDRA-11032)
 + * Remove unneeded code to repair index summaries that have
 +   been improperly down-sampled (CASSANDRA-11127)
 + * Avoid WriteTimeoutExceptions during commit log replay due to materialized
 +   view lock contention (CASSANDRA-11891)
 + * Prevent OOM failures on SSTable corruption, improve tests for corruption detection (CASSANDRA-9530)
 + * Use CFS.initialDirectories when clearing snapshots (CASSANDRA-11705)
 + * Allow compaction strategies to disable early open (CASSANDRA-11754)
 + * Refactor Materialized View code (CASSANDRA-11475)
 + * Update Java Driver (CASSANDRA-11615)
 +Merged from 2.2:
   * 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)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
index 6ee554e,5b7c58d..ae0c9c4
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@@ -773,19 -601,8 +773,19 @@@ public final class StatementRestriction
          checkFalse(selectsOnlyStaticColumns, "Queries using 2ndary indexes don't support selecting only static columns");
      }
  
 -    public void reverse()
 +    /**
 +     * Checks that all the primary key columns (partition key and clustering columns) are restricted by an equality
 +     * relation ('=' or 'IN').
 +     *
 +     * @return <code>true</code> if all the primary key columns are restricted by an equality relation.
 +     */
 +    public boolean hasAllPKColumnsRestrictedByEqualities()
      {
 -        clusteringColumnsRestrictions = new ReversedPrimaryKeyRestrictions(clusteringColumnsRestrictions);
 +        return !isPartitionKeyRestrictionsOnToken()
-                 && !hasUnrestrictedPartitionKeyComponents()
-                 && (partitionKeyRestrictions.isEQ() || partitionKeyRestrictions.isIN())
-                 && !hasUnrestrictedClusteringColumns()
-                 && (clusteringColumnsRestrictions.isEQ() || clusteringColumnsRestrictions.isIN());
++               && !hasUnrestrictedPartitionKeyComponents()
++               && (partitionKeyRestrictions.isEQ() || partitionKeyRestrictions.isIN())
++               && !hasUnrestrictedClusteringColumns()
++               && (clusteringColumnsRestrictions.isEQ() || clusteringColumnsRestrictions.isIN());
      }
 +
  }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
index daeecfe,397928d..4888b43
--- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
@@@ -149,26 -150,10 +149,33 @@@ public class DeleteStatement extends Mo
  
                  Operation op = deletion.prepare(cfm.ksName, def);
                  op.collectMarkerSpecification(boundNames);
 -                stmt.addOperation(op);
 +                operations.add(op);
 +            }
 +
 +            StatementRestrictions restrictions = newRestrictions(cfm,
 +                                                                 boundNames,
 +                                                                 operations,
 +                                                                 whereClause,
 +                                                                 conditions);
 +
 +            DeleteStatement stmt = new DeleteStatement(boundNames.size(),
 +                                                       cfm,
 +                                                       operations,
 +                                                       restrictions,
 +                                                       conditions,
 +                                                       attrs);
 +
-             if (stmt.hasConditions())
-                 checkTrue(restrictions.hasAllPKColumnsRestrictedByEqualities(),
-                           "DELETE statements must restrict all PRIMARY KEY columns with equality relations" +
-                           " in order to use IF conditions");
++            if (stmt.hasConditions() && !restrictions.hasAllPKColumnsRestrictedByEqualities())
++            {
++                checkFalse(operations.appliesToRegularColumns(),
++                           "DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns");
++
++                // All primary keys must be specified, unless this has static column restrictions
++                checkFalse(conditions.appliesToRegularColumns(),
++                           "DELETE statements must restrict all PRIMARY KEY columns with equality relations" +
++                           " in order to use IF condition on non static columns");
+             }
+ 
 -            stmt.processWhereClause(whereClause, boundNames);
              return stmt;
          }
      }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index ade80bb,ca19a51..2d59a11
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@@ -188,25 -175,11 +188,25 @@@ public class InsertUpdateIfConditionTes
          assertRows(execute("DELETE FROM %s WHERE k='k' AND i=0 IF EXISTS"), row(false));
  
          // CASSANDRA-6430
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
 -        assertInvalid("DELETE FROM %s WHERE k = 'k' IF EXISTS");
 -        assertInvalid("DELETE FROM %s WHERE k = 'k' IF v = 'foo'");
 -        assertInvalid("DELETE FROM %s WHERE i = 0 IF EXISTS");
 -        assertInvalid("DELETE FROM %s WHERE k = 0 AND i > 0 IF EXISTS");
 -        assertInvalid("DELETE FROM %s WHERE k = 0 AND i > 0 IF v = 'foo'");
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' IF EXISTS");
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' IF v = 'foo'");
 +        assertInvalidMessage("Some partition key parts are missing: k",
 +                             "DELETE FROM %s WHERE i = 0 IF EXISTS");
 +
 +        assertInvalidMessage("Invalid INTEGER constant (0) for \"k\" of type text",
 +                             "DELETE FROM %s WHERE k = 0 AND i > 0 IF EXISTS");
 +        assertInvalidMessage("Invalid INTEGER constant (0) for \"k\" of type text",
 +                             "DELETE FROM %s WHERE k = 0 AND i > 0 IF v = 'foo'");
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' AND i > 0 IF EXISTS");
-         assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
 +                             "DELETE FROM %s WHERE k = 'k' AND i > 0 IF v = 'foo'");
 +        assertInvalidMessage("IN on the clustering key columns is not supported with conditional deletions",
 +                             "DELETE FROM %s WHERE k = 'k' AND i IN (0, 1) IF v = 'foo'");
 +        assertInvalidMessage("IN on the clustering key columns is not supported with conditional deletions",
 +                             "DELETE FROM %s WHERE k = 'k' AND i IN (0, 1) IF EXISTS");
  
          createTable("CREATE TABLE %s(k int, s int static, i int, v text, PRIMARY KEY(k, i))");
          execute("INSERT INTO %s (k, s, i, v) VALUES ( 1, 1, 2, '1')");
@@@ -338,6 -311,119 +338,118 @@@
      }
  
      /**
+      * Test CASSANDRA-10532
+      */
+     @Test
+     public void testStaticColumnsCasDelete() throws Throwable
+     {
+         createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+         execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+ 
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 2), row(false, 1));
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 1), row(true));
+ 
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, null, 2),
+                    row(1, 3, null, 4),
+                    row(1, 5, null, 6),
+                    row(1, 7, null, 8));
+         execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+ 
 -        assertInvalidMessage("DELETE statements must restrict all PARTITION KEY columns with equality relations in order " +
 -                             "to use IF conditions on static columns, but column 'pk' is not restricted",
++        assertInvalidMessage("Some partition key parts are missing: pk",
+                              "DELETE static_col FROM %s WHERE ck = ? IF static_col = ?", 1, 1);
+ 
 -        assertInvalidMessage("Invalid restriction on clustering column ck since the DELETE statement modifies only static columns",
++        assertInvalidMessage("Invalid restrictions on clustering columns since the DELETE statement modifies only static columns",
+                              "DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF static_col = ?", 1, 1, 1);
+ 
 -        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
+                              "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 1);
+ 
+         // Same query but with an invalid condition
 -        assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns",
+                              "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 2);
+ 
+         // DELETE of an underspecified PRIMARY KEY should not succeed if static is not only restriction
 -        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order " +
 -                             "to use IF conditions, but column 'ck' is not restricted",
++        assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations" +
++                             " in order to use IF condition on non static columns",
+                              "DELETE static_col FROM %s WHERE pk = ? IF value = ? AND static_col = ?", 1, 2, 1);
+ 
+         assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 2), row(false, 2, 1));
+         assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 1), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 1, null),
+                    row(1, 3, 1, 4),
+                    row(1, 5, 1, 6),
+                    row(1, 7, 1, 8));
+ 
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 10), row(false, 6));
+         assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 6), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, null, null),
+                    row(1, 3, null, 4),
+                    row(1, 5, null, 6),
+                    row(1, 7, null, 8));
+     }
+ 
+     @Test
+     public void testStaticColumnsCasUpdate() throws Throwable
+     {
+         createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))");
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8);
+         execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2);
+         execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1);
+ 
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 3, 1, 2), row(false, 1));
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 2, 1, 1), row(true));
+ 
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 2, 2),
+                    row(1, 3, 2, 4),
+                    row(1, 5, 2, 6),
+                    row(1, 7, 2, 8));
+ 
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part pk",
++        assertInvalidMessage("Some partition key parts are missing: pk",
+                              "UPDATE %s SET static_col = ? WHERE ck = ? IF static_col = ?", 3, 1, 1);
+ 
 -        assertInvalidMessage("Invalid restriction on clustering column ck since the UPDATE statement modifies only static columns",
++        assertInvalidMessage("Invalid restrictions on clustering columns since the UPDATE statement modifies only static columns",
+                              "UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF static_col = ?", 3, 1, 1, 1);
+ 
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
++        assertInvalidMessage("Some clustering keys are missing: ck",
+                              "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 2);
+ 
+         // Same query but with an invalid condition
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
++        assertInvalidMessage("Some clustering keys are missing: ck",
+                              "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 1);
+ 
 -        assertInvalidMessage("Missing mandatory PRIMARY KEY part ck",
++        assertInvalidMessage("Some clustering keys are missing: ck",
+                              "UPDATE %s SET static_col = ? WHERE pk = ? IF value = ? AND static_col = ?", 3, 1, 4, 2);
+ 
+         assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 3, 1, 1, 3, 2), row(false, 2, 2));
+         assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 1, 2, 2), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 2, 1),
+                    row(1, 3, 2, 4),
+                    row(1, 5, 2, 6),
+                    row(1, 7, 2, 8));
+ 
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 3, 1, 1, 2), row(false, 1));
+         assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 1, 1, 1, 1), row(true));
+         assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"),
+                    row(1, 1, 1, 1),
+                    row(1, 3, 1, 4),
+                    row(1, 5, 1, 6),
+                    row(1, 7, 1, 8));
+     }
+ 
+     /**
       * Migrated from cql_tests.py:TestCQL.bug_6069_test()
       */
      @Test