You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sa...@apache.org on 2016/05/02 12:15:00 UTC
[1/3] cassandra git commit: Add support for filtering on counter
columns
Repository: cassandra
Updated Branches:
refs/heads/cassandra-3.0 620efdc8c -> c08eeafdc
refs/heads/trunk a529e6ae6 -> 1800a5b62
Add support for filtering on counter columns
Patch by Alex Petrov; reviewed by Sam Tunnicliffe for CASSANDRA-11629
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c08eeafd
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c08eeafd
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c08eeafd
Branch: refs/heads/cassandra-3.0
Commit: c08eeafdcfe4b5d0fb1a8aa34ca5df27be7934ce
Parents: 620efdc
Author: Alex Petrov <ol...@gmail.com>
Authored: Tue Apr 26 18:10:38 2016 +0200
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Mon May 2 11:07:39 2016 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../apache/cassandra/db/filter/RowFilter.java | 22 ++++++
.../cql3/validation/entities/CountersTest.java | 74 ++++++++++++++++++++
3 files changed, 97 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/c08eeafd/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 64bcbd8..95f450b 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
3.0.6
+ * 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/c08eeafd/src/java/org/apache/cassandra/db/filter/RowFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/RowFilter.java b/src/java/org/apache/cassandra/db/filter/RowFilter.java
index 4960452..8060f23 100644
--- a/src/java/org/apache/cassandra/db/filter/RowFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/RowFilter.java
@@ -27,6 +27,7 @@ import org.apache.cassandra.config.CFMetaData;
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.rows.*;
@@ -611,6 +612,27 @@ public abstract class RowFilter implements Iterable<RowFilter.Expression>
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:
{
assert !column.isComplex() : "Only CONTAINS and CONTAINS_KEY are supported for 'complex' types";
http://git-wip-us.apache.org/repos/asf/cassandra/blob/c08eeafd/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java
index e54d105..89fd767 100644
--- 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 @@ public class CountersTest extends CQLTester
row(1L) // no change to the counter value
);
}
+
+ @Test
+ public void testCounterFiltering() throws Throwable
+ {
+ 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");
+ }
+ }
}
[3/3] cassandra git commit: Merge branch 'cassandra-3.0' into trunk
Posted by sa...@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/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 <sa...@beobal.com>
Authored: Mon May 2 11:12:01 2016 +0100
Committer: Sam Tunnicliffe <sa...@beobal.com>
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
[2/3] cassandra git commit: Add support for filtering on counter
columns
Posted by sa...@apache.org.
Add support for filtering on counter columns
Patch by Alex Petrov; reviewed by Sam Tunnicliffe for CASSANDRA-11629
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c08eeafd
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c08eeafd
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c08eeafd
Branch: refs/heads/trunk
Commit: c08eeafdcfe4b5d0fb1a8aa34ca5df27be7934ce
Parents: 620efdc
Author: Alex Petrov <ol...@gmail.com>
Authored: Tue Apr 26 18:10:38 2016 +0200
Committer: Sam Tunnicliffe <sa...@beobal.com>
Committed: Mon May 2 11:07:39 2016 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../apache/cassandra/db/filter/RowFilter.java | 22 ++++++
.../cql3/validation/entities/CountersTest.java | 74 ++++++++++++++++++++
3 files changed, 97 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/c08eeafd/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 64bcbd8..95f450b 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
3.0.6
+ * 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/c08eeafd/src/java/org/apache/cassandra/db/filter/RowFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/RowFilter.java b/src/java/org/apache/cassandra/db/filter/RowFilter.java
index 4960452..8060f23 100644
--- a/src/java/org/apache/cassandra/db/filter/RowFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/RowFilter.java
@@ -27,6 +27,7 @@ import org.apache.cassandra.config.CFMetaData;
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.rows.*;
@@ -611,6 +612,27 @@ public abstract class RowFilter implements Iterable<RowFilter.Expression>
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:
{
assert !column.isComplex() : "Only CONTAINS and CONTAINS_KEY are supported for 'complex' types";
http://git-wip-us.apache.org/repos/asf/cassandra/blob/c08eeafd/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java
index e54d105..89fd767 100644
--- 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 @@ public class CountersTest extends CQLTester
row(1L) // no change to the counter value
);
}
+
+ @Test
+ public void testCounterFiltering() throws Throwable
+ {
+ 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");
+ }
+ }
}