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/1800a5b6 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1800a5b6 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1800a5b6 Branch: refs/heads/trunk Commit: 1800a5b627ce8fa4186d4b52902d029920bd8e5a Parents: a529e6a c08eeaf Author: Sam Tunnicliffe <[email protected]> Authored: Mon May 2 11:12:01 2016 +0100 Committer: Sam Tunnicliffe <[email protected]> Committed: Mon May 2 11:14:21 2016 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../apache/cassandra/db/filter/RowFilter.java | 22 ++++++ .../cql3/validation/entities/CountersTest.java | 76 +++++++++++++++++++- .../cql3/validation/operations/SelectTest.java | 38 +++++++++- 4 files changed, 135 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/1800a5b6/CHANGES.txt ---------------------------------------------------------------------- diff --cc CHANGES.txt index b1ca6dd,95f450b..d30b7a4 --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -1,67 -1,5 +1,68 @@@ -3.0.6 +3.6 + * Add units to stress ouput (CASSANDRA-11352) + * Fix PER PARTITION LIMIT for single and multi partitions queries (CASSANDRA-11603) + * Add uncompressed chunk cache for RandomAccessReader (CASSANDRA-5863) + * Clarify ClusteringPrefix hierarchy (CASSANDRA-11213) + * Always perform collision check before joining ring (CASSANDRA-10134) + * SSTableWriter output discrepancy (CASSANDRA-11646) + * Fix potential timeout in NativeTransportService.testConcurrentDestroys (CASSANDRA-10756) + * Support large partitions on the 3.0 sstable format (CASSANDRA-11206) + * Add support to rebuild from specific range (CASSANDRA-10406) + * Optimize the overlapping lookup by calculating all the + bounds in advance (CASSANDRA-11571) + * Support json/yaml output in noetool tablestats (CASSANDRA-5977) + * (stress) Add datacenter option to -node options (CASSANDRA-11591) + * Fix handling of empty slices (CASSANDRA-11513) + * Make number of cores used by cqlsh COPY visible to testing code (CASSANDRA-11437) + * Allow filtering on clustering columns for queries without secondary indexes (CASSANDRA-11310) + * Refactor Restriction hierarchy (CASSANDRA-11354) + * Eliminate allocations in R/W path (CASSANDRA-11421) + * Update Netty to 4.0.36 (CASSANDRA-11567) + * Fix PER PARTITION LIMIT for queries requiring post-query ordering (CASSANDRA-11556) + * Allow instantiation of UDTs and tuples in UDFs (CASSANDRA-10818) + * Support UDT in CQLSSTableWriter (CASSANDRA-10624) + * Support for non-frozen user-defined types, updating + individual fields of user-defined types (CASSANDRA-7423) + * Make LZ4 compression level configurable (CASSANDRA-11051) + * Allow per-partition LIMIT clause in CQL (CASSANDRA-7017) + * Make custom filtering more extensible with UserExpression (CASSANDRA-11295) + * Improve field-checking and error reporting in cassandra.yaml (CASSANDRA-10649) + * Print CAS stats in nodetool proxyhistograms (CASSANDRA-11507) + * More user friendly error when providing an invalid token to nodetool (CASSANDRA-9348) + * Add static column support to SASI index (CASSANDRA-11183) + * Support EQ/PREFIX queries in SASI CONTAINS mode without tokenization (CASSANDRA-11434) + * Support LIKE operator in prepared statements (CASSANDRA-11456) + * Add a command to see if a Materialized View has finished building (CASSANDRA-9967) + * Log endpoint and port associated with streaming operation (CASSANDRA-8777) + * Print sensible units for all log messages (CASSANDRA-9692) + * Upgrade Netty to version 4.0.34 (CASSANDRA-11096) + * Break the CQL grammar into separate Parser and Lexer (CASSANDRA-11372) + * Compress only inter-dc traffic by default (CASSANDRA-8888) + * Add metrics to track write amplification (CASSANDRA-11420) + * cassandra-stress: cannot handle "value-less" tables (CASSANDRA-7739) + * Add/drop multiple columns in one ALTER TABLE statement (CASSANDRA-10411) + * Add require_endpoint_verification opt for internode encryption (CASSANDRA-9220) + * Add auto import java.util for UDF code block (CASSANDRA-11392) + * Add --hex-format option to nodetool getsstables (CASSANDRA-11337) + * sstablemetadata should print sstable min/max token (CASSANDRA-7159) + * Do not wrap CassandraException in TriggerExecutor (CASSANDRA-9421) + * COPY TO should have higher double precision (CASSANDRA-11255) + * Stress should exit with non-zero status after failure (CASSANDRA-10340) + * Add client to cqlsh SHOW_SESSION (CASSANDRA-8958) + * Fix nodetool tablestats keyspace level metrics (CASSANDRA-11226) + * Store repair options in parent_repair_history (CASSANDRA-11244) + * Print current leveling in sstableofflinerelevel (CASSANDRA-9588) + * Change repair message for keyspaces with RF 1 (CASSANDRA-11203) + * Remove hard-coded SSL cipher suites and protocols (CASSANDRA-10508) + * Improve concurrency in CompactionStrategyManager (CASSANDRA-10099) + * (cqlsh) interpret CQL type for formatting blobs (CASSANDRA-11274) + * Refuse to start and print txn log information in case of disk + corruption (CASSANDRA-10112) + * Resolve some eclipse-warnings (CASSANDRA-11086) + * (cqlsh) Show static columns in a different color (CASSANDRA-11059) + * Allow to remove TTLs on table with default_time_to_live (CASSANDRA-11207) +Merged from 3.0: + * Fix queries with filtering on counter columns (CASSANDRA-11629) * Improve tombstone printing in sstabledump (CASSANDRA-11655) * Fix paging for range queries where all clustering columns are specified (CASSANDRA-11669) * Don't require HEAP_NEW_SIZE to be set when using G1 (CASSANDRA-11600) http://git-wip-us.apache.org/repos/asf/cassandra/blob/1800a5b6/src/java/org/apache/cassandra/db/filter/RowFilter.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/db/filter/RowFilter.java index 0ef29c2,8060f23..ea60669 --- a/src/java/org/apache/cassandra/db/filter/RowFilter.java +++ b/src/java/org/apache/cassandra/db/filter/RowFilter.java @@@ -32,9 -27,9 +32,10 @@@ import org.apache.cassandra.config.CFMe import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.cql3.Operator; import org.apache.cassandra.db.*; + import org.apache.cassandra.db.context.*; import org.apache.cassandra.db.marshal.*; -import org.apache.cassandra.db.partitions.*; +import org.apache.cassandra.db.partitions.ImmutableBTreePartition; +import org.apache.cassandra.db.partitions.UnfilteredPartitionIterator; import org.apache.cassandra.db.rows.*; import org.apache.cassandra.db.transform.Transformation; import org.apache.cassandra.exceptions.InvalidRequestException; @@@ -654,11 -612,28 +655,32 @@@ public abstract class RowFilter impleme case LTE: case GTE: case GT: + { + assert !column.isComplex() : "Only CONTAINS and CONTAINS_KEY are supported for 'complex' types"; + + // In order to support operators on Counter types, their value has to be extracted from internal + // representation. See CASSANDRA-11629 + if (column.type.isCounter()) + { + ByteBuffer foundValue = getValue(metadata, partitionKey, row); + if (foundValue == null) + return false; + + ByteBuffer counterValue = LongType.instance.decompose(CounterContext.instance().total(foundValue)); + return operator.isSatisfiedBy(LongType.instance, counterValue, value); + } + else + { + // Note that CQL expression are always of the form 'x < 4', i.e. the tested value is on the left. + ByteBuffer foundValue = getValue(metadata, partitionKey, row); + return foundValue != null && operator.isSatisfiedBy(column.type, foundValue, value); + } + } case NEQ: + case LIKE_PREFIX: + case LIKE_SUFFIX: + case LIKE_CONTAINS: + case LIKE_MATCHES: { assert !column.isComplex() : "Only CONTAINS and CONTAINS_KEY are supported for 'complex' types"; ByteBuffer foundValue = getValue(metadata, partitionKey, row); http://git-wip-us.apache.org/repos/asf/cassandra/blob/1800a5b6/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java index e54d105,89fd767..7a096b3 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java @@@ -112,4 -112,78 +112,78 @@@ public class CountersTest extends CQLTe row(1L) // no change to the counter value ); } - } + + @Test + public void testCounterFiltering() throws Throwable + { - for (String compactStorageClause: new String[] {"", " WITH COMPACT STORAGE"}) ++ for (String compactStorageClause : new String[]{ "", " WITH COMPACT STORAGE" }) + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, a counter)" + compactStorageClause); + + for (int i = 0; i < 10; i++) + execute("UPDATE %s SET a = a + ? WHERE k = ?", (long) i, i); + + execute("UPDATE %s SET a = a + ? WHERE k = ?", 6L, 10); + + // GT + assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE a > ? ALLOW FILTERING", 5L), + row(6, 6L), + row(7, 7L), + row(8, 8L), + row(9, 9L), + row(10, 6L)); + + // GTE + assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE a >= ? ALLOW FILTERING", 6L), + row(6, 6L), + row(7, 7L), + row(8, 8L), + row(9, 9L), + row(10, 6L)); + + // LT + assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE a < ? ALLOW FILTERING", 3L), + row(0, 0L), + row(1, 1L), + row(2, 2L)); + + // LTE + assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE a <= ? ALLOW FILTERING", 3L), + row(0, 0L), + row(1, 1L), + row(2, 2L), + row(3, 3L)); + + // EQ + assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE a = ? ALLOW FILTERING", 6L), + row(6, 6L), + row(10, 6L)); + } + } + + @Test + public void testCounterFilteringWithNull() throws Throwable + { + for (String compactStorageClause : new String[]{ "", " WITH COMPACT STORAGE" }) + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, a counter, b counter)" + compactStorageClause); + execute("UPDATE %s SET a = a + ? WHERE k = ?", 1L, 1); + + assertRows(execute("SELECT * FROM %s WHERE a > ? ALLOW FILTERING", 0L), + row(1, 1L, null)); + // GT + assertEmpty(execute("SELECT * FROM %s WHERE b > ? ALLOW FILTERING", 1L)); + // GTE + assertEmpty(execute("SELECT * FROM %s WHERE b >= ? ALLOW FILTERING", 1L)); + // LT + assertEmpty(execute("SELECT * FROM %s WHERE b < ? ALLOW FILTERING", 1L)); + // LTE + assertEmpty(execute("SELECT * FROM %s WHERE b <= ? ALLOW FILTERING", 1L)); + // EQ + assertEmpty(execute("SELECT * FROM %s WHERE b = ? ALLOW FILTERING", 1L)); + // with null + assertInvalidMessage("Invalid null value for counter increment/decrement", + "SELECT * FROM %s WHERE b = null ALLOW FILTERING"); + } + } -} ++} http://git-wip-us.apache.org/repos/asf/cassandra/blob/1800a5b6/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java index 6e3b6eb,b49bd87..f91ec5a --- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java @@@ -2437,381 -2426,6 +2437,417 @@@ public class SelectTest extends CQLTest unset()); } + @Test + public void filteringOnClusteringColumns() throws Throwable + { + createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY (a, b, c))"); + + execute("INSERT INTO %s (a,b,c,d) VALUES (11, 12, 13, 14)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (11, 15, 16, 17)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (21, 22, 23, 24)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (31, 32, 33, 34)"); + + beforeAndAfterFlush(() -> { + + assertRows(execute("SELECT * FROM %s WHERE a = 11 AND b = 15"), + row(11, 15, 16, 17)); + + assertInvalidMessage("Clustering column \"c\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE a = 11 AND b > 12 AND c = 15"); + + assertRows(execute("SELECT * FROM %s WHERE a = 11 AND b = 15 AND c > 15"), + row(11, 15, 16, 17)); + + assertRows(execute("SELECT * FROM %s WHERE a = 11 AND b > 12 AND c > 13 AND d = 17 ALLOW FILTERING"), + row(11, 15, 16, 17)); + assertInvalidMessage("Clustering column \"c\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE a = 11 AND b > 12 AND c > 13 and d = 17"); + + assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c > 30 ALLOW FILTERING"), + row(31, 32, 33, 34)); + assertInvalidMessage("Clustering column \"c\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE b > 20 AND c > 30"); + + assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c < 30 ALLOW FILTERING"), + row(21, 22, 23, 24)); + assertInvalidMessage("Clustering column \"c\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE b > 20 AND c < 30"); + + assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c = 33 ALLOW FILTERING"), + row(31, 32, 33, 34)); + assertInvalidMessage("Clustering column \"c\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE b > 20 AND c = 33"); + + assertRows(execute("SELECT * FROM %s WHERE c = 33 ALLOW FILTERING"), + row(31, 32, 33, 34)); + assertInvalidMessage("PRIMARY KEY column \"c\" cannot be restricted as preceding column \"b\" is not restricted", + "SELECT * FROM %s WHERE c = 33"); + }); + + // -------------------------------------------------- + // Clustering column within and across partition keys + // -------------------------------------------------- + createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY (a, b, c))"); + + execute("INSERT INTO %s (a,b,c,d) VALUES (11, 12, 13, 14)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (11, 15, 16, 17)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (11, 18, 19, 20)"); + + execute("INSERT INTO %s (a,b,c,d) VALUES (21, 22, 23, 24)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (21, 25, 26, 27)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (21, 28, 29, 30)"); + + execute("INSERT INTO %s (a,b,c,d) VALUES (31, 32, 33, 34)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (31, 35, 36, 37)"); + execute("INSERT INTO %s (a,b,c,d) VALUES (31, 38, 39, 40)"); + + beforeAndAfterFlush(() -> { + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE a = 21 AND c > 23"), + row(21, 25, 26, 27), + row(21, 28, 29, 30)); + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE a = 21 AND c > 23 ORDER BY b DESC"), + row(21, 28, 29, 30), + row(21, 25, 26, 27)); + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c > 16 and c < 36"), + row(11, 18, 19, 20), + row(21, 22, 23, 24), + row(21, 25, 26, 27), + row(21, 28, 29, 30), + row(31, 32, 33, 34)); + }); + } + + @Test + public void filteringWithMultiColumnSlices() throws Throwable + { + //---------------------------------------- + // Multi-column slices for clustering keys + //---------------------------------------- + createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, PRIMARY KEY (a, b, c, d))"); + + execute("INSERT INTO %s (a,b,c,d,e) VALUES (11, 12, 13, 14, 15)"); + execute("INSERT INTO %s (a,b,c,d,e) VALUES (21, 22, 23, 24, 25)"); + execute("INSERT INTO %s (a,b,c,d,e) VALUES (31, 32, 33, 34, 35)"); + + beforeAndAfterFlush(() -> { + + assertRows(execute("SELECT * FROM %s WHERE b = 22 AND d = 24 ALLOW FILTERING"), + row(21, 22, 23, 24, 25)); + assertInvalidMessage("PRIMARY KEY column \"d\" cannot be restricted as preceding column \"c\" is not restricted", + "SELECT * FROM %s WHERE b = 22 AND d = 24"); + + assertRows(execute("SELECT * FROM %s WHERE (b, c) > (20, 30) AND d = 34 ALLOW FILTERING"), + row(31, 32, 33, 34, 35)); + assertInvalidMessage("Clustering column \"d\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE (b, c) > (20, 30) AND d = 34"); + }); + } + + @Test + public void containsFilteringForClusteringKeys() throws Throwable + { + //------------------------------------------------- + // Frozen collections filtering for clustering keys + //------------------------------------------------- + + // first clustering column + createTable("CREATE TABLE %s (a int, b frozen<list<int>>, c int, PRIMARY KEY (a, b, c))"); + execute("INSERT INTO %s (a,b,c) VALUES (?, ?, ?)", 11, list(1, 3), 14); + execute("INSERT INTO %s (a,b,c) VALUES (?, ?, ?)", 21, list(2, 3), 24); + execute("INSERT INTO %s (a,b,c) VALUES (?, ?, ?)", 21, list(3, 3), 34); + + beforeAndAfterFlush(() -> { + + assertRows(execute("SELECT * FROM %s WHERE a = 21 AND b CONTAINS 2 ALLOW FILTERING"), + row(21, list(2, 3), 24)); + assertInvalidMessage("Clustering columns can only be restricted with CONTAINS with a secondary index or filtering", + "SELECT * FROM %s WHERE a = 21 AND b CONTAINS 2"); + + assertRows(execute("SELECT * FROM %s WHERE b CONTAINS 2 ALLOW FILTERING"), + row(21, list(2, 3), 24)); + assertInvalidMessage("Clustering columns can only be restricted with CONTAINS with a secondary index or filtering", + "SELECT * FROM %s WHERE b CONTAINS 2"); + + assertRows(execute("SELECT * FROM %s WHERE b CONTAINS 3 ALLOW FILTERING"), + row(11, list(1, 3), 14), + row(21, list(2, 3), 24), + row(21, list(3, 3), 34)); + }); + + // non-first clustering column + createTable("CREATE TABLE %s (a int, b int, c frozen<list<int>>, d int, PRIMARY KEY (a, b, c))"); + + execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", 11, 12, list(1, 3), 14); + execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", 21, 22, list(2, 3), 24); + execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", 21, 22, list(3, 3), 34); + + beforeAndAfterFlush(() -> { + + assertRows(execute("SELECT * FROM %s WHERE a = 21 AND c CONTAINS 2 ALLOW FILTERING"), + row(21, 22, list(2, 3), 24)); + assertInvalidMessage("Clustering columns can only be restricted with CONTAINS with a secondary index or filtering", + "SELECT * FROM %s WHERE a = 21 AND c CONTAINS 2"); + + assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c CONTAINS 2 ALLOW FILTERING"), + row(21, 22, list(2, 3), 24)); + assertInvalidMessage("Clustering column \"c\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE b > 20 AND c CONTAINS 2"); + + assertRows(execute("SELECT * FROM %s WHERE c CONTAINS 3 ALLOW FILTERING"), + row(11, 12, list(1, 3), 14), + row(21, 22, list(2, 3), 24), + row(21, 22, list(3, 3), 34)); + }); + + createTable("CREATE TABLE %s (a int, b int, c frozen<map<text, text>>, d int, PRIMARY KEY (a, b, c))"); + + execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", 11, 12, map("1", "3"), 14); + execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", 21, 22, map("2", "3"), 24); + execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", 21, 22, map("3", "3"), 34); + + beforeAndAfterFlush(() -> { + assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c CONTAINS KEY '2' ALLOW FILTERING"), + row(21, 22, map("2", "3"), 24)); + assertInvalidMessage("Clustering column \"c\" cannot be restricted (preceding column \"b\" is restricted by a non-EQ relation)", + "SELECT * FROM %s WHERE b > 20 AND c CONTAINS KEY '2'"); + }); + } + + @Test + public void filteringWithOrderClause() throws Throwable + { + createTable("CREATE TABLE %s (a int, b int, c int, d list<int>, PRIMARY KEY (a, b, c))"); + + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 11, 12, 13, list(1,4)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 22, 23, list(2,4)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 25, 26, list(2,7)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 31, 32, 33, list(3,4)); + + beforeAndAfterFlush(() -> { + + assertRows(executeFilteringOnly("SELECT a, b, c, d FROM %s WHERE a = 21 AND c > 20 ORDER BY b DESC"), + row(21, 25, 26, list(2, 7)), + row(21, 22, 23, list(2, 4))); + + assertRows(executeFilteringOnly("SELECT a, b, c, d FROM %s WHERE a IN(21, 31) AND c > 20 ORDER BY b DESC"), + row(31, 32, 33, list(3, 4)), + row(21, 25, 26, list(2, 7)), + row(21, 22, 23, list(2, 4))); + }); + } + + + @Test + public void filteringOnStaticColumnTest() throws Throwable + { + createTable("CREATE TABLE %s (a int, b int, c int, d int, s int static, PRIMARY KEY (a, b))"); + + execute("INSERT INTO %s (a, b, c, d, s) VALUES (11, 12, 13, 14, 15)"); + execute("INSERT INTO %s (a, b, c, d, s) VALUES (21, 22, 23, 24, 25)"); + execute("INSERT INTO %s (a, b, c, d, s) VALUES (21, 26, 27, 28, 29)"); + execute("INSERT INTO %s (a, b, c, d, s) VALUES (31, 32, 33, 34, 35)"); + execute("INSERT INTO %s (a, b, c, d, s) VALUES (11, 42, 43, 44, 45)"); + + beforeAndAfterFlush(() -> { + + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE s = 29"), + row(21, 22, 23, 24, 29), + row(21, 26, 27, 28, 29)); + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE b > 22 AND s = 29"), + row(21, 26, 27, 28, 29)); + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE b > 10 and b < 26 AND s = 29"), + row(21, 22, 23, 24, 29)); + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE c > 10 and c < 27 AND s = 29"), + row(21, 22, 23, 24, 29)); + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE c > 10 and c < 43 AND s = 29"), + row(21, 22, 23, 24, 29), + row(21, 26, 27, 28, 29)); + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE c > 10 AND s > 15 AND s < 45"), + row(21, 22, 23, 24, 29), + row(21, 26, 27, 28, 29), + row(31, 32, 33, 34, 35)); + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE a = 21 AND s > 15 AND s < 45 ORDER BY b DESC"), + row(21, 26, 27, 28, 29), + row(21, 22, 23, 24, 29)); + assertRows(executeFilteringOnly("SELECT a, b, c, d, s FROM %s WHERE c > 13 and d < 44"), + row(21, 22, 23, 24, 29), + row(21, 26, 27, 28, 29), + row(31, 32, 33, 34, 35)); + }); + } + + @Test + public void containsFilteringOnNonClusteringColumn() throws Throwable { + createTable("CREATE TABLE %s (a int, b int, c int, d list<int>, PRIMARY KEY (a, b, c))"); + + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 11, 12, 13, list(1,4)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 22, 23, list(2,4)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 25, 26, list(2,7)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 31, 32, 33, list(3,4)); + + beforeAndAfterFlush(() -> { + + assertRows(executeFilteringOnly("SELECT a, b, c, d FROM %s WHERE b > 20 AND d CONTAINS 2"), + row(21, 22, 23, list(2, 4)), + row(21, 25, 26, list(2, 7))); + + assertRows(executeFilteringOnly("SELECT a, b, c, d FROM %s WHERE b > 20 AND d CONTAINS 2 AND d contains 4"), + row(21, 22, 23, list(2, 4))); + }); + } + + @Test + public void filteringOnCompactTable() throws Throwable + { + createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY (a, b, c)) WITH COMPACT STORAGE"); + + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 11, 12, 13, 14); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 22, 23, 24); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 25, 26, 27); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 31, 32, 33, 34); + + beforeAndAfterFlush(() -> { + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c > 13"), + row(21, 22, 23, 24), + row(21, 25, 26, 27), + row(31, 32, 33, 34)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c > 13 AND c < 33"), + row(21, 22, 23, 24), + row(21, 25, 26, 27)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c > 13 AND b < 32"), + row(21, 22, 23, 24), + row(21, 25, 26, 27)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE a = 21 AND c > 13 AND b < 32 ORDER BY b DESC"), + row(21, 25, 26, 27), + row(21, 22, 23, 24)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE a IN (21, 31) AND c > 13 ORDER BY b DESC"), + row(31, 32, 33, 34), + row(21, 25, 26, 27), + row(21, 22, 23, 24)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c > 13 AND d < 34"), + row(21, 22, 23, 24), + row(21, 25, 26, 27)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c > 13"), + row(21, 22, 23, 24), + row(21, 25, 26, 27), + row(31, 32, 33, 34)); + }); + + // with frozen in clustering key + createTable("CREATE TABLE %s (a int, b int, c frozen<list<int>>, d int, PRIMARY KEY (a, b, c)) WITH COMPACT STORAGE"); + + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 11, 12, list(1, 3), 14); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 22, list(2, 3), 24); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 25, list(2, 6), 27); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 31, 32, list(3, 3), 34); + + beforeAndAfterFlush(() -> { + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c CONTAINS 2"), + row(21, 22, list(2, 3), 24), + row(21, 25, list(2, 6), 27)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c CONTAINS 2 AND b < 25"), + row(21, 22, list(2, 3), 24)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE c CONTAINS 2 AND c CONTAINS 3"), + row(21, 22, list(2, 3), 24)); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE b > 12 AND c CONTAINS 2 AND d < 27"), + row(21, 22, list(2, 3), 24)); + }); + + // with frozen in value + createTable("CREATE TABLE %s (a int, b int, c int, d frozen<list<int>>, PRIMARY KEY (a, b, c)) WITH COMPACT STORAGE"); + + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 11, 12, 13, list(1, 4)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 22, 23, list(2, 4)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 21, 25, 25, list(2, 6)); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 31, 32, 34, list(3, 4)); + + beforeAndAfterFlush(() -> { + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE d CONTAINS 2"), + row(21, 22, 23, list(2, 4)), + row(21, 25, 25, list(2, 6))); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE d CONTAINS 2 AND b < 25"), + row(21, 22, 23, list(2, 4))); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE d CONTAINS 2 AND d CONTAINS 4"), + row(21, 22, 23, list(2, 4))); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE b > 12 AND c < 25 AND d CONTAINS 2"), + row(21, 22, 23, list(2, 4))); + }); + } + + @Test - public void testCustomIndexWithFiltering() throws Throwable { ++ public void testCustomIndexWithFiltering() throws Throwable ++ { + // Test for CASSANDRA-11310 compatibility with 2i + createTable("CREATE TABLE %s (a text, b int, c text, d int, PRIMARY KEY (a, b, c));"); + createIndex("CREATE INDEX ON %s(c)"); + + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", "a", 0, "b", 1); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", "a", 1, "b", 2); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", "a", 2, "b", 3); + execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", "c", 3, "b", 4); + + assertRows(executeFilteringOnly("SELECT * FROM %s WHERE a='a' AND b > 0 AND c = 'b'"), + row("a", 1, "b", 2), + row("a", 2, "b", 3)); + } + ++ @Test ++ public void testFilteringWithCounters() throws Throwable ++ { ++ for (String compactStorageClause: new String[] {"", " WITH COMPACT STORAGE"}) ++ { ++ createTable("CREATE TABLE %s (a int, b int, c int, cnt counter, PRIMARY KEY (a, b, c))" + compactStorageClause); ++ ++ execute("UPDATE %s SET cnt = cnt + ? WHERE a = ? AND b = ? AND c = ?", 14L, 11, 12, 13); ++ execute("UPDATE %s SET cnt = cnt + ? WHERE a = ? AND b = ? AND c = ?", 24L, 21, 22, 23); ++ execute("UPDATE %s SET cnt = cnt + ? WHERE a = ? AND b = ? AND c = ?", 27L, 21, 25, 26); ++ execute("UPDATE %s SET cnt = cnt + ? WHERE a = ? AND b = ? AND c = ?", 34L, 31, 32, 33); ++ execute("UPDATE %s SET cnt = cnt + ? WHERE a = ? AND b = ? AND c = ?", 24L, 41, 42, 43); ++ ++ beforeAndAfterFlush(() -> { ++ ++ assertRows(executeFilteringOnly("SELECT * FROM %s WHERE cnt = 24"), ++ row(21, 22, 23, 24L), ++ row(41, 42, 43, 24L)); ++ assertRows(executeFilteringOnly("SELECT * FROM %s WHERE b > 22 AND cnt = 24"), ++ row(41, 42, 43, 24L)); ++ assertRows(executeFilteringOnly("SELECT * FROM %s WHERE b > 10 AND b < 25 AND cnt = 24"), ++ row(21, 22, 23, 24L)); ++ assertRows(executeFilteringOnly("SELECT * FROM %s WHERE b > 10 AND c < 25 AND cnt = 24"), ++ row(21, 22, 23, 24L)); ++ assertRows(executeFilteringOnly("SELECT * FROM %s WHERE a = 21 AND b > 10 AND cnt > 23 ORDER BY b DESC"), ++ row(21, 25, 26, 27L), ++ row(21, 22, 23, 24L)); ++ assertRows(executeFilteringOnly("SELECT * FROM %s WHERE cnt > 20 AND cnt < 30"), ++ row(21, 22, 23, 24L), ++ row(21, 25, 26, 27L), ++ row(41, 42, 43, 24L)); ++ }); ++ } ++ } ++ + private UntypedResultSet executeFilteringOnly(String statement) throws Throwable + { + assertInvalid(statement); + return execute(statement + " ALLOW FILTERING"); + } + /** * Check select with and without compact storage, with different column * order. See CASSANDRA-10988
