You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2016/06/21 14:34:05 UTC
[1/4] cassandra git commit: Remove distinction between non-existing
static columns and existing but null in LWTs
Repository: cassandra
Updated Branches:
refs/heads/trunk 5382f4ec3 -> 448389207
Remove distinction between non-existing static columns and existing but null in LWTs
Path by Alex Petrov; reviewed by Benjamin Lerer for CASSANDRA-9842
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/85f2bbfd
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/85f2bbfd
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/85f2bbfd
Branch: refs/heads/trunk
Commit: 85f2bbfd1c6803977ecc1c2053527363078bce22
Parents: a56bc16
Author: Alex Petrov <ol...@gmail.com>
Authored: Tue Jun 21 16:22:23 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:22:23 2016 +0200
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../cql3/statements/ModificationStatement.java | 5 +-
.../apache/cassandra/service/StorageProxy.java | 5 +-
.../operations/InsertUpdateIfConditionTest.java | 291 ++++++++++++++++++-
4 files changed, 298 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 64cfdaa..7944967 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
2.1.15
+ * Remove distinction between non-existing static columns and existing but null in LWTs (CASSANDRA-9842)
* Support mlockall on IBM POWER arch (CASSANDRA-11576)
* Cache local ranges when calculating repair neighbors (CASSANDRA-11933)
* Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
index a9f65e1..f84188a 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -697,10 +697,11 @@ public abstract class ModificationStatement implements CQLStatement
Row row = readCommand.getRow(keyspace);
ColumnFamily current = row.cf;
+ if (current == null)
+ current = ArrayBackedSortedColumns.factory.create(metadata);
+
if (!request.appliesTo(current))
{
- if (current == null)
- current = ArrayBackedSortedColumns.factory.create(metadata);
return current;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/src/java/org/apache/cassandra/service/StorageProxy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java b/src/java/org/apache/cassandra/service/StorageProxy.java
index 58a2874..845a732 100644
--- a/src/java/org/apache/cassandra/service/StorageProxy.java
+++ b/src/java/org/apache/cassandra/service/StorageProxy.java
@@ -233,12 +233,15 @@ public class StorageProxy implements StorageProxyMBean
? ConsistencyLevel.LOCAL_QUORUM
: ConsistencyLevel.QUORUM);
ColumnFamily current = rows.get(0).cf;
+ if (current == null)
+ current = ArrayBackedSortedColumns.factory.create(metadata);
+
if (!request.appliesTo(current))
{
Tracing.trace("CAS precondition does not match current values {}", current);
// We should not return null as this means success
casWriteMetrics.conditionNotMet.inc();
- return current == null ? ArrayBackedSortedColumns.factory.create(metadata) : current;
+ return current;
}
// finish the paxos round w/ the desired updates
http://git-wip-us.apache.org/repos/asf/cassandra/blob/85f2bbfd/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index 05ba09d..900cc7d 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@ -140,7 +140,7 @@ public class InsertUpdateIfConditionTest extends CQLTester
@Test
public void testConditionalDelete() throws Throwable
{
- createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int,)");
+ createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int)");
assertRows(execute("DELETE FROM %s WHERE k=1 IF EXISTS"), row(false));
@@ -981,4 +981,293 @@ public class InsertUpdateIfConditionTest extends CQLTester
execute("DROP TYPE IF EXISTS mytype");
assertEmpty(execute("SELECT type_name from system.schema_usertypes where keyspace_name = ? and type_name = ?", KEYSPACE, "mytype"));
}
+
+ @Test
+ public void testConditionalUpdatesOnStaticColumns() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ // pre-existing row
+ execute("INSERT INTO %s (a, b, s, d) values (6, 6, 100, 'a')");
+ assertRows(execute("UPDATE %s SET s = 6 WHERE a = 6 IF s = 100"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+ row(6, 6, 6, "a"));
+
+ // pre-existing row with null in the static column
+ execute("INSERT INTO %s (a, b, d) values (7, 7, 'a')");
+ assertRows(execute("UPDATE %s SET s = 7 WHERE a = 7 IF s = NULL"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+ row(7, 7, 7, "a"));
+
+ // deleting row before CAS
+ execute("DELETE FROM %s WHERE a = 8;");
+ assertRows(execute("UPDATE %s SET s = 8 WHERE a = 8 IF s = NULL"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 8"),
+ row(8, null, 8, null));
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNullValues() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ // pre-populate, leave out static column
+ for (int i = 1; i <= 5; i++)
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+
+ conditionalUpdatesWithNonExistingOrNullValues();
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("UPDATE %s SET s = 30 WHERE a = 3 IF s IN (10,20,30)"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+ row(3, 3, null, null));
+
+ // rejected: comparing number with NULL always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, null, null));
+ }
+
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNonExistingValues() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ conditionalUpdatesWithNonExistingOrNullValues();
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("UPDATE %s SET s = 3 WHERE a = 3 IF s IN (10,20,30)"),
+ row(false));
+ assertEmpty(execute("SELECT a, s, d FROM %s WHERE a = 3"));
+
+ // rejected: comparing number with NULL always returns false
+ for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+ {
+ assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 5"));
+ }
+ }
+
+ private void conditionalUpdatesWithNonExistingOrNullValues() throws Throwable
+ {
+ assertRows(execute("UPDATE %s SET s = 1 WHERE a = 1 IF s = NULL"),
+ row(true));
+ assertRows(execute("SELECT a, s, d FROM %s WHERE a = 1"),
+ row(1, 1, null));
+
+ assertRows(execute("UPDATE %s SET s = 2 WHERE a = 2 IF s IN (10,20,NULL)"),
+ row(true));
+ assertRows(execute("SELECT a, s, d FROM %s WHERE a = 2"),
+ row(2, 2, null));
+
+ assertRows(execute("UPDATE %s SET s = 4 WHERE a = 4 IF s != 4"),
+ row(true));
+ assertRows(execute("SELECT a, s, d FROM %s WHERE a = 4"),
+ row(4, 4, null));
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNullValuesWithBatch() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ // pre-populate, leave out static column
+ for (int i = 1; i <= 6; i++)
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+
+ testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+
+ // rejected: comparing number with null value always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 40, 'a');\n"
+ + "UPDATE %1$s SET s = 30 WHERE a = 3 IF s " + operator + " 5;\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+ row(3, 3, null, null));
+ }
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 70, 'a');\n"
+ + "UPDATE %1$s SET s = 60 WHERE a = 6 IF s IN (1,2,3);\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+ row(6, 6, null, null));
+
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNonExistingValuesWithBatch() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+
+ // rejected: comparing number with non-existing value always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 3, 'a');\n"
+ + "UPDATE %1$s SET s = 3 WHERE a = 3 IF s " + operator + " 5;\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+ }
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 6, 'a');\n"
+ + "UPDATE %1$s SET s = 7 WHERE a = 6 IF s IN (1,2,3);\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+ }
+
+ private void testConditionalUpdatesWithNonExistingOrNullValuesWithBatch() throws Throwable
+ {
+ // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, d) values (2, 2, 'a');\n"
+ + "UPDATE %1$s SET s = 2 WHERE a = 2 IF s = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+ row(2, 2, 2, "a"));
+
+ // applied: lwt condition is executed before INSERT, update is applied after it
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (4, 4, 4, 'a');\n"
+ + "UPDATE %1$s SET s = 5 WHERE a = 4 IF s = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+ row(4, 4, 5, "a"));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (5, 5, 5, 'a');\n"
+ + "UPDATE %1$s SET s = 6 WHERE a = 5 IF s IN (1,2,null);\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, 6, "a"));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (7, 7, 7, 'a');\n"
+ + "UPDATE %1$s SET s = 8 WHERE a = 7 IF s != 7;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+ row(7, 7, 8, "a"));
+ }
+
+ @Test
+ public void testConditionalDeleteWithNullValues() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+
+ for (int i = 1; i <= 5; i++)
+ execute("INSERT INTO %s (a, b, s1, s2, v) VALUES (?, ?, ?, ?, ?)", i, i, i, null, i);
+
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 1 IF s2 = NULL"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 1"),
+ row(1, 1, null, null, 1));
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 2 IF s2 IN (10,20,30)"),
+ row(false, null));
+ assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+ row(2, 2, 2, null, 2));
+
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 3 IF s2 IN (NULL,20,30)"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+ row(3, 3, null, null, 3));
+
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 4 IF s2 != 4"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+ row(4, 4, null, null, 4));
+
+ // rejected: comparing number with NULL always returns false
+ for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+ {
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 5 IF s2 " + operator + " 3"),
+ row(false, null));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, 5, null, 5));
+ }
+ }
+
+ @Test
+ public void testConditionalDeletesWithNonExistingValuesWithBatch() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+
+ // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (2, 2, 2, 2);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 2 IF s2 = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+ row(2, 2, null, null, 2));
+
+ // rejected: comparing number with non-existing value always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (3, 3, 3, 3);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 3 IF s2 " + operator + " 5;\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+ }
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (6, 6, 6, 6);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 6 IF s2 IN (1,2,3);\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (4, 4, 4, 4);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 4 IF s2 = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+ row(4, 4, null, null, 4));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) VALUES (5, 5, 5, 5);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 5 IF s1 IN (1,2,null);\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, null, null, 5));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (7, 7, 7, 7);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 7 IF s2 != 7;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+ row(7, 7, null, null, 7));
+ }
}
[3/4] cassandra git commit: Merge branch cassandra-2.2 into
cassandra-3.0
Posted by bl...@apache.org.
Merge branch cassandra-2.2 into cassandra-3.0
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/723a143c
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/723a143c
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/723a143c
Branch: refs/heads/trunk
Commit: 723a143c9d71ba8b3450cad8a0ad178f133a3869
Parents: b657223 5a09627
Author: Benjamin Lerer <b....@gmail.com>
Authored: Tue Jun 21 16:28:25 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:30:06 2016 +0200
----------------------------------------------------------------------
.../operations/InsertUpdateIfConditionTest.java | 290 +++++++++++++++++++
1 file changed, 290 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/723a143c/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index 2d59a11,fc6cc2e..a1ee4f8
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@@ -23,10 -23,8 +23,11 @@@ import org.junit.Test
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.cassandra.schema.SchemaKeyspace;
+import static java.lang.String.format;
import static org.junit.Assert.assertEquals;
++import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class InsertUpdateIfConditionTest extends CQLTester
@@@ -1018,10 -979,295 +1019,299 @@@
// drop and confirm
execute("DROP TYPE IF EXISTS mytype");
- assertEmpty(execute("SELECT type_name from system.schema_usertypes where keyspace_name = ? and type_name = ?", KEYSPACE, "mytype"));
+ assertEmpty(execute(format("SELECT type_name from %s.%s where keyspace_name = ? and type_name = ?",
+ SchemaKeyspace.NAME,
+ SchemaKeyspace.TYPES),
+ KEYSPACE,
+ "mytype"));
}
+
+ @Test
+ public void testConditionalUpdatesOnStaticColumns() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ // pre-existing row
+ execute("INSERT INTO %s (a, b, s, d) values (6, 6, 100, 'a')");
+ assertRows(execute("UPDATE %s SET s = 6 WHERE a = 6 IF s = 100"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+ row(6, 6, 6, "a"));
+
+ // pre-existing row with null in the static column
+ execute("INSERT INTO %s (a, b, d) values (7, 7, 'a')");
+ assertRows(execute("UPDATE %s SET s = 7 WHERE a = 7 IF s = NULL"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+ row(7, 7, 7, "a"));
+
+ // deleting row before CAS
+ execute("DELETE FROM %s WHERE a = 8;");
+ assertRows(execute("UPDATE %s SET s = 8 WHERE a = 8 IF s = NULL"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 8"),
+ row(8, null, 8, null));
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNullValues() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ // pre-populate, leave out static column
+ for (int i = 1; i <= 5; i++)
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+
+ conditionalUpdatesWithNonExistingOrNullValues();
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("UPDATE %s SET s = 30 WHERE a = 3 IF s IN (10,20,30)"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+ row(3, 3, null, null));
+
+ // rejected: comparing number with NULL always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, null, null));
+ }
+
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNonExistingValues() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ conditionalUpdatesWithNonExistingOrNullValues();
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("UPDATE %s SET s = 3 WHERE a = 3 IF s IN (10,20,30)"),
+ row(false));
+ assertEmpty(execute("SELECT a, s, d FROM %s WHERE a = 3"));
+
+ // rejected: comparing number with NULL always returns false
+ for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+ {
+ assertRows(execute("UPDATE %s SET s = 50 WHERE a = 5 IF s " + operator + " 3"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 5"));
+ }
+ }
+
+ private void conditionalUpdatesWithNonExistingOrNullValues() throws Throwable
+ {
+ assertRows(execute("UPDATE %s SET s = 1 WHERE a = 1 IF s = NULL"),
+ row(true));
+ assertRows(execute("SELECT a, s, d FROM %s WHERE a = 1"),
+ row(1, 1, null));
+
+ assertRows(execute("UPDATE %s SET s = 2 WHERE a = 2 IF s IN (10,20,NULL)"),
+ row(true));
+ assertRows(execute("SELECT a, s, d FROM %s WHERE a = 2"),
+ row(2, 2, null));
+
+ assertRows(execute("UPDATE %s SET s = 4 WHERE a = 4 IF s != 4"),
+ row(true));
+ assertRows(execute("SELECT a, s, d FROM %s WHERE a = 4"),
+ row(4, 4, null));
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNullValuesWithBatch() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ // pre-populate, leave out static column
+ for (int i = 1; i <= 6; i++)
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", i, i);
+
+ testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+
+ // rejected: comparing number with null value always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 40, 'a');\n"
+ + "UPDATE %1$s SET s = 30 WHERE a = 3 IF s " + operator + " 5;\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+ row(3, 3, null, null));
+ }
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 70, 'a');\n"
+ + "UPDATE %1$s SET s = 60 WHERE a = 6 IF s IN (1,2,3);\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 6"),
+ row(6, 6, null, null));
+
+ }
+
+ @Test
+ public void testConditionalUpdatesWithNonExistingValuesWithBatch() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s int static, d text, PRIMARY KEY (a, b))");
+
+ testConditionalUpdatesWithNonExistingOrNullValuesWithBatch();
+
+ // rejected: comparing number with non-existing value always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (3, 3, 3, 'a');\n"
+ + "UPDATE %1$s SET s = 3 WHERE a = 3 IF s " + operator + " 5;\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+ }
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (6, 6, 6, 'a');\n"
+ + "UPDATE %1$s SET s = 7 WHERE a = 6 IF s IN (1,2,3);\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+ }
+
+ private void testConditionalUpdatesWithNonExistingOrNullValuesWithBatch() throws Throwable
+ {
+ // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, d) values (2, 2, 'a');\n"
+ + "UPDATE %1$s SET s = 2 WHERE a = 2 IF s = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+ row(2, 2, 2, "a"));
+
+ // applied: lwt condition is executed before INSERT, update is applied after it
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (4, 4, 4, 'a');\n"
+ + "UPDATE %1$s SET s = 5 WHERE a = 4 IF s = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+ row(4, 4, 5, "a"));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (5, 5, 5, 'a');\n"
+ + "UPDATE %1$s SET s = 6 WHERE a = 5 IF s IN (1,2,null);\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, 6, "a"));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s, d) values (7, 7, 7, 'a');\n"
+ + "UPDATE %1$s SET s = 8 WHERE a = 7 IF s != 7;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+ row(7, 7, 8, "a"));
+ }
+
+ @Test
+ public void testConditionalDeleteWithNullValues() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+
+ for (int i = 1; i <= 5; i++)
+ execute("INSERT INTO %s (a, b, s1, s2, v) VALUES (?, ?, ?, ?, ?)", i, i, i, null, i);
+
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 1 IF s2 = NULL"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 1"),
+ row(1, 1, null, null, 1));
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 2 IF s2 IN (10,20,30)"),
- row(false, null));
++ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+ row(2, 2, 2, null, 2));
+
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 3 IF s2 IN (NULL,20,30)"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 3"),
+ row(3, 3, null, null, 3));
+
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 4 IF s2 != 4"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+ row(4, 4, null, null, 4));
+
+ // rejected: comparing number with NULL always returns false
+ for (String operator : new String[]{ ">", "<", ">=", "<=", "=" })
+ {
+ assertRows(execute("DELETE s1 FROM %s WHERE a = 5 IF s2 " + operator + " 3"),
- row(false, null));
++ row(false));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, 5, null, 5));
+ }
+ }
+
+ @Test
+ public void testConditionalDeletesWithNonExistingValuesWithBatch() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, s1 int static, s2 int static, v int, PRIMARY KEY (a, b))");
+
+ // applied: null is indistiguishable from empty value, lwt condition is executed before INSERT
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (2, 2, 2, 2);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 2 IF s2 = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 2"),
+ row(2, 2, null, null, 2));
+
+ // rejected: comparing number with non-existing value always returns false
+ for (String operator: new String[] { ">", "<", ">=", "<=", "="})
+ {
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (3, 3, 3, 3);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 3 IF s2 " + operator + " 5;\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 3"));
+ }
+
+ // rejected: IN doesn't contain null
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (6, 6, 6, 6);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 6 IF s2 IN (1,2,3);\n"
+ + "APPLY BATCH"),
+ row(false));
+ assertEmpty(execute("SELECT * FROM %s WHERE a = 6"));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (4, 4, 4, 4);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 4 IF s2 = null;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 4"),
+ row(4, 4, null, null, 4));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) VALUES (5, 5, 5, 5);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 5 IF s1 IN (1,2,null);\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 5"),
+ row(5, 5, null, null, 5));
+
+ assertRows(execute("BEGIN BATCH\n"
+ + "INSERT INTO %1$s (a, b, s1, v) values (7, 7, 7, 7);\n"
+ + "DELETE s1 FROM %1$s WHERE a = 7 IF s2 != 7;\n"
+ + "APPLY BATCH"),
+ row(true));
+ assertRows(execute("SELECT * FROM %s WHERE a = 7"),
+ row(7, 7, null, null, 7));
+ }
}
[2/4] cassandra git commit: Merge branch cassandra-2.1 into
cassandra-2.2
Posted by bl...@apache.org.
Merge branch cassandra-2.1 into cassandra-2.2
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5a096274
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5a096274
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5a096274
Branch: refs/heads/trunk
Commit: 5a096274dc592c35efe0dfaa12bf4bc40b02402b
Parents: 68398ad 85f2bbf
Author: Benjamin Lerer <b....@gmail.com>
Authored: Tue Jun 21 16:25:23 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:25:23 2016 +0200
----------------------------------------------------------------------
CHANGES.txt | 5 +
.../cql3/statements/ModificationStatement.java | 5 +-
.../apache/cassandra/service/StorageProxy.java | 5 +-
.../operations/InsertUpdateIfConditionTest.java | 291 ++++++++++++++++++-
4 files changed, 302 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index ef993fe,7944967..fe4728d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,32 -1,5 +1,37 @@@
++<<<<<<< HEAD
+2.2.7
+ * RandomAccessReader: call isEOF() only when rebuffering, not for every read operation (CASSANDRA-12013)
+ * Don't send erroneous NEW_NODE notifications on restart (CASSANDRA-11038)
+ * StorageService shutdown hook should use a volatile variable (CASSANDRA-11984)
+ * Persist local metadata earlier in startup sequence (CASSANDRA-11742)
+ * Run CommitLog tests with different compression settings (CASSANDRA-9039)
+ * cqlsh: fix tab completion for case-sensitive identifiers (CASSANDRA-11664)
+ * Avoid showing estimated key as -1 in tablestats (CASSANDRA-11587)
+ * Fix possible race condition in CommitLog.recover (CASSANDRA-11743)
+ * Enable client encryption in sstableloader with cli options (CASSANDRA-11708)
+ * Possible memory leak in NIODataInputStream (CASSANDRA-11867)
+ * Fix commit log replay after out-of-order flush completion (CASSANDRA-9669)
+ * Add seconds to cqlsh tracing session duration (CASSANDRA-11753)
+ * Prohibit Reverse Counter type as part of the PK (CASSANDRA-9395)
+ * cqlsh: correctly handle non-ascii chars in error messages (CASSANDRA-11626)
+ * Exit JVM if JMX server fails to startup (CASSANDRA-11540)
+ * Produce a heap dump when exiting on OOM (CASSANDRA-9861)
+ * Avoid read repairing purgeable tombstones on range slices (CASSANDRA-11427)
+ * Restore ability to filter on clustering columns when using a 2i (CASSANDRA-11510)
+ * JSON datetime formatting needs timezone (CASSANDRA-11137)
+ * Fix is_dense recalculation for Thrift-updated tables (CASSANDRA-11502)
+ * Remove unnescessary file existence check during anticompaction (CASSANDRA-11660)
+ * Add missing files to debian packages (CASSANDRA-11642)
+ * Avoid calling Iterables::concat in loops during ModificationStatement::getFunctions (CASSANDRA-11621)
+ * cqlsh: COPY FROM should use regular inserts for single statement batches and
+ report errors correctly if workers processes crash on initialization (CASSANDRA-11474)
+ * Always close cluster with connection in CqlRecordWriter (CASSANDRA-11553)
+ * Fix slice queries on ordered COMPACT tables (CASSANDRA-10988)
+Merged from 2.1:
++=======
+ 2.1.15
+ * Remove distinction between non-existing static columns and existing but null in LWTs (CASSANDRA-9842)
++>>>>>>> asf/cassandra-2.1
* Support mlockall on IBM POWER arch (CASSANDRA-11576)
* Cache local ranges when calculating repair neighbors (CASSANDRA-11933)
* Allow LWT operation on static column with only partition keys (CASSANDRA-10532)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/src/java/org/apache/cassandra/service/StorageProxy.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/5a096274/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
[4/4] cassandra git commit: Merge branch cassandra-3.0 into trunk
Posted by bl...@apache.org.
Merge branch cassandra-3.0 into trunk
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/44838920
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/44838920
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/44838920
Branch: refs/heads/trunk
Commit: 44838920709e0333ec105c299fa8cbb1f0905f93
Parents: 5382f4e 723a143
Author: Benjamin Lerer <b....@gmail.com>
Authored: Tue Jun 21 16:33:12 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Tue Jun 21 16:33:25 2016 +0200
----------------------------------------------------------------------
.../operations/InsertUpdateIfConditionTest.java | 290 +++++++++++++++++++
1 file changed, 290 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/44838920/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------