Repository: cassandra Updated Branches: refs/heads/trunk 30bfa07a4 -> c83729f41
Make sure that indexing/filtering restrictions are picked up correctly even if the columns are given in order Patch by Alex Petrov; reviewed by Sam Tunnicliffe and Benjamin Lerer for CASSANDRA-11310 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c83729f4 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c83729f4 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c83729f4 Branch: refs/heads/trunk Commit: c83729f41d358ce3ca2ac0323704ef516dff9298 Parents: 30bfa07 Author: Alex Petrov <[email protected]> Authored: Tue Apr 19 10:43:12 2016 +0200 Committer: Sam Tunnicliffe <[email protected]> Committed: Tue Apr 19 18:05:29 2016 +0100 ---------------------------------------------------------------------- .../restrictions/StatementRestrictions.java | 39 +++++++------- .../entities/FrozenCollectionsTest.java | 2 +- .../cql3/validation/operations/SelectTest.java | 56 ++++++++++++++++++++ 3 files changed, 77 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/c83729f4/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java index b146cfd..c4d7622 100644 --- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java +++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java @@ -42,7 +42,6 @@ import org.apache.cassandra.utils.btree.BTreeSet; import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse; import static org.apache.cassandra.cql3.statements.RequestValidations.checkNotNull; -import static org.apache.cassandra.cql3.statements.RequestValidations.checkTrue; import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest; /** @@ -471,35 +470,37 @@ public final class StatementRestrictions checkFalse(clusteringColumnsRestrictions.hasIN() && selectsComplexColumn, "Cannot restrict clustering columns by IN relations when a collection is selected by the query"); checkFalse(clusteringColumnsRestrictions.hasContains() && !hasQueriableIndex && !allowFiltering, - "Cannot restrict clustering columns by a CONTAINS relation without a secondary index"); + "Clustering columns can only be restricted with CONTAINS with a secondary index or filtering"); - if (hasClusteringColumnsRestriction()) + if (hasClusteringColumnsRestriction() && clusteringColumnsRestrictions.needFiltering()) { - List<ColumnDefinition> clusteringColumns = cfm.clusteringColumns(); - List<ColumnDefinition> restrictedColumns = new LinkedList<>(clusteringColumnsRestrictions.getColumnDefs()); - - for (int i = 0, m = restrictedColumns.size(); i < m; i++) + if (hasQueriableIndex || forView) + { + usesSecondaryIndexing = true; + } + else { - ColumnDefinition clusteringColumn = clusteringColumns.get(i); - ColumnDefinition restrictedColumn = restrictedColumns.get(i); + List<ColumnDefinition> clusteringColumns = cfm.clusteringColumns(); + List<ColumnDefinition> restrictedColumns = new LinkedList<>(clusteringColumnsRestrictions.getColumnDefs()); - if (!clusteringColumn.equals(restrictedColumn) && !allowFiltering) + for (int i = 0, m = restrictedColumns.size(); i < m; i++) { - checkTrue(hasQueriableIndex || forView, - "PRIMARY KEY column \"%s\" cannot be restricted as preceding column \"%s\" is not restricted", - restrictedColumn.name, - clusteringColumn.name); - - usesSecondaryIndexing = true; // handle gaps and non-keyrange cases. - break; + ColumnDefinition clusteringColumn = clusteringColumns.get(i); + ColumnDefinition restrictedColumn = restrictedColumns.get(i); + + if (!clusteringColumn.equals(restrictedColumn) && !allowFiltering) + { + throw invalidRequest("PRIMARY KEY column \"%s\" cannot be restricted as preceding column \"%s\" is not restricted", + restrictedColumn.name, + clusteringColumn.name); + } } } } + } - if (clusteringColumnsRestrictions.hasContains()) - usesSecondaryIndexing = true; } /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/c83729f4/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java index 4aa178a..4c7c135 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java @@ -630,7 +630,7 @@ public class FrozenCollectionsTest extends CQLTester "SELECT * FROM %s WHERE c CONTAINS KEY ?", 1); // normal indexes on frozen collections don't support CONTAINS or CONTAINS KEY - assertInvalidMessage("Cannot restrict clustering columns by a CONTAINS relation without a secondary index", + assertInvalidMessage("Clustering columns can only be restricted with CONTAINS with a secondary index or filtering", "SELECT * FROM %s WHERE b CONTAINS ?", 1); assertRows(execute("SELECT * FROM %s WHERE b CONTAINS ? ALLOW FILTERING", 1), http://git-wip-us.apache.org/repos/asf/cassandra/blob/c83729f4/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java index 6789baf..49e6c4b 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java @@ -2449,6 +2449,15 @@ public class SelectTest extends CQLTester 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)", @@ -2541,6 +2550,32 @@ public class SelectTest extends CQLTester //------------------------------------------------- // 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); @@ -2549,6 +2584,11 @@ public class SelectTest extends CQLTester 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)", @@ -2750,6 +2790,22 @@ public class SelectTest extends CQLTester }); } + @Test + 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)); + } + private UntypedResultSet executeFilteringOnly(String statement) throws Throwable { assertInvalid(statement);
