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 2017/01/27 14:51:39 UTC
[2/7] cassandra git commit: Merge branch cassandra-2.2 into
cassandra-3.0
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/714edbce
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/714edbce
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/714edbce
Branch: refs/heads/trunk
Commit: 714edbce9a38c70a0f031a73d3c1a20f7f2b4bb3
Parents: e1da99a 70e33d9
Author: Benjamin Lerer <b....@gmail.com>
Authored: Fri Jan 27 15:26:18 2017 +0100
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Fri Jan 27 15:29:40 2017 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../apache/cassandra/cql3/ColumnCondition.java | 62 ++++++-
.../operations/InsertUpdateIfConditionTest.java | 162 ++++++++++++++++++-
3 files changed, 215 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/714edbce/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 3796a8d,c5e5335..547fc07
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,32 -1,5 +1,33 @@@
-2.2.9
+3.0.11
+ * Better error when modifying function permissions without explicit keyspace (CASSANDRA-12925)
+ * Indexer is not correctly invoked when building indexes over sstables (CASSANDRA-13075)
+ * Read repair is not blocking repair to finish in foreground repair (CASSANDRA-13115)
+ * Stress daemon help is incorrect (CASSANDRA-12563)
+ * Remove ALTER TYPE support (CASSANDRA-12443)
+ * Fix assertion for certain legacy range tombstone pattern (CASSANDRA-12203)
+ * Set javac encoding to utf-8 (CASSANDRA-11077)
+ * Replace empty strings with null values if they cannot be converted (CASSANDRA-12794)
+ * Fixed flacky SSTableRewriterTest: check file counts before calling validateCFS (CASSANDRA-12348)
+ * Fix deserialization of 2.x DeletedCells (CASSANDRA-12620)
+ * Add parent repair session id to anticompaction log message (CASSANDRA-12186)
+ * Improve contention handling on failure to acquire MV lock for streaming and hints (CASSANDRA-12905)
+ * Fix DELETE and UPDATE queries with empty IN restrictions (CASSANDRA-12829)
+ * Mark MVs as built after successful bootstrap (CASSANDRA-12984)
+ * Estimated TS drop-time histogram updated with Cell.NO_DELETION_TIME (CASSANDRA-13040)
+ * Nodetool compactionstats fails with NullPointerException (CASSANDRA-13021)
+ * Thread local pools never cleaned up (CASSANDRA-13033)
+ * Set RPC_READY to false when draining or if a node is marked as shutdown (CASSANDRA-12781)
+ * Make sure sstables only get committed when it's safe to discard commit log records (CASSANDRA-12956)
+ * Reject default_time_to_live option when creating or altering MVs (CASSANDRA-12868)
+ * Nodetool should use a more sane max heap size (CASSANDRA-12739)
+ * LocalToken ensures token values are cloned on heap (CASSANDRA-12651)
+ * AnticompactionRequestSerializer serializedSize is incorrect (CASSANDRA-12934)
+ * Prevent reloading of logback.xml from UDF sandbox (CASSANDRA-12535)
+ * Reenable HeapPool (CASSANDRA-12900)
+Merged from 2.2:
+ * Fix handling of nulls and unsets in IN conditions (CASSANDRA-12981)
+ * Fix race causing infinite loop if Thrift server is stopped before it starts listening (CASSANDRA-12856)
+ * CompactionTasks now correctly drops sstables out of compaction when not enough disk space is available (CASSANDRA-12979)
* Remove support for non-JavaScript UDFs (CASSANDRA-12883)
* Fix DynamicEndpointSnitch noop in multi-datacenter situations (CASSANDRA-13074)
* cqlsh copy-from: encode column names to avoid primary key parsing errors (CASSANDRA-12909)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/714edbce/src/java/org/apache/cassandra/cql3/ColumnCondition.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/ColumnCondition.java
index b13e534,3412e71..60e67f3
--- a/src/java/org/apache/cassandra/cql3/ColumnCondition.java
+++ b/src/java/org/apache/cassandra/cql3/ColumnCondition.java
@@@ -23,8 -23,16 +23,9 @@@ import java.util.*
import com.google.common.collect.Iterators;
import org.apache.cassandra.config.ColumnDefinition;
+ import org.apache.cassandra.cql3.Term.Terminal;
import org.apache.cassandra.cql3.functions.Function;
-import org.apache.cassandra.db.Cell;
-import org.apache.cassandra.db.ColumnFamily;
-import org.apache.cassandra.db.composites.CellName;
-import org.apache.cassandra.db.composites.CellNameType;
-import org.apache.cassandra.db.composites.Composite;
-import org.apache.cassandra.db.filter.ColumnSlice;
+import org.apache.cassandra.db.rows.*;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.transport.Server;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/714edbce/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index fd02a69,6396727..8adce7a
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@@ -155,8 -150,6 +159,7 @@@ public class InsertUpdateIfConditionTes
"UPDATE %s SET v1 = 3, v2 = 'bar' WHERE k = 0 IF v1 >= ?", unset());
assertInvalidMessage("Invalid 'unset' value in condition",
"UPDATE %s SET v1 = 3, v2 = 'bar' WHERE k = 0 IF v1 != ?", unset());
- assertInvalidMessage("Invalid 'unset' value in condition",
- "UPDATE %s SET v1 = 3, v2 = 'bar' WHERE k = 0 IF v1 IN (?, ?)", unset(), 1);
++
}
/**
@@@ -1482,107 -1306,158 +1485,262 @@@
row(7, 7, null, null, 7));
}
+ /**
+ * Test for CASSANDRA-12060, using a table without clustering.
+ */
+ @Test
+ public void testMultiExistConditionOnSameRowNoClustering() throws Throwable
+ {
+ createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 text, v2 text)");
+
+ // Multiple inserts on the same row with not exist conditions
+ assertRows(execute("BEGIN BATCH "
+ + "INSERT INTO %1$s (k, v1) values (0, 'foo') IF NOT EXISTS; "
+ + "INSERT INTO %1$s (k, v2) values (0, 'bar') IF NOT EXISTS; "
+ + "APPLY BATCH"),
+ row(true));
+
+ assertRows(execute("SELECT * FROM %s WHERE k = 0"), row(0, "foo", "bar"));
+
+ // Same, but both insert on the same column: doing so would almost surely be a user error, but that's the
+ // original case reported in #12867, so being thorough.
+ assertRows(execute("BEGIN BATCH "
+ + "INSERT INTO %1$s (k, v1) values (1, 'foo') IF NOT EXISTS; "
+ + "INSERT INTO %1$s (k, v1) values (1, 'bar') IF NOT EXISTS; "
+ + "APPLY BATCH"),
+ row(true));
+
+ // As all statement gets the same timestamp, the biggest value ends up winning, so that's "foo"
+ assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, "foo", null));
+
+ // Multiple deletes on the same row with exists conditions (note that this is somewhat non-sensical, one of the
+ // delete is redundant, we're just checking it doesn't break something)
+ assertRows(execute("BEGIN BATCH "
+ + "DELETE FROM %1$s WHERE k = 0 IF EXISTS; "
+ + "DELETE FROM %1$s WHERE k = 0 IF EXISTS; "
+ + "APPLY BATCH"),
+ row(true));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE k = 0"));
+
+ // Validate we can't mix different type of conditions however
+ assertInvalidMessage("Cannot mix IF EXISTS and IF NOT EXISTS conditions for the same row",
+ "BEGIN BATCH "
+ + "INSERT INTO %1$s (k, v1) values (1, 'foo') IF NOT EXISTS; "
+ + "DELETE FROM %1$s WHERE k = 1 IF EXISTS; "
+ + "APPLY BATCH");
+
+ assertInvalidMessage("Cannot mix IF conditions and IF NOT EXISTS for the same row",
+ "BEGIN BATCH "
+ + "INSERT INTO %1$s (k, v1) values (1, 'foo') IF NOT EXISTS; "
+ + "UPDATE %1$s SET v2 = 'bar' WHERE k = 1 IF v1 = 'foo'; "
+ + "APPLY BATCH");
+ }
+
+ /**
+ * Test for CASSANDRA-12060, using a table with clustering.
+ */
+ @Test
+ public void testMultiExistConditionOnSameRowClustering() throws Throwable
+ {
+ createTable("CREATE TABLE %s (k int, t int, v1 text, v2 text, PRIMARY KEY (k, t))");
+
+ // Multiple inserts on the same row with not exist conditions
+ assertRows(execute("BEGIN BATCH "
+ + "INSERT INTO %1$s (k, t, v1) values (0, 0, 'foo') IF NOT EXISTS; "
+ + "INSERT INTO %1$s (k, t, v2) values (0, 0, 'bar') IF NOT EXISTS; "
+ + "APPLY BATCH"),
+ row(true));
+
+ assertRows(execute("SELECT * FROM %s WHERE k = 0"), row(0, 0, "foo", "bar"));
+
+ // Same, but both insert on the same column: doing so would almost surely be a user error, but that's the
+ // original case reported in #12867, so being thorough.
+ assertRows(execute("BEGIN BATCH "
+ + "INSERT INTO %1$s (k, t, v1) values (1, 0, 'foo') IF NOT EXISTS; "
+ + "INSERT INTO %1$s (k, t, v1) values (1, 0, 'bar') IF NOT EXISTS; "
+ + "APPLY BATCH"),
+ row(true));
+
+ // As all statement gets the same timestamp, the biggest value ends up winning, so that's "foo"
+ assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, 0, "foo", null));
+
+ // Multiple deletes on the same row with exists conditions (note that this is somewhat non-sensical, one of the
+ // delete is redundant, we're just checking it doesn't break something)
+ assertRows(execute("BEGIN BATCH "
+ + "DELETE FROM %1$s WHERE k = 0 AND t = 0 IF EXISTS; "
+ + "DELETE FROM %1$s WHERE k = 0 AND t = 0 IF EXISTS; "
+ + "APPLY BATCH"),
+ row(true));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE k = 0"));
+
+ // Validate we can't mix different type of conditions however
+ assertInvalidMessage("Cannot mix IF EXISTS and IF NOT EXISTS conditions for the same row",
+ "BEGIN BATCH "
+ + "INSERT INTO %1$s (k, t, v1) values (1, 0, 'foo') IF NOT EXISTS; "
+ + "DELETE FROM %1$s WHERE k = 1 AND t = 0 IF EXISTS; "
+ + "APPLY BATCH");
+
+ assertInvalidMessage("Cannot mix IF conditions and IF NOT EXISTS for the same row",
+ "BEGIN BATCH "
+ + "INSERT INTO %1$s (k, t, v1) values (1, 0, 'foo') IF NOT EXISTS; "
+ + "UPDATE %1$s SET v2 = 'bar' WHERE k = 1 AND t = 0 IF v1 = 'foo'; "
+ + "APPLY BATCH");
+ }
++
+ @Test
+ public void testInMarkerWithUDTs() throws Throwable
+ {
+ String typename = createType("CREATE TYPE %s (a int, b text)");
+ String myType = KEYSPACE + '.' + typename;
+
+ createTable("CREATE TABLE %s (k int PRIMARY KEY, v frozen<" + myType + "> )");
+
+ Object v = userType(0, "abc");
+ execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, v);
+
+ // Does not apply
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN (?, ?)", userType(1, "abc"), userType(0, "ac")),
+ row(false, v));
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN (?, ?)", userType(1, "abc"), null),
+ row(false, v));
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN (?, ?)", userType(1, "abc"), unset()),
+ row(false, v));
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN (?, ?)", null, null),
+ row(false, v));
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN (?, ?)", unset(), unset()),
+ row(false, v));
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN ?", list(userType(1, "abc"), userType(0, "ac"))),
+ row(false, v));
+
+ // Does apply
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN (?, ?)", userType(0, "abc"), userType(0, "ac")),
+ row(true));
+ assertRows(execute("UPDATE %s SET v = {a: 1, b: 'bc'} WHERE k = 0 IF v IN (?, ?)", userType(0, "bc"), null),
+ row(true));
+ assertRows(execute("UPDATE %s SET v = {a: 1, b: 'ac'} WHERE k = 0 IF v IN (?, ?, ?)", userType(0, "bc"), unset(), userType(1, "bc")),
+ row(true));
+ assertRows(execute("UPDATE %s SET v = {a: 0, b: 'abc'} WHERE k = 0 IF v IN ?", list(userType(1, "ac"), userType(0, "ac"))),
+ row(true));
+
+ assertInvalidMessage("Invalid null list in IN condition",
+ "UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN ?", (List<ByteBuffer>) null);
+ assertInvalidMessage("Invalid 'unset' value in condition",
+ "UPDATE %s SET v = {a: 0, b: 'bc'} WHERE k = 0 IF v IN ?", unset());
+ }
+
+ @Test
+ public void testInMarkerWithLists() throws Throwable
+ {
+ for (boolean frozen : new boolean[]{false, true})
+ {
+ createTable(String.format("CREATE TABLE %%s (k int PRIMARY KEY, l %s)",
+ frozen
+ ? "frozen<list<text>>"
+ : "list<text>"));
+
+ execute("INSERT INTO %s(k, l) VALUES (0, ['foo', 'bar', 'foobar'])");
+
+ // Does not apply
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN (?, ?)", list("foo", "foobar"), list("bar", "foobar")),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN (?, ?)", list("foo", "foobar"), null),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN (?, ?)", list("foo", "foobar"), unset()),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN (?, ?)", null, null),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN ?", list(list("foo", "foobar"), list("bar", "foobar"))),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l[?] IN ?", 1, list("foo", "foobar")),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l[?] IN (?, ?)", 1, "foo", "foobar"),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l[?] IN (?, ?)", 1, "foo", null),
+ row(false, list("foo", "bar", "foobar")));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l[?] IN (?, ?)", 1, "foo", unset()),
+ row(false, list("foo", "bar", "foobar")));
+
+ // Does apply
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN (?, ?)", list("foo", "bar", "foobar"), list("bar", "foobar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'foobar'] WHERE k = 0 IF l IN (?, ?, ?)", list("foo", "bar", "foobar"), null, list("foo", "bar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN (?, ?, ?)", list("foo", "bar", "foobar"), unset(), list("foo", "foobar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'foobar'] WHERE k = 0 IF l IN (?, ?)", list("bar", "foobar"), list("foo", "bar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l[?] IN ?", 1, list("bar", "foobar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'foobar'] WHERE k = 0 IF l[?] IN (?, ?, ?)", 1, "bar", null, "foobar"),
+ row(true));
+ assertRows(execute("UPDATE %s SET l = ['foo', 'foobar'] WHERE k = 0 IF l[?] IN (?, ?, ?)", 1, "bar", unset(), "foobar"),
+ row(true));
+
+ assertInvalidMessage("Invalid null list in IN condition",
+ "UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN ?", (List<ByteBuffer>) null);
+ assertInvalidMessage("Invalid 'unset' value in condition",
+ "UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l IN ?", unset());
+ assertInvalidMessage("Invalid 'unset' value in condition",
+ "UPDATE %s SET l = ['foo', 'bar'] WHERE k = 0 IF l[?] IN ?", 1, unset());
+ }
+ }
+
+ @Test
+ public void testInMarkerWithMaps() throws Throwable
+ {
+ for (boolean frozen : new boolean[] {false, true})
+ {
+ createTable(String.format("CREATE TABLE %%s (k int PRIMARY KEY, m %s)",
+ frozen
+ ? "frozen<map<text, text>>"
+ : "map<text, text>"));
+
+ execute("INSERT INTO %s (k, m) VALUES (0, {'foo' : 'bar'})");
+
+ // Does not apply
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN (?, ?)", map("foo", "foobar"), map("bar", "foobar")),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN (?, ?)", map("foo", "foobar"), null),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN (?, ?)", map("foo", "foobar"), unset()),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN (?, ?)", null, null),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN ?", list(map("foo", "foobar"), map("bar", "foobar"))),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN ?", "foo", list("foo", "foobar")),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN (?, ?)", "foo", "foo", "foobar"),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN (?, ?)", "foo", "foo", null),
+ row(false, map("foo", "bar")));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN (?, ?)", "foo", "foo", unset()),
+ row(false, map("foo", "bar")));
+
+ // Does apply
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN (?, ?)", map("foo", "foobar"), map("foo", "bar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'bar'} WHERE k = 0 IF m IN (?, ?, ?)", map("bar", "foobar"), null, map("foo", "foobar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'bar'} WHERE k = 0 IF m IN (?, ?, ?)", map("bar", "foobar"), unset(), map("foo", "bar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN ?", list(map("foo", "bar"), map("bar", "foobar"))),
+ row(true));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'bar'} WHERE k = 0 IF m[?] IN ?", "foo", list("bar", "foobar")),
+ row(true));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN (?, ?, ?)", "foo", "bar", null, "foobar"),
+ row(true));
+ assertRows(execute("UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN (?, ?, ?)", "foo", "bar", unset(), "foobar"),
+ row(true));
+
+ assertInvalidMessage("Invalid null list in IN condition",
+ "UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN ?", (List<ByteBuffer>) null);
+ assertInvalidMessage("Invalid 'unset' value in condition",
+ "UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m IN ?", unset());
+ assertInvalidMessage("Invalid 'unset' value in condition",
+ "UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN ?", "foo", unset());
+ }
+ }
}