Merge branch cassandra-3.0 into cassandra-3.11
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/6b8da361 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/6b8da361 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/6b8da361 Branch: refs/heads/cassandra-3.11 Commit: 6b8da3612bd01317220067251b13ed2c48fab264 Parents: 1092f5e 0eebc6e Author: Benjamin Lerer <b.le...@gmail.com> Authored: Mon Mar 20 12:25:41 2017 +0100 Committer: Benjamin Lerer <b.le...@gmail.com> Committed: Mon Mar 20 12:25:41 2017 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../apache/cassandra/db/filter/RowFilter.java | 21 +++++----- src/java/org/apache/cassandra/db/rows/Row.java | 2 +- .../validation/entities/SecondaryIndexTest.java | 39 ++++++++++++++++++ .../cql3/validation/operations/SelectTest.java | 42 ++++++++++++++++++++ 5 files changed, 95 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6b8da361/CHANGES.txt ---------------------------------------------------------------------- diff --cc CHANGES.txt index 44321ef,10402f3..a800f82 --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -1,16 -1,5 +1,17 @@@ -3.0.13 +3.11.0 + * Support unaligned memory access for AArch64 (CASSANDRA-13326) + * Improve SASI range iterator efficiency on intersection with an empty range (CASSANDRA-12915). + * Fix equality comparisons of columns using the duration type (CASSANDRA-13174) + * Obfuscate password in stress-graphs (CASSANDRA-12233) + * Move to FastThreadLocalThread and FastThreadLocal (CASSANDRA-13034) + * nodetool stopdaemon errors out (CASSANDRA-13030) + * Tables in system_distributed should not use gcgs of 0 (CASSANDRA-12954) + * Fix primary index calculation for SASI (CASSANDRA-12910) + * More fixes to the TokenAllocator (CASSANDRA-12990) + * NoReplicationTokenAllocator should work with zero replication factor (CASSANDRA-12983) + * Address message coalescing regression (CASSANDRA-12676) +Merged from 3.0: + * Fix CONTAINS filtering for null collections (CASSANDRA-13246) * Applying: Use a unique metric reservoir per test run when using Cassandra-wide metrics residing in MBeans (CASSANDRA-13216) * Propagate row deletions in 2i tables on upgrade (CASSANDRA-13320) * Slice.isEmpty() returns false for some empty slices (CASSANDRA-13305) http://git-wip-us.apache.org/repos/asf/cassandra/blob/6b8da361/src/java/org/apache/cassandra/db/filter/RowFilter.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6b8da361/src/java/org/apache/cassandra/db/rows/Row.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6b8da361/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java index c03b0cc,5d43bd2..88c6f17 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java @@@ -420,27 -401,64 +420,66 @@@ public class SecondaryIndexTest extend execute("INSERT INTO %s (k, v, l, s, m) VALUES (1, 0, [1, 2, 4], {}, {'b' : 1})"); execute("INSERT INTO %s (k, v, l, s, m) VALUES (1, 1, [4, 5], {'d'}, {'a' : 1, 'b' : 3})"); - // lists - assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 1"), row(1, 0), row(0, 0), row(0, 2)); - assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND l CONTAINS 1"), row(0, 0), row(0, 2)); - assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 2"), row(1, 0), row(0, 0)); - assertEmpty(execute("SELECT k, v FROM %s WHERE l CONTAINS 6")); + beforeAndAfterFlush(() -> { + // lists + assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 1"), row(1, 0), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND l CONTAINS 1"), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 2"), row(1, 0), row(0, 0)); + assertEmpty(execute("SELECT k, v FROM %s WHERE l CONTAINS 6")); - // sets - assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'a'"), row(0, 0), row(0, 2)); - assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND s CONTAINS 'a'"), row(0, 0), row(0, 2)); - assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'd'"), row(1, 1)); - assertEmpty(execute("SELECT k, v FROM %s WHERE s CONTAINS 'e'")); + // sets + assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'a'"), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND s CONTAINS 'a'"), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'd'"), row(1, 1)); + assertEmpty(execute("SELECT k, v FROM %s WHERE s CONTAINS 'e'")); - // maps - assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 1"), row(1, 0), row(1, 1), row(0, 0), row(0, 1)); - assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS 1"), row(0, 0), row(0, 1)); - assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 2"), row(0, 1)); - assertEmpty(execute("SELECT k, v FROM %s WHERE m CONTAINS 4")); + // maps + assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 1"), row(1, 0), row(1, 1), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS 1"), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 2"), row(0, 1)); + assertEmpty(execute("SELECT k, v FROM %s WHERE m CONTAINS 4")); + }); } + @Test + public void testSelectOnMultiIndexOnCollectionsWithNull() throws Throwable + { + createTable(" CREATE TABLE %s ( k int, v int, x text, l list<int>, s set<text>, m map<text, int>, PRIMARY KEY (k, v))"); + + createIndex("CREATE INDEX ON %s (x)"); + createIndex("CREATE INDEX ON %s (v)"); + createIndex("CREATE INDEX ON %s (s)"); + createIndex("CREATE INDEX ON %s (m)"); + + + execute("INSERT INTO %s (k, v, x, l, s, m) VALUES (0, 0, 'x', [1, 2], {'a'}, {'a' : 1})"); + execute("INSERT INTO %s (k, v, x, l, s, m) VALUES (0, 1, 'x', [3, 4], {'b', 'c'}, {'a' : 1, 'b' : 2})"); + execute("INSERT INTO %s (k, v, x, l, s, m) VALUES (0, 2, 'x', [1], {'a', 'c'}, {'c' : 3})"); + execute("INSERT INTO %s (k, v, x, l, s, m) VALUES (1, 0, 'x', [1, 2, 4], {}, {'b' : 1})"); + execute("INSERT INTO %s (k, v, x, l, s, m) VALUES (1, 1, 'x', [4, 5], {'d'}, {'a' : 1, 'b' : 3})"); + execute("INSERT INTO %s (k, v, x, l, s, m) VALUES (1, 2, 'x', null, null, null)"); + + beforeAndAfterFlush(() -> { + // lists + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND l CONTAINS 1 ALLOW FILTERING"), row(1, 0), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND k = 0 AND l CONTAINS 1 ALLOW FILTERING"), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND l CONTAINS 2 ALLOW FILTERING"), row(1, 0), row(0, 0)); + assertEmpty(execute("SELECT k, v FROM %s WHERE x = 'x' AND l CONTAINS 6 ALLOW FILTERING")); + + // sets + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND s CONTAINS 'a' ALLOW FILTERING" ), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND k = 0 AND s CONTAINS 'a' ALLOW FILTERING"), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND s CONTAINS 'd' ALLOW FILTERING"), row(1, 1)); + assertEmpty(execute("SELECT k, v FROM %s WHERE x = 'x' AND s CONTAINS 'e' ALLOW FILTERING")); + + // maps + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND m CONTAINS 1 ALLOW FILTERING"), row(1, 0), row(1, 1), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND k = 0 AND m CONTAINS 1 ALLOW FILTERING"), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE x = 'x' AND m CONTAINS 2 ALLOW FILTERING"), row(0, 1)); + assertEmpty(execute("SELECT k, v FROM %s WHERE x = 'x' AND m CONTAINS 4 ALLOW FILTERING")); + }); + } + /** * Migrated from cql_tests.py:TestCQL.map_keys_indexing() */ http://git-wip-us.apache.org/repos/asf/cassandra/blob/6b8da361/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java index f1fcfc3,f40ae4b..572d903 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java @@@ -4481,166 -2925,45 +4481,208 @@@ public class SelectTest extends CQLTest } @Test + public void testFilteringOnDurationColumn() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, d duration)"); + execute("INSERT INTO %s (k, d) VALUES (0, 1s)"); + execute("INSERT INTO %s (k, d) VALUES (1, 2s)"); + execute("INSERT INTO %s (k, d) VALUES (2, 1s)"); + + assertRows(execute("SELECT * FROM %s WHERE d=1s ALLOW FILTERING"), + row(0, Duration.from("1s")), + row(2, Duration.from("1s"))); + + assertInvalidMessage("IN predicates on non-primary-key columns (d) is not yet supported", + "SELECT * FROM %s WHERE d IN (1s, 2s) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on duration columns", + "SELECT * FROM %s WHERE d > 1s ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on duration columns", + "SELECT * FROM %s WHERE d >= 1s ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on duration columns", + "SELECT * FROM %s WHERE d <= 1s ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on duration columns", + "SELECT * FROM %s WHERE d < 1s ALLOW FILTERING"); + } + + @Test + public void testFilteringOnListContainingDurations() throws Throwable + { + for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE}) + { + String listType = String.format(frozen ? "frozen<%s>" : "%s", "list<duration>"); + + createTable("CREATE TABLE %s (k int PRIMARY KEY, l " + listType + ")"); + execute("INSERT INTO %s (k, l) VALUES (0, [1s, 2s])"); + execute("INSERT INTO %s (k, l) VALUES (1, [2s, 3s])"); + execute("INSERT INTO %s (k, l) VALUES (2, [1s, 3s])"); + + if (frozen) + assertRows(execute("SELECT * FROM %s WHERE l = [1s, 2s] ALLOW FILTERING"), + row(0, list(Duration.from("1s"), Duration.from("2s")))); + + assertInvalidMessage("IN predicates on non-primary-key columns (l) is not yet supported", + "SELECT * FROM %s WHERE l IN ([1s, 2s], [2s, 3s]) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE l > [2s, 3s] ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE l >= [2s, 3s] ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE l <= [2s, 3s] ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE l < [2s, 3s] ALLOW FILTERING"); + + assertRows(execute("SELECT * FROM %s WHERE l CONTAINS 1s ALLOW FILTERING"), + row(0, list(Duration.from("1s"), Duration.from("2s"))), + row(2, list(Duration.from("1s"), Duration.from("3s")))); + } + } + + @Test + public void testFilteringOnMapContainingDurations() throws Throwable + { + for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE}) + { + String mapType = String.format(frozen ? "frozen<%s>" : "%s", "map<int, duration>"); + + createTable("CREATE TABLE %s (k int PRIMARY KEY, m " + mapType + ")"); + execute("INSERT INTO %s (k, m) VALUES (0, {1:1s, 2:2s})"); + execute("INSERT INTO %s (k, m) VALUES (1, {2:2s, 3:3s})"); + execute("INSERT INTO %s (k, m) VALUES (2, {1:1s, 3:3s})"); + + if (frozen) + assertRows(execute("SELECT * FROM %s WHERE m = {1:1s, 2:2s} ALLOW FILTERING"), + row(0, map(1, Duration.from("1s"), 2, Duration.from("2s")))); + + assertInvalidMessage("IN predicates on non-primary-key columns (m) is not yet supported", + "SELECT * FROM %s WHERE m IN ({1:1s, 2:2s}, {1:1s, 3:3s}) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE m > {1:1s, 3:3s} ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE m >= {1:1s, 3:3s} ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE m <= {1:1s, 3:3s} ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on collections containing durations", + "SELECT * FROM %s WHERE m < {1:1s, 3:3s} ALLOW FILTERING"); + + assertRows(execute("SELECT * FROM %s WHERE m CONTAINS 1s ALLOW FILTERING"), + row(0, map(1, Duration.from("1s"), 2, Duration.from("2s"))), + row(2, map(1, Duration.from("1s"), 3, Duration.from("3s")))); + } + } + + @Test + public void testFilteringOnTupleContainingDurations() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, t tuple<int, duration>)"); + execute("INSERT INTO %s (k, t) VALUES (0, (1, 2s))"); + execute("INSERT INTO %s (k, t) VALUES (1, (2, 3s))"); + execute("INSERT INTO %s (k, t) VALUES (2, (1, 3s))"); + + assertRows(execute("SELECT * FROM %s WHERE t = (1, 2s) ALLOW FILTERING"), + row(0, tuple(1, Duration.from("2s")))); + + assertInvalidMessage("IN predicates on non-primary-key columns (t) is not yet supported", + "SELECT * FROM %s WHERE t IN ((1, 2s), (1, 3s)) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on tuples containing durations", + "SELECT * FROM %s WHERE t > (1, 2s) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on tuples containing durations", + "SELECT * FROM %s WHERE t >= (1, 2s) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on tuples containing durations", + "SELECT * FROM %s WHERE t <= (1, 2s) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on tuples containing durations", + "SELECT * FROM %s WHERE t < (1, 2s) ALLOW FILTERING"); + } + + @Test + public void testFilteringOnUdtContainingDurations() throws Throwable + { + String udt = createType("CREATE TYPE %s (i int, d duration)"); + + for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE}) + { + udt = String.format(frozen ? "frozen<%s>" : "%s", udt); + + createTable("CREATE TABLE %s (k int PRIMARY KEY, u " + udt + ")"); + execute("INSERT INTO %s (k, u) VALUES (0, {i: 1, d:2s})"); + execute("INSERT INTO %s (k, u) VALUES (1, {i: 2, d:3s})"); + execute("INSERT INTO %s (k, u) VALUES (2, {i: 1, d:3s})"); + + if (frozen) + assertRows(execute("SELECT * FROM %s WHERE u = {i: 1, d:2s} ALLOW FILTERING"), + row(0, userType("i", 1, "d", Duration.from("2s")))); + + assertInvalidMessage("IN predicates on non-primary-key columns (u) is not yet supported", + "SELECT * FROM %s WHERE u IN ({i: 2, d:3s}, {i: 1, d:3s}) ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations", + "SELECT * FROM %s WHERE u > {i: 1, d:3s} ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations", + "SELECT * FROM %s WHERE u >= {i: 1, d:3s} ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations", + "SELECT * FROM %s WHERE u <= {i: 1, d:3s} ALLOW FILTERING"); + + assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations", + "SELECT * FROM %s WHERE u < {i: 1, d:3s} ALLOW FILTERING"); + } + } ++ ++ @Test + public void testFilteringOnCollectionsWithNull() throws Throwable + { + createTable(" CREATE TABLE %s ( k int, v int, l list<int>, s set<text>, m map<text, int>, PRIMARY KEY (k, v))"); + + createIndex("CREATE INDEX ON %s (v)"); + createIndex("CREATE INDEX ON %s (s)"); + createIndex("CREATE INDEX ON %s (m)"); + + + execute("INSERT INTO %s (k, v, l, s, m) VALUES (0, 0, [1, 2], {'a'}, {'a' : 1})"); + execute("INSERT INTO %s (k, v, l, s, m) VALUES (0, 1, [3, 4], {'b', 'c'}, {'a' : 1, 'b' : 2})"); + execute("INSERT INTO %s (k, v, l, s, m) VALUES (0, 2, [1], {'a', 'c'}, {'c' : 3})"); + execute("INSERT INTO %s (k, v, l, s, m) VALUES (1, 0, [1, 2, 4], {}, {'b' : 1})"); + execute("INSERT INTO %s (k, v, l, s, m) VALUES (1, 1, [4, 5], {'d'}, {'a' : 1, 'b' : 3})"); + execute("INSERT INTO %s (k, v, l, s, m) VALUES (1, 2, null, null, null)"); + + beforeAndAfterFlush(() -> { + // lists + assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 1 ALLOW FILTERING"), row(1, 0), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND l CONTAINS 1 ALLOW FILTERING"), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 2 ALLOW FILTERING"), row(1, 0), row(0, 0)); + assertEmpty(execute("SELECT k, v FROM %s WHERE l CONTAINS 6 ALLOW FILTERING")); + + // sets + assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'a' ALLOW FILTERING" ), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND s CONTAINS 'a' ALLOW FILTERING"), row(0, 0), row(0, 2)); + assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'd' ALLOW FILTERING"), row(1, 1)); + assertEmpty(execute("SELECT k, v FROM %s WHERE s CONTAINS 'e' ALLOW FILTERING")); + + // maps + assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 1 ALLOW FILTERING"), row(1, 0), row(1, 1), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS 1 ALLOW FILTERING"), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 2 ALLOW FILTERING"), row(0, 1)); + assertEmpty(execute("SELECT k, v FROM %s WHERE m CONTAINS 4 ALLOW FILTERING")); + + assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS KEY 'a' ALLOW FILTERING"), row(1, 1), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS KEY 'a' ALLOW FILTERING"), row(0, 0), row(0, 1)); + assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS KEY 'c' ALLOW FILTERING"), row(0, 2)); + }); + } - }