You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2016/09/12 09:24:46 UTC
[3/3] cassandra git commit: Allow filtering on partition key columns
for queries without secondary indexes
Allow filtering on partition key columns for queries without secondary indexes
patch by ZhaoYang and Alex Petrov; reviewed by Benjamin Lerer for CASSANDRA-11031
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3f49c328
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3f49c328
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3f49c328
Branch: refs/heads/trunk
Commit: 3f49c328f202e68b67a9caaa63522e333ea5006f
Parents: 64f12ab
Author: ZhaoYang <zh...@gmail.com>
Authored: Mon Sep 12 11:22:25 2016 +0200
Committer: Benjamin Lerer <b....@gmail.com>
Committed: Mon Sep 12 11:24:38 2016 +0200
----------------------------------------------------------------------
CHANGES.txt | 1 +
NEWS.txt | 2 +
.../cassandra/cql3/SingleColumnRelation.java | 11 -
.../restrictions/PartitionKeyRestrictions.java | 17 +
.../PartitionKeySingleRestrictionSet.java | 26 +
.../cql3/restrictions/RestrictionSet.java | 10 +
.../restrictions/RestrictionSetWrapper.java | 5 +
.../cql3/restrictions/Restrictions.java | 6 +
.../restrictions/StatementRestrictions.java | 65 +-
.../cql3/restrictions/TokenFilter.java | 23 +-
.../cql3/restrictions/TokenRestriction.java | 25 +-
.../apache/cassandra/db/filter/RowFilter.java | 30 +-
.../cassandra/cql3/ViewFilteringTest.java | 211 ++-
.../org/apache/cassandra/cql3/ViewTest.java | 13 +
.../validation/entities/SecondaryIndexTest.java | 95 ++
.../SelectMultiColumnRelationTest.java | 13 +-
.../SelectOrderedPartitionerTest.java | 34 +-
.../SelectSingleColumnRelationTest.java | 28 +-
.../cql3/validation/operations/SelectTest.java | 1495 +++++++++++++++---
.../index/internal/CassandraIndexTest.java | 4 +-
20 files changed, 1832 insertions(+), 282 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 3ab144e..312713f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
3.10
+ * Allow filtering on partition key columns for queries without secondary indexes (CASSANDRA-11031)
* Fix Cassandra Stress reporting thread model and precision (CASSANDRA-12585)
* Add JMH benchmarks.jar (CASSANDRA-12586)
* Add row offset support to SASI (CASSANDRA-11990)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/NEWS.txt
----------------------------------------------------------------------
diff --git a/NEWS.txt b/NEWS.txt
index ddb1263..1b15f7d 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -18,6 +18,8 @@ using the provided 'sstableupgrade' tool.
New features
------------
+ - Filtering on partition key columns is now also supported for queries without
+ secondary indexes.
- A slow query log has been added: slow queries will be logged at DEBUG level.
For more details refer to CASSANDRA-12403 and slow_query_log_timeout_in_ms
in cassandra.yaml.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java b/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java
index 22df6bd..4dbb7da 100644
--- a/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java
+++ b/src/java/org/apache/cassandra/cql3/SingleColumnRelation.java
@@ -252,17 +252,6 @@ public final class SingleColumnRelation extends Relation
checkFalse(!columnDef.isPrimaryKeyColumn() && !canHaveOnlyOneValue(),
"IN predicates on non-primary-key columns (%s) is not yet supported", columnDef.name);
}
- else if (isSlice())
- {
- // Non EQ relation is not supported without token(), even if we have a 2ndary index (since even those
- // are ordered by partitioner).
- // Note: In theory we could allow it for 2ndary index queries with ALLOW FILTERING, but that would
- // probably require some special casing
- // Note bis: This is also why we don't bother handling the 'tuple' notation of #4851 for keys. If we
- // lift the limitation for 2ndary
- // index with filtering, we'll need to handle it though.
- checkFalse(columnDef.isPartitionKey(), "Only EQ and IN relation are supported on the partition key (unless you use the token() function)");
- }
checkFalse(isContainsKey() && !(receiver.type instanceof MapType), "Cannot use CONTAINS KEY on non-map column %s", receiver.name);
checkFalse(isContains() && !(receiver.type.isCollection()), "Cannot use CONTAINS on non-collection column %s", receiver.name);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
index 10efa9f..1ff45d0 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
@@ -20,6 +20,7 @@ package org.apache.cassandra.cql3.restrictions;
import java.nio.ByteBuffer;
import java.util.List;
+import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.QueryOptions;
import org.apache.cassandra.cql3.statements.Bound;
@@ -48,4 +49,20 @@ interface PartitionKeyRestrictions extends Restrictions
* @return <code>true</code> if the specified bound is inclusive, <code>false</code> otherwise
*/
public boolean isInclusive(Bound b);
+
+ /**
+ * checks if specified restrictions require filtering
+ *
+ * @param cfm column family metadata
+ * @return <code>true</code> if filtering is required, <code>false</code> otherwise
+ */
+ public boolean needFiltering(CFMetaData cfm);
+
+ /**
+ * Checks if the partition key has unrestricted components.
+ *
+ * @param cfm column family metadata
+ * @return <code>true</code> if the partition key has unrestricted components, <code>false</code> otherwise.
+ */
+ public boolean hasUnrestrictedPartitionKeyComponents(CFMetaData cfm);
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeySingleRestrictionSet.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeySingleRestrictionSet.java b/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeySingleRestrictionSet.java
index b96f6da..b34ff54 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeySingleRestrictionSet.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeySingleRestrictionSet.java
@@ -129,4 +129,30 @@ final class PartitionKeySingleRestrictionSet extends RestrictionSetWrapper imple
restriction.addRowFilterTo(filter, indexManager, options);
}
}
+
+ @Override
+ public boolean needFiltering(CFMetaData cfm)
+ {
+ if (isEmpty())
+ return false;
+ // slice or has unrestricted key component
+ return hasUnrestrictedPartitionKeyComponents(cfm) || hasSlice();
+ }
+
+ @Override
+ public boolean hasUnrestrictedPartitionKeyComponents(CFMetaData cfm)
+ {
+ return size() < cfm.partitionKeyColumns().size();
+ }
+
+ @Override
+ public boolean hasSlice()
+ {
+ for (SingleRestriction restriction : restrictions)
+ {
+ if (restriction.isSlice())
+ return true;
+ }
+ return false;
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java b/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
index 0e6c2f7..0876f3e 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSet.java
@@ -266,6 +266,16 @@ final class RestrictionSet implements Restrictions, Iterable<SingleRestriction>
return false;
}
+ public final boolean hasSlice()
+ {
+ for (SingleRestriction restriction : this)
+ {
+ if (restriction.isSlice())
+ return true;
+ }
+ return false;
+ }
+
/**
* Checks if all of the underlying restrictions are EQ or IN restrictions.
*
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSetWrapper.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSetWrapper.java b/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSetWrapper.java
index 6b110da..996a1c4 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSetWrapper.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/RestrictionSetWrapper.java
@@ -89,6 +89,11 @@ class RestrictionSetWrapper implements Restrictions
return restrictions.hasIN();
}
+ public boolean hasSlice()
+ {
+ return restrictions.hasSlice();
+ }
+
public boolean hasOnlyEqualityRestrictions()
{
return restrictions.hasOnlyEqualityRestrictions();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
index 4cf165f..8a5140a 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/Restrictions.java
@@ -55,6 +55,12 @@ public interface Restrictions extends Restriction
public boolean hasIN();
/**
+ * Checks if any of the underlying restrictions is a slice.
+ * @return <code>true</code> if any of the underlying restrictions is a slice, <code>false</code> otherwise
+ */
+ public boolean hasSlice();
+
+ /**
* Checks if all of the underlying restrictions are EQ or IN restrictions.
*
* @return <code>true</code> if all of the underlying restrictions are EQ or IN restrictions,
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/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 0b3b37d..53ac68c 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@ -190,11 +190,11 @@ public final class StatementRestrictions
}
// At this point, the select statement if fully constructed, but we still have a few things to validate
- processPartitionKeyRestrictions(hasQueriableIndex);
+ processPartitionKeyRestrictions(hasQueriableIndex, allowFiltering, forView);
// Some but not all of the partition key columns have been specified;
// hence we need turn these restrictions into a row filter.
- if (usesSecondaryIndexing)
+ if (usesSecondaryIndexing || partitionKeyRestrictions.needFiltering(cfm))
filterRestrictions.add(partitionKeyRestrictions);
if (selectsOnlyStaticColumns && hasClusteringColumnsRestriction())
@@ -385,36 +385,48 @@ public final class StatementRestrictions
return this.usesSecondaryIndexing;
}
- private void processPartitionKeyRestrictions(boolean hasQueriableIndex)
+ private void processPartitionKeyRestrictions(boolean hasQueriableIndex, boolean allowFiltering, boolean forView)
{
if (!type.allowPartitionKeyRanges())
{
checkFalse(partitionKeyRestrictions.isOnToken(),
"The token function cannot be used in WHERE clauses for %s statements", type);
- if (hasUnrestrictedPartitionKeyComponents())
+ if (partitionKeyRestrictions.hasUnrestrictedPartitionKeyComponents(cfm))
throw invalidRequest("Some partition key parts are missing: %s",
Joiner.on(", ").join(getPartitionKeyUnrestrictedComponents()));
+
+ // slice query
+ checkFalse(partitionKeyRestrictions.hasSlice(),
+ "Only EQ and IN relation are supported on the partition key (unless you use the token() function)"
+ + " for %s statements", type);
}
else
{
- // If there is a queriable index, no special condition are required on the other restrictions.
- // But we still need to know 2 things:
- // - If we don't have a queriable index, is the query ok
- // - Is it queriable without 2ndary index, which is always more efficient
- // If a component of the partition key is restricted by a relation, all preceding
- // components must have a EQ. Only the last partition key component can be in IN relation.
- if (partitionKeyRestrictions.isOnToken())
- isKeyRange = true;
+ // If there are no partition restrictions or there's only token restriction, we have to set a key range
+ if (partitionKeyRestrictions.isOnToken())
+ isKeyRange = true;
- if (hasUnrestrictedPartitionKeyComponents())
+ if (partitionKeyRestrictions.isEmpty() && partitionKeyRestrictions.hasUnrestrictedPartitionKeyComponents(cfm))
{
- if (!partitionKeyRestrictions.isEmpty())
- {
- if (!hasQueriableIndex)
- throw invalidRequest("Partition key parts: %s must be restricted as other parts are",
- Joiner.on(", ").join(getPartitionKeyUnrestrictedComponents()));
- }
+ isKeyRange = true;
+ usesSecondaryIndexing = hasQueriableIndex;
+ }
+
+ // If there is a queriable index, no special condition is required on the other restrictions.
+ // But we still need to know 2 things:
+ // - If we don't have a queriable index, is the query ok
+ // - Is it queriable without 2ndary index, which is always more efficient
+ // If a component of the partition key is restricted by a relation, all preceding
+ // components must have a EQ. Only the last partition key component can be in IN relation.
+ if (partitionKeyRestrictions.needFiltering(cfm))
+ {
+ if (!allowFiltering && !forView && !hasQueriableIndex
+ && (partitionKeyRestrictions.hasUnrestrictedPartitionKeyComponents(cfm) || partitionKeyRestrictions.hasSlice()))
+ throw new InvalidRequestException(REQUIRES_ALLOW_FILTERING_MESSAGE);
+
+ if (partitionKeyRestrictions.hasIN())
+ throw new InvalidRequestException("IN restrictions are not supported when the query involves filtering");
isKeyRange = true;
usesSecondaryIndexing = hasQueriableIndex;
@@ -422,15 +434,6 @@ public final class StatementRestrictions
}
}
- /**
- * Checks if the partition key has some unrestricted components.
- * @return <code>true</code> if the partition key has some unrestricted components, <code>false</code> otherwise.
- */
- private boolean hasUnrestrictedPartitionKeyComponents()
- {
- return partitionKeyRestrictions.size() < cfm.partitionKeyColumns().size();
- }
-
public boolean hasPartitionKeyRestrictions()
{
return !partitionKeyRestrictions.isEmpty();
@@ -622,8 +625,8 @@ public final class StatementRestrictions
private ByteBuffer getPartitionKeyBound(Bound b, QueryOptions options)
{
// Deal with unrestricted partition key components (special-casing is required to deal with 2i queries on the
- // first component of a composite partition key).
- if (hasUnrestrictedPartitionKeyComponents())
+ // first component of a composite partition key) queries that filter on the partition key.
+ if (partitionKeyRestrictions.needFiltering(cfm))
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
// We deal with IN queries for keys in other places, so we know buildBound will return only one result
@@ -804,7 +807,7 @@ public final class StatementRestrictions
public boolean hasAllPKColumnsRestrictedByEqualities()
{
return !isPartitionKeyRestrictionsOnToken()
- && !hasUnrestrictedPartitionKeyComponents()
+ && !partitionKeyRestrictions.hasUnrestrictedPartitionKeyComponents(cfm)
&& (partitionKeyRestrictions.hasOnlyEqualityRestrictions())
&& !hasUnrestrictedClusteringColumns()
&& (clusteringColumnsRestrictions.hasOnlyEqualityRestrictions());
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/restrictions/TokenFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/TokenFilter.java b/src/java/org/apache/cassandra/cql3/restrictions/TokenFilter.java
index c27d742..2611d19 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/TokenFilter.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/TokenFilter.java
@@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableRangeSet;
import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
+import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.QueryOptions;
import org.apache.cassandra.cql3.functions.Function;
@@ -135,8 +136,8 @@ final class TokenFilter implements PartitionKeyRestrictions
*/
private List<ByteBuffer> filter(List<ByteBuffer> values, QueryOptions options) throws InvalidRequestException
{
- RangeSet<Token> rangeSet = tokenRestriction.isSlice() ? toRangeSet(tokenRestriction, options)
- : toRangeSet(tokenRestriction.values(options));
+ RangeSet<Token> rangeSet = tokenRestriction.hasSlice() ? toRangeSet(tokenRestriction, options)
+ : toRangeSet(tokenRestriction.values(options));
return filterWithRangeSet(rangeSet, values);
}
@@ -285,4 +286,22 @@ final class TokenFilter implements PartitionKeyRestrictions
{
return restrictions.size();
}
+
+ @Override
+ public boolean needFiltering(CFMetaData cfm)
+ {
+ return restrictions.needFiltering(cfm);
+ }
+
+ @Override
+ public boolean hasUnrestrictedPartitionKeyComponents(CFMetaData cfm)
+ {
+ return restrictions.hasUnrestrictedPartitionKeyComponents(cfm);
+ }
+
+ @Override
+ public boolean hasSlice()
+ {
+ return restrictions.hasSlice();
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java b/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
index dd31730..e90319d 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/TokenRestriction.java
@@ -57,11 +57,6 @@ public abstract class TokenRestriction implements PartitionKeyRestrictions
this.metadata = metadata;
}
- public boolean isSlice()
- {
- return false;
- }
-
public boolean hasIN()
{
return false;
@@ -85,6 +80,24 @@ public abstract class TokenRestriction implements PartitionKeyRestrictions
}
@Override
+ public boolean needFiltering(CFMetaData cfm)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean hasSlice()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean hasUnrestrictedPartitionKeyComponents(CFMetaData cfm)
+ {
+ return false;
+ }
+
+ @Override
public List<ColumnDefinition> getColumnDefs()
{
return columnDefs;
@@ -225,7 +238,7 @@ public abstract class TokenRestriction implements PartitionKeyRestrictions
}
@Override
- public boolean isSlice()
+ public boolean hasSlice()
{
return true;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/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 6626275..4c0608f 100644
--- a/src/java/org/apache/cassandra/db/filter/RowFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/RowFilter.java
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.base.Objects;
+import com.google.common.collect.Iterables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -274,9 +275,19 @@ public abstract class RowFilter implements Iterable<RowFilter.Expression>
return iter;
final CFMetaData metadata = iter.metadata();
- long numberOfStaticColumnExpressions = expressions.stream().filter(e -> e.column.isStatic()).count();
- final boolean filterStaticColumns = numberOfStaticColumnExpressions != 0;
- final boolean filterNonStaticColumns = (expressions.size() - numberOfStaticColumnExpressions) > 0;
+
+ List<Expression> partitionLevelExpressions = new ArrayList<>();
+ List<Expression> rowLevelExpressions = new ArrayList<>();
+ for (Expression e: expressions)
+ {
+ if (e.column.isStatic() || e.column.isPartitionKey())
+ partitionLevelExpressions.add(e);
+ else
+ rowLevelExpressions.add(e);
+ }
+
+ long numberOfRegularColumnExpressions = rowLevelExpressions.size();
+ final boolean filterNonStaticColumns = numberOfRegularColumnExpressions > 0;
class IsSatisfiedFilter extends Transformation<UnfilteredRowIterator>
{
@@ -285,9 +296,10 @@ public abstract class RowFilter implements Iterable<RowFilter.Expression>
{
pk = partition.partitionKey();
- // The filter might be on static columns, so need to check static row first.
- if (filterStaticColumns && applyToRow(partition.staticRow()) == null)
- return null;
+ // Short-circuit all partitions that won't match based on static and partition keys
+ for (Expression e : partitionLevelExpressions)
+ if (!e.isSatisfiedBy(metadata, partition.partitionKey(), partition.staticRow()))
+ return null;
UnfilteredRowIterator iterator = Transformation.apply(partition, this);
return (filterNonStaticColumns && !iterator.hasNext()) ? null : iterator;
@@ -299,9 +311,10 @@ public abstract class RowFilter implements Iterable<RowFilter.Expression>
if (purged == null)
return null;
- for (Expression e : expressions)
+ for (Expression e : rowLevelExpressions)
if (!e.isSatisfiedBy(metadata, pk, purged))
return null;
+
return row;
}
}
@@ -669,9 +682,6 @@ public abstract class RowFilter implements Iterable<RowFilter.Expression>
// TODO: we should try to merge both code someday.
assert value != null;
- if (row.isStatic() != column.isStatic())
- return true;
-
switch (operator)
{
case EQ:
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/test/unit/org/apache/cassandra/cql3/ViewFilteringTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/ViewFilteringTest.java b/test/unit/org/apache/cassandra/cql3/ViewFilteringTest.java
index 12cb673..0cecfa2 100644
--- a/test/unit/org/apache/cassandra/cql3/ViewFilteringTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ViewFilteringTest.java
@@ -148,13 +148,6 @@ public class ViewFilteringTest extends CQLTester
throw new RuntimeException("MV alter failed: " + goodStatements.get(i), e);
}
}
-
- try
- {
- createView("mv_foo", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a = 1 AND b IS NOT NULL AND c IS NOT NULL AND d is NOT NULL PRIMARY KEY ((a, b), c, d)");
- Assert.fail("Partial partition key restriction should not be allowed");
- }
- catch (InvalidQueryException exc) {}
}
@Test
@@ -266,6 +259,210 @@ public class ViewFilteringTest extends CQLTester
}
@Test
+ public void testPartitionKeyFilteringUnrestrictedPart() throws Throwable
+ {
+ List<String> mvPrimaryKeys = Arrays.asList("((a, b), c)", "((b, a), c)", "(a, b, c)", "(c, b, a)", "((c, a), b)");
+ for (int i = 0; i < mvPrimaryKeys.size(); i++)
+ {
+ createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY ((a, b), c))");
+
+ execute("USE " + keyspace());
+ executeNet(protocolVersion, "USE " + keyspace());
+
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 0, 0);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, 0, 0);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 0, 0, 0);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 0, 1, 0);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 1, 0, 0);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 1, 1, 0);
+
+ logger.info("Testing MV primary key: {}", mvPrimaryKeys.get(i));
+
+ // only accept rows where a = 1
+ String viewName= "mv_test" + i;
+ createView(viewName, "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a = 1 AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY " + mvPrimaryKeys.get(i));
+
+ waitForView(keyspace(), viewName);
+
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 0, 0, 0),
+ row(1, 0, 1, 0),
+ row(1, 1, 0, 0),
+ row(1, 1, 1, 0)
+ );
+
+ // insert new rows that do not match the filter
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 2, 0, 0, 0);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 2, 1, 0, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 0, 0, 0),
+ row(1, 0, 1, 0),
+ row(1, 1, 0, 0),
+ row(1, 1, 1, 0)
+ );
+
+ // insert new row that does match the filter
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 1, 2, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 0, 0, 0),
+ row(1, 0, 1, 0),
+ row(1, 1, 0, 0),
+ row(1, 1, 1, 0),
+ row(1, 1, 2, 0)
+ );
+
+ // update rows that don't match the filter
+ execute("UPDATE %s SET d = ? WHERE a = ? AND b = ? AND c = ?", 1, 0, 0, 0);
+ execute("UPDATE %s SET d = ? WHERE a = ? AND b = ? AND c = ?", 1, 0, 1, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 0, 0, 0),
+ row(1, 0, 1, 0),
+ row(1, 1, 0, 0),
+ row(1, 1, 1, 0),
+ row(1, 1, 2, 0)
+ );
+
+ // update a row that does match the filter
+ execute("UPDATE %s SET d = ? WHERE a = ? AND b = ? AND c = ?", 1, 1, 1, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 0, 0, 0),
+ row(1, 0, 1, 0),
+ row(1, 1, 0, 1),
+ row(1, 1, 1, 0),
+ row(1, 1, 2, 0)
+ );
+
+ // delete rows that don't match the filter
+ execute("DELETE FROM %s WHERE a = ? AND b = ? AND c = ?", 0, 0, 0);
+ execute("DELETE FROM %s WHERE a = ? AND b = ? AND c = ?", 0, 1, 0);
+ execute("DELETE FROM %s WHERE a = ? AND b = ?", 0, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 0, 0, 0),
+ row(1, 0, 1, 0),
+ row(1, 1, 0, 1),
+ row(1, 1, 1, 0),
+ row(1, 1, 2, 0)
+ );
+
+ // delete a row that does match the filter
+ execute("DELETE FROM %s WHERE a = ? AND b = ? AND c = ?", 1, 1, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 0, 0, 0),
+ row(1, 0, 1, 0),
+ row(1, 1, 1, 0),
+ row(1, 1, 2, 0)
+ );
+
+ // delete a partition that matches the filter
+ execute("DELETE FROM %s WHERE a = ? AND b = ?", 1, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 1, 1, 0),
+ row(1, 1, 2, 0));
+ execute("DELETE FROM %s WHERE a = ? AND b = ?", 1, 1);
+ assertEmpty(execute("SELECT * FROM mv_test" + i));
+ }
+ }
+
+ @Test
+ public void testPartitionKeyFilteringWithSlice() throws Throwable
+ {
+ List<String> mvPrimaryKeys = Arrays.asList("((a, b), c)", "((b, a), c)", "(a, b, c)", "(c, b, a)", "((c, a), b)");
+ for (int i = 0; i < mvPrimaryKeys.size(); i++)
+ {
+ createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY ((a, b), c))");
+
+ execute("USE " + keyspace());
+ executeNet(protocolVersion, "USE " + keyspace());
+
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 1, 1);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 10, 1, 2);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 0, 2, 1);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 10, 2, 2);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 2, 1, 3, 1);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 2, 10, 3, 2);
+
+ logger.info("Testing MV primary key: {}", mvPrimaryKeys.get(i));
+
+ // only accept rows where a = 1
+ String viewName= "mv_test" + i;
+ createView(viewName, "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a > 0 AND b > 5 AND c IS NOT NULL PRIMARY KEY " + mvPrimaryKeys.get(i));
+
+ waitForView(keyspace(), viewName);
+
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 10, 2, 2),
+ row(2, 10, 3, 2)
+ );
+
+ // insert new rows that do not match the filter
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 2, 0, 0, 0);
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 2, 1, 0, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 10, 2, 2),
+ row(2, 10, 3, 2)
+ );
+
+ // insert new row that does match the filter
+ execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 3, 10, 4, 2);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 10, 2, 2),
+ row(2, 10, 3, 2),
+ row(3, 10, 4, 2)
+ );
+
+ // update rows that don't match the filter
+ execute("UPDATE %s SET d = ? WHERE a = ? AND b = ? AND c = ?", 1, 0, 0, 0);
+ execute("UPDATE %s SET d = ? WHERE a = ? AND b = ? AND c = ?", 1, 0, 1, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 10, 2, 2),
+ row(2, 10, 3, 2),
+ row(3, 10, 4, 2)
+ );
+
+ // update a row that does match the filter
+ execute("UPDATE %s SET d = ? WHERE a = ? AND b = ? AND c = ?", 100, 3, 10, 4);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 10, 2, 2),
+ row(2, 10, 3, 2),
+ row(3, 10, 4, 100)
+ );
+
+ // delete rows that don't match the filter
+ execute("DELETE FROM %s WHERE a = ? AND b = ? AND c = ?", 0, 0, 0);
+ execute("DELETE FROM %s WHERE a = ? AND b = ? AND c = ?", 0, 1, 0);
+ execute("DELETE FROM %s WHERE a = ? AND b = ?", 0, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 10, 2, 2),
+ row(2, 10, 3, 2),
+ row(3, 10, 4, 100)
+ );
+
+ // delete a row that does match the filter
+ execute("DELETE FROM %s WHERE a = ? AND b = ? AND c = ?", 1, 1, 0);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(1, 10, 2, 2),
+ row(2, 10, 3, 2),
+ row(3, 10, 4, 100)
+ );
+
+ // delete a partition that matches the filter
+ execute("DELETE FROM %s WHERE a = ? AND b = ?", 1, 10);
+ assertRowsIgnoringOrder(execute("SELECT a, b, c, d FROM mv_test" + i),
+ row(2, 10, 3, 2),
+ row(3, 10, 4, 100));
+ }
+ }
+
+
+
+
+ private static void waitForView(String keyspace, String view) throws InterruptedException
+ {
+ while (!SystemKeyspace.isViewBuilt(keyspace, view))
+ Thread.sleep(10);
+ }
+
+ @Test
public void testPartitionKeyRestrictions() throws Throwable
{
List<String> mvPrimaryKeys = Arrays.asList("((a, b), c)", "((b, a), c)", "(a, b, c)", "(c, b, a)", "((c, a), b)");
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/test/unit/org/apache/cassandra/cql3/ViewTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/ViewTest.java b/test/unit/org/apache/cassandra/cql3/ViewTest.java
index c9ef401..0945511 100644
--- a/test/unit/org/apache/cassandra/cql3/ViewTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java
@@ -117,6 +117,19 @@ public class ViewTest extends CQLTester
Assert.assertEquals(0, execute("select * from view1").size());
}
+
+ @Test
+ public void createMvWithUnrestrictedPKParts() throws Throwable
+ {
+ createTable("CREATE TABLE %s (k1 int, c1 int , val int, PRIMARY KEY (k1, c1))");
+
+ execute("USE " + keyspace());
+ executeNet(protocolVersion, "USE " + keyspace());
+
+ createView("view1", "CREATE MATERIALIZED VIEW view1 AS SELECT k1 FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND val IS NOT NULL PRIMARY KEY (val, k1, c1)");
+
+ }
+
@Test
public void testClusteringKeyTombstone() throws Throwable
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
index 2072bf2..05c11a4 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
@@ -1177,6 +1177,101 @@ public class SecondaryIndexTest extends CQLTester
row(bytes("foo124"), EMPTY_BYTE_BUFFER));
}
+ @Test
+ public void testPartitionKeyWithIndex() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY ((a, b)))");
+ createIndex("CREATE INDEX ON %s (a);");
+ createIndex("CREATE INDEX ON %s (b);");
+
+ execute("INSERT INTO %s (a, b, c) VALUES (1,2,3)");
+ execute("INSERT INTO %s (a, b, c) VALUES (2,3,4)");
+ execute("INSERT INTO %s (a, b, c) VALUES (5,6,7)");
+
+ beforeAndAfterFlush(() -> {
+ assertRows(execute("SELECT * FROM %s WHERE a = 1"),
+ row(1, 2, 3));
+ assertRows(execute("SELECT * FROM %s WHERE b = 3"),
+ row(2, 3, 4));
+
+ });
+ }
+
+ @Test
+ public void testAllowFilteringOnPartitionKeyWithSecondaryIndex() throws Throwable
+ {
+ createTable("CREATE TABLE %s (pk1 int, pk2 int, c1 int, c2 int, v int, " +
+ "PRIMARY KEY ((pk1, pk2), c1, c2))");
+ createIndex("CREATE INDEX v_idx_1 ON %s (v);");
+
+ for (int i = 1; i <= 5; i++)
+ {
+ for (int j = 1; j <= 2; j++)
+ {
+ execute("INSERT INTO %s (pk1, pk2, c1, c2, v) VALUES (?, ?, ?, ?, ?)", j, 1, 1, 1, i);
+ execute("INSERT INTO %s (pk1, pk2, c1, c2, v) VALUES (?, ?, ?, ?, ?)", j, 1, 1, i, i);
+ execute("INSERT INTO %s (pk1, pk2, c1, c2, v) VALUES (?, ?, ?, ?, ?)", j, 1, i, i, i);
+ execute("INSERT INTO %s (pk1, pk2, c1, c2, v) VALUES (?, ?, ?, ?, ?)", j, i, i, i, i);
+ }
+ }
+
+ beforeAndAfterFlush(() -> {
+ assertEmpty(execute("SELECT * FROM %s WHERE pk1 = 1 AND c1 > 0 AND c1 < 5 AND c2 = 1 AND v = 3 ALLOW FILTERING;"));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk1 = 1 AND c1 > 0 AND c1 < 5 AND c2 = 3 AND v = 3 ALLOW FILTERING;"),
+ row(1, 3, 3, 3, 3),
+ row(1, 1, 1, 3, 3),
+ row(1, 1, 3, 3, 3));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE pk1 = 1 AND c2 > 1 AND c2 < 5 AND v = 1 ALLOW FILTERING;"));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk1 = 1 AND c1 > 1 AND c2 > 2 AND v = 3 ALLOW FILTERING;"),
+ row(1, 3, 3, 3, 3),
+ row(1, 1, 3, 3, 3));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk1 = 1 AND pk2 > 1 AND c2 > 2 AND v = 3 ALLOW FILTERING;"),
+ row(1, 3, 3, 3, 3));
+
+ assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk2 > 1 AND c1 IN(0,1,2) AND v <= 3 ALLOW FILTERING;"),
+ row(1, 2, 2, 2, 2),
+ row(2, 2, 2, 2, 2));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk1 >= 2 AND pk2 <=3 AND c1 IN(0,1,2) AND c2 IN(0,1,2) AND v < 3 ALLOW FILTERING;"),
+ row(2, 2, 2, 2, 2),
+ row(2, 1, 1, 2, 2),
+ row(2, 1, 2, 2, 2));
+
+ assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE pk1 >= 1 AND pk2 <=3 AND c1 IN(0,1,2) AND c2 IN(0,1,2) AND v = 3");
+ });
+ }
+
+ @Test
+ public void testAllowFilteringOnPartitionKeyWithIndexForContains() throws Throwable
+ {
+ createTable("CREATE TABLE %s (k1 int, k2 int, v set<int>, PRIMARY KEY ((k1, k2)))");
+ createIndex("CREATE INDEX ON %s(k2)");
+
+ execute("INSERT INTO %s (k1, k2, v) VALUES (?, ?, ?)", 0, 0, set(1, 2, 3));
+ execute("INSERT INTO %s (k1, k2, v) VALUES (?, ?, ?)", 0, 1, set(2, 3, 4));
+ execute("INSERT INTO %s (k1, k2, v) VALUES (?, ?, ?)", 1, 0, set(3, 4, 5));
+ execute("INSERT INTO %s (k1, k2, v) VALUES (?, ?, ?)", 1, 1, set(4, 5, 6));
+
+ beforeAndAfterFlush(() -> {
+ assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE k2 > ?", 0);
+
+ assertRows(execute("SELECT * FROM %s WHERE k2 > ? ALLOW FILTERING", 0),
+ row(0, 1, set(2, 3, 4)),
+ row(1, 1, set(4, 5, 6)));
+
+ assertRows(execute("SELECT * FROM %s WHERE k2 >= ? AND v CONTAINS ? ALLOW FILTERING", 1, 6),
+ row(1, 1, set(4, 5, 6)));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE k2 < ? AND v CONTAINS ? ALLOW FILTERING", 0, 7));
+ });
+ }
+
private ResultMessage.Prepared prepareStatement(String cql, boolean forThrift)
{
return QueryProcessor.prepare(String.format(cql, KEYSPACE, currentTable()),
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
index 19f798f..b91650d 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
@@ -958,11 +958,14 @@ public class SelectMultiColumnRelationTest extends CQLTester
row(0, 0, 1, 1, 0, 4),
row(0, 0, 1, 1, 1, 5));
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
- "SELECT * FROM %s WHERE a = ? AND (c, d) IN ((?, ?), (?, ?)) ALLOW FILTERING", 0, 1, 1, 2, 1);
-
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
- "SELECT * FROM %s WHERE a = ? AND (c, d) >= (?, ?) ALLOW FILTERING", 0, 1, 1);
+ assertRows(execute("SELECT * FROM %s WHERE a = ? AND (c, d) IN ((?, ?)) ALLOW FILTERING", 0, 1, 1),
+ row(0, 0, 1, 1, 0, 4),
+ row(0, 0, 1, 1, 1, 5));
+
+ assertRows(execute("SELECT * FROM %s WHERE a = ? AND (c, d) >= (?, ?) ALLOW FILTERING", 0, 1, 1),
+ row(0, 0, 1, 1, 0, 4),
+ row(0, 0, 1, 1, 1, 5),
+ row(0, 0, 2, 0, 0, 5));
assertRows(execute("SELECT * FROM %s WHERE a = ? AND b = ? AND (c) IN ((?)) AND f = ?", 0, 0, 1, 5),
row(0, 0, 1, 1, 1, 5));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/test/unit/org/apache/cassandra/cql3/validation/operations/SelectOrderedPartitionerTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectOrderedPartitionerTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectOrderedPartitionerTest.java
index 83e7e47..0e3a342 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectOrderedPartitionerTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectOrderedPartitionerTest.java
@@ -27,8 +27,11 @@ import org.junit.Test;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertEquals;
+
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.restrictions.StatementRestrictions;
import org.apache.cassandra.dht.ByteOrderedPartitioner;
/**
@@ -43,6 +46,33 @@ public class SelectOrderedPartitionerTest extends CQLTester
}
@Test
+ public void testFilteringOnPartitionKeyWithToken() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY ((a, b), c))");
+
+ for (int i = 0; i < 10; i++)
+ {
+ execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i, i, i);
+ execute("INSERT INTO %s (a,b,c,d) VALUES (?, ?, ?, ?)", i, i + 10, i + 10, i + 10);
+ }
+
+ beforeAndAfterFlush(() -> {
+ assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE token(a, b) > token(5, 10) AND b < 8 ALLOW FILTERING"),
+ row(6, 6, 6, 6),
+ row(7, 7, 7, 7));
+
+ assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(8, 10) AND a = 9 ALLOW FILTERING"),
+ row(9, 9, 9, 9),
+ row(9, 19, 19, 19));
+
+ assertRows(execute("SELECT * FROM %s WHERE token(a, b) > token(8, 10) AND a = 9 AND c = 19 ALLOW FILTERING"),
+ row(9, 19, 19, 19));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE token(a, b) = token(8, 8) AND b = 9 ALLOW FILTERING"));
+ });
+ }
+
+ @Test
public void testTokenFunctionWithSingleColumnPartitionKey() throws Throwable
{
createTable("CREATE TABLE IF NOT EXISTS %s (a int PRIMARY KEY, b text)");
@@ -130,7 +160,7 @@ public class SelectOrderedPartitionerTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE token(a) < token(?) AND token(a) >= token(?) AND a IN (?, ?);",
1, 3, 1, 3),
row(3, 3));
- assertInvalidMessage("Only EQ and IN relation are supported on the partition key (unless you use the token() function)",
+ assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE token(a) > token(?) AND token(a) <= token(?) AND a > ?;", 1, 3, 1);
assertRows(execute("SELECT * FROM %s WHERE token(a) > token(?) AND token(a) <= token(?) AND a IN ?;",
@@ -206,7 +236,7 @@ public class SelectOrderedPartitionerTest extends CQLTester
assertEmpty(execute("SELECT * FROM %s WHERE b IN (?, ?) AND token(a, b) = token(?, ?) AND a = ?;",
0, 1, 0, 0, 1));
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
+ assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE token(a, b) > token(?, ?) AND a = ?;", 0, 0, 1);
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3f49c328/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
index a52ce66..2ad0427 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
@@ -206,9 +206,9 @@ public class SelectSingleColumnRelationTest extends CQLTester
row("second", 1, 1, 1),
row("second", 4, 4, 4));
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
+ assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"select * from %s where a in (?, ?)", "first", "second");
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
+ assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"select * from %s where a = ?", "first");
assertInvalidMessage("b cannot be restricted by more than one relation if it includes a IN",
"select * from %s where a = ? AND b IN (?, ?) AND b = ?", "first", 2, 2, 3);
@@ -498,11 +498,14 @@ public class SelectSingleColumnRelationTest extends CQLTester
row(0, 0, 1, 1, 0, 4),
row(0, 0, 1, 1, 1, 5));
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
- "SELECT * FROM %s WHERE a = ? AND c IN (?, ?) AND d IN (?) ALLOW FILTERING", 0, 0, 1, 1);
+ assertRows(execute("SELECT * FROM %s WHERE a = ? AND c IN (?) AND d IN (?) ALLOW FILTERING", 0, 1, 1),
+ row(0, 0, 1, 1, 0, 4),
+ row(0, 0, 1, 1, 1, 5));
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
- "SELECT * FROM %s WHERE a = ? AND (c, d) >= (?, ?) ALLOW FILTERING", 0, 1, 1);
+ assertRows(execute("SELECT * FROM %s WHERE a = ? AND (c, d) >= (?, ?) ALLOW FILTERING", 0, 1, 1),
+ row(0, 0, 1, 1, 0, 4),
+ row(0, 0, 1, 1, 1, 5),
+ row(0, 0, 2, 0, 0, 5));
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE a = ? AND c IN (?, ?) AND f = ?", 0, 0, 1, 5);
@@ -520,8 +523,11 @@ public class SelectSingleColumnRelationTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE a = ? AND c IN (?, ?) AND d IN (?) AND f = ? ALLOW FILTERING", 0, 1, 3, 0, 3),
row(0, 0, 1, 0, 0, 3));
- assertInvalidMessage("Partition key parts: b must be restricted as other parts are",
- "SELECT * FROM %s WHERE a = ? AND c >= ? ALLOW FILTERING", 0, 1);
+ assertRows(execute("SELECT * FROM %s WHERE a = ? AND c >= ? ALLOW FILTERING", 0, 1),
+ row(0, 0, 1, 0, 0, 3),
+ row(0, 0, 1, 1, 0, 4),
+ row(0, 0, 1, 1, 1, 5),
+ row(0, 0, 2, 0, 0, 5));
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE a = ? AND c >= ? AND f = ?", 0, 1, 5);
@@ -592,7 +598,7 @@ public class SelectSingleColumnRelationTest extends CQLTester
public void testInvalidSliceRestrictionOnPartitionKey() throws Throwable
{
createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c text)");
- assertInvalidMessage("Only EQ and IN relation are supported on the partition key (unless you use the token() function)",
+ assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE a >= 1 and a < 4");
assertInvalidMessage("Multi-column relations can only be applied to clustering columns but was applied to: a",
"SELECT * FROM %s WHERE (a) >= (1) and (a) < (4)");
@@ -604,9 +610,9 @@ public class SelectSingleColumnRelationTest extends CQLTester
createTable("CREATE TABLE %s (a int, b int, c text, PRIMARY KEY ((a, b)))");
assertInvalidMessage("Multi-column relations can only be applied to clustering columns but was applied to: a",
"SELECT * FROM %s WHERE (a, b) >= (1, 1) and (a, b) < (4, 1)");
- assertInvalidMessage("Only EQ and IN relation are supported on the partition key (unless you use the token() function)",
+ assertInvalidMessage("Multi-column relations can only be applied to clustering columns but was applied to: a",
"SELECT * FROM %s WHERE a >= 1 and (a, b) < (4, 1)");
- assertInvalidMessage("Only EQ and IN relation are supported on the partition key (unless you use the token() function)",
+ assertInvalidMessage("Multi-column relations can only be applied to clustering columns but was applied to: a",
"SELECT * FROM %s WHERE b >= 1 and (a, b) < (4, 1)");
assertInvalidMessage("Multi-column relations can only be applied to clustering columns but was applied to: a",
"SELECT * FROM %s WHERE (a, b) >= (1, 1) and (b) < (4)");