This is an automated email from the ASF dual-hosted git repository.
edimitrova pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new e0074a31ef Add support for NOT operators in WHERE clauses
(CASSANDRA-18584) In addition - Fixed Three Valued Logic
e0074a31ef is described below
commit e0074a31ef26adaebff6ac0657e4471fc805f93f
Author: Benjamin Lerer <[email protected]>
AuthorDate: Thu Mar 21 11:11:10 2024 +0100
Add support for NOT operators in WHERE clauses (CASSANDRA-18584)
In addition - Fixed Three Valued Logic
patch by Piotr Kolaczkowski; reviewed by Benjamin Lerer, Ekaterina
Dimitrova, Andres de la Pena for CASSANDRA-18584
Co-authored-by: Benjamin Lerer <[email protected]>
Co-authored by: Ekaterina Dimitrova<[email protected]>
---
CHANGES.txt | 1 +
doc/cql3/CQL.textile | 14 +-
.../cassandra/examples/BNF/select_statement.bnf | 2 +-
.../cassandra/pages/developing/cql/changes.adoc | 1 +
.../pages/developing/cql/cql_singlefile.adoc | 2 +-
pylib/cqlshlib/cql3handling.py | 4 +-
pylib/cqlshlib/test/test_cqlsh_completion.py | 6 +-
src/antlr/Parser.g | 14 +-
src/java/org/apache/cassandra/cql3/Operator.java | 173 +++++-
src/java/org/apache/cassandra/cql3/Relation.java | 6 +-
.../cassandra/cql3/conditions/ColumnCondition.java | 2 +-
.../cql3/restrictions/ClusteringElements.java | 5 +
.../cql3/restrictions/MergedRestriction.java | 6 +-
.../restrictions/PartitionKeyRestrictions.java | 2 +-
.../cql3/restrictions/SimpleRestriction.java | 14 +-
.../org/apache/cassandra/db/filter/RowFilter.java | 9 +-
.../operations/SelectMultiColumnRelationTest.java | 584 ++++++++++++++++++++-
.../operations/SelectSingleColumnRelationTest.java | 499 +++++++++++++++++-
.../cql3/validation/operations/SelectTest.java | 312 +++++++++--
.../index/sai/cql/TokenRangeReadTest.java | 31 ++
.../index/sai/cql/UnindexedExpressionsTest.java | 4 +-
21 files changed, 1593 insertions(+), 98 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index d3e54a69f7..26cb5d2c29 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.1
+ * Add support for NOT operators in WHERE clauses. Fixed Three Valued Logic
(CASSANDRA-18584)
* Allow getendpoints for system tables and make sure getNaturalReplicas work
for MetaStrategy (CASSANDRA-19846)
* On upgrade, handle pre-existing tables with unexpected table ids
(CASSANDRA-19845)
* Reconfigure CMS before assassinate (CASSANDRA-19768)
diff --git a/doc/cql3/CQL.textile b/doc/cql3/CQL.textile
index d60b4d476f..4c2b09acc3 100644
--- a/doc/cql3/CQL.textile
+++ b/doc/cql3/CQL.textile
@@ -940,6 +940,10 @@ bc(syntax)..
| <identifier> IN <variable>
| '(' <identifier> (',' <identifier>)* ')' IN '(' ( <term-tuple>
( ',' <term-tuple>)* )? ')'
| '(' <identifier> (',' <identifier>)* ')' IN <variable>
+ | <identifier> NOT IN '(' ( <term> ( ',' <term>)* )? ')'
+ | <identifier> NOT IN <variable>
+ | '(' <identifier> (',' <identifier>)* ')' NOT IN '(' (
<term-tuple> ( ',' <term-tuple>)* )? ')'
+ | '(' <identifier> (',' <identifier>)* ')' NOT IN <variable>
<option> ::= TIMESTAMP <integer>
| TTL <integer>
@@ -993,12 +997,16 @@ bc(syntax)..
<where-clause> ::= <relation> ( AND <relation> )*
-<relation> ::= <identifier> <op> <term>
+<relation> ::= <identifier> (<op> | NOT CONTAINS ( KEY )?) <term>
| '(' <identifier> (',' <identifier>)* ')' <op> <term-tuple>
| <identifier> IN '(' ( <term> ( ',' <term>)* )? ')'
| <identifier> IN <variable>
| '(' <identifier> (',' <identifier>)* ')' IN '(' ( <term-tuple>
( ',' <term-tuple>)* )? ')'
| '(' <identifier> (',' <identifier>)* ')' IN <variable>
+ | <identifier> NOT IN '(' ( <term> ( ',' <term>)* )? ')'
+ | <identifier> NOT IN <variable>
+ | '(' <identifier> (',' <identifier>)* ')' NOT IN '(' (
<term-tuple> ( ',' <term-tuple>)* )? ')'
+ | '(' <identifier> (',' <identifier>)* ')' NOT IN <variable>
<op> ::= '=' | '<' | '>' | '<=' | '>=' | CONTAINS ( KEY )?
<in-values> ::= (<variable> | '(' ( <term> ( ',' <term> )* )? ')')
@@ -1118,9 +1126,11 @@ bc(syntax)..
| '(' <identifier> (',' <identifier>)* ')' <op> <term-tuple>
| <identifier> IN '(' ( <term> ( ',' <term>)* )? ')'
| '(' <identifier> (',' <identifier>)* ')' IN '(' ( <term-tuple>
( ',' <term-tuple>)* )? ')'
+ | <identifier> NOT IN '(' ( <term> ( ',' <term>)* )? ')'
+ | '(' <identifier> (',' <identifier>)* ')' NOT IN '(' (
<term-tuple> ( ',' <term-tuple>)* )? ')'
| TOKEN '(' <identifier> ( ',' <identifer>)* ')' <op> <term>
-<op> ::= '=' | '<' | '>' | '<=' | '>=' | CONTAINS | CONTAINS KEY
+<op> ::= '=' | '<' | '>' | '<=' | '>=' | CONTAINS | CONTAINS KEY | NOT
CONTAINS | NOT CONTAINS KEY
<group-by> ::= (<identifier>,)* (<identifier> | <function>)
<order-by> ::= <ordering> ( ',' <odering> )*
<ordering> ::= <identifer> ( ASC | DESC )?
diff --git a/doc/modules/cassandra/examples/BNF/select_statement.bnf
b/doc/modules/cassandra/examples/BNF/select_statement.bnf
index f53da41da5..260d55dcd3 100644
--- a/doc/modules/cassandra/examples/BNF/select_statement.bnf
+++ b/doc/modules/cassandra/examples/BNF/select_statement.bnf
@@ -16,6 +16,6 @@ where_clause::= `relation` ( AND `relation` )*
relation::= column_name operator term
'(' column_name ( ',' column_name )* ')' operator tuple_literal
TOKEN '(' column_name# ( ',' column_name )* ')' operator term
-operator::= '=' | '<' | '>' | '<=' | '>=' | '!=' | IN | CONTAINS | CONTAINS
KEY
+operator::= '=' | '<' | '>' | '<=' | '>=' | '!=' | IN | NOT IN | CONTAINS |
NOT CONTAINS | CONTAINS KEY | NOT CONTAINS KEY
group_by_clause::= column_name ( ',' column_name )*
ordering_clause::= column_name [ ASC | DESC ] ( ',' column_name [ ASC | DESC ]
)*
diff --git a/doc/modules/cassandra/pages/developing/cql/changes.adoc
b/doc/modules/cassandra/pages/developing/cql/changes.adoc
index e307919e3a..2dbfae7ecf 100644
--- a/doc/modules/cassandra/pages/developing/cql/changes.adoc
+++ b/doc/modules/cassandra/pages/developing/cql/changes.adoc
@@ -6,6 +6,7 @@ The following describes the changes in each version of CQL.
* Add support for the BETWEEN operator in WHERE clauses (`19604`)
* Add support for GENERATED PASSWORD clause (`17457`)
+* Add support for NOT operator in WHERE clauses ('18584')
== 3.4.7
diff --git a/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
b/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
index 18dd52e13d..bff1a65f47 100644
--- a/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
+++ b/doc/modules/cassandra/pages/developing/cql/cql_singlefile.adoc
@@ -1686,7 +1686,7 @@ FROM +
| `(' (`,' )* `)' IN `(' ( ( `,' )* )? `)' +
| TOKEN `(' ( `,' )* `)'
-::= `=' | `<' | `>' | `<=' | `>=' | CONTAINS | CONTAINS KEY +
+::= `=' | `<' | `>' | `<=' | `>=' | CONTAINS | CONTAINS KEY | NOT CONTAINS |
NOT CONTAINS KEY +
::= (`,' )* +
::= ( `,' )* +
::= ( ASC | DESC )? +
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index e09094f317..ce2b3726c4 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -738,11 +738,11 @@ syntax_rules += r'''
;
<whereClause> ::= <relation> ( "AND" <relation> )*
;
-<relation> ::= [rel_lhs]=<cident> ( "[" <term> "]" )? ( "=" | "<" | ">" | "<="
| ">=" | "CONTAINS" ( "KEY" )? ) <term>
+<relation> ::= [rel_lhs]=<cident> ( "[" <term> "]" )? ( "=" | "<" | ">" | "<="
| ">=" | "!=" | ( "NOT" )? "CONTAINS" ( "KEY" )? ) <term>
| token="TOKEN" "(" [rel_tokname]=<cident>
( "," [rel_tokname]=<cident> )*
")" ("=" | "<" | ">" | "<=" | ">=")
<tokenDefinition>
- | [rel_lhs]=<cident> "IN" "(" <term> ( "," <term> )* ")"
+ | [rel_lhs]=<cident> (( "NOT" )? "IN" ) "(" <term> ( "," <term>
)* ")"
| [rel_lhs]=<cident> "BETWEEN" <term> "AND" <term>
;
<selectClause> ::= "DISTINCT"? <selector> ("AS" <cident>)? ("," <selector>
("AS" <cident>)?)*
diff --git a/pylib/cqlshlib/test/test_cqlsh_completion.py
b/pylib/cqlshlib/test/test_cqlsh_completion.py
index a787f3fcb2..112474e7c7 100644
--- a/pylib/cqlshlib/test/test_cqlsh_completion.py
+++ b/pylib/cqlshlib/test/test_cqlsh_completion.py
@@ -381,7 +381,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE
lonel",
immediate='ykey ')
self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE
lonelykey ",
- choices=['=', '<=', '>=', '>', '<', 'BETWEEN',
'CONTAINS', 'IN', '['])
+ choices=['=', '<=', '>=', '>', '<', '!=',
'BETWEEN', 'CONTAINS', 'IN', 'NOT', '['])
self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE
lonelykey = 0.0 ",
choices=['AND', 'IF', ';'])
self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE
lonelykey = 0.0 AND ",
@@ -397,7 +397,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
choices=['EXISTS', '<quotedName>', '<identifier>'])
self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE
TOKEN(lonelykey) <= TOKEN(13) IF EXISTS ",
- choices=['>=', '!=', '<=', 'IN', '[', ';', '=',
'<', '>', '.', 'CONTAINS'])
+ choices=['>=', '!=', '<=', 'IN','[', ';', '=',
'<', '>', '.', 'CONTAINS'])
self.trycompletions("UPDATE empty_table SET lonelycol = 'eggs' WHERE
TOKEN(lonelykey) <= TOKEN(13) IF lonelykey ",
choices=['>=', '!=', '<=', 'IN', '=', '<', '>',
'CONTAINS'])
@@ -464,7 +464,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
choices=['a', 'b', 'TOKEN('])
self.trycompletions('DELETE FROM twenty_rows_composite_table USING
TIMESTAMP 0 WHERE a ',
- choices=['<=', '>=', 'BETWEEN', 'CONTAINS', 'IN',
'[', '=', '<', '>'])
+ choices=['<=', '>=', 'BETWEEN', 'CONTAINS', 'IN',
'NOT' , '[', '=', '<', '>', '!='])
self.trycompletions('DELETE FROM twenty_rows_composite_table USING
TIMESTAMP 0 WHERE TOKEN(',
immediate='a ')
diff --git a/src/antlr/Parser.g b/src/antlr/Parser.g
index d774022e19..099feaa1db 100644
--- a/src/antlr/Parser.g
+++ b/src/antlr/Parser.g
@@ -1756,7 +1756,7 @@ columnCondition returns [ColumnCondition.Raw condition]
// Note: we'll reject duplicates later
: column=cident
( op=relationType t=term { $condition =
ColumnCondition.Raw.simpleCondition(column, op, Terms.Raw.of(t)); }
- | op=containsOperator t=term { $condition =
ColumnCondition.Raw.simpleCondition(column, op, Terms.Raw.of(t)); }
+ | K_CONTAINS (K_KEY)? t=term { $condition =
ColumnCondition.Raw.simpleCondition(column, $K_KEY != null ?
Operator.CONTAINS_KEY : Operator.CONTAINS, Terms.Raw.of(t)); }
| K_IN v=singleColumnInValues { $condition =
ColumnCondition.Raw.simpleCondition(column, Operator.IN, v); }
| '[' element=term ']'
( op=relationType t=term { $condition =
ColumnCondition.Raw.collectionElementCondition(column, element, op,
Terms.Raw.of(t)); }
@@ -1804,8 +1804,8 @@ relation[WhereClause.Builder clauses]
| K_BETWEEN betweenValues=singleColumnBetweenValues {
$clauses.add(Relation.singleColumn(name, Operator.BETWEEN, betweenValues)); }
| K_LIKE t=term { $clauses.add(Relation.singleColumn(name,
Operator.LIKE, t)); }
| K_IS K_NOT K_NULL { $clauses.add(Relation.singleColumn(name,
Operator.IS_NOT, Constants.NULL_LITERAL)); }
- | K_IN inValue=singleColumnInValues {
$clauses.add(Relation.singleColumn(name, Operator.IN, inValue)); }
- | rt=containsOperator t=term {
$clauses.add(Relation.singleColumn(name, rt, t)); }
+ | rtInOperator=inOperator inValue=singleColumnInValues {
$clauses.add(Relation.singleColumn(name, rtInOperator, inValue)); }
+ | rtContainsOperator=containsOperator t=term {
$clauses.add(Relation.singleColumn(name, rtContainsOperator, t)); }
)
| K_TOKEN l=tupleOfIdentifiers
( type=relationType t=term { $clauses.add(Relation.token(l, type, t));
}
@@ -1813,7 +1813,7 @@ relation[WhereClause.Builder clauses]
)
| name=cident '[' key=term ']' type=relationType t=term {
$clauses.add(Relation.mapElement(name, key, type, t)); }
| ids=tupleOfIdentifiers
- ( K_IN inValue=multiColumnInValues {
$clauses.add(Relation.multiColumn(ids, Operator.IN, inValue)); }
+ ( rt=inOperator inValue=multiColumnInValues {
$clauses.add(Relation.multiColumn(ids, rt, inValue)); }
| type=relationType v=multiColumnValue
{$clauses.add(Relation.multiColumn(ids, type, v)); }
| K_BETWEEN t1=multiColumnValue K_AND t2=multiColumnValue {
$clauses.add(Relation.multiColumn(ids, Operator.BETWEEN,
Terms.Raw.of(List.of(t1, t2)))); }
)
@@ -1822,6 +1822,12 @@ relation[WhereClause.Builder clauses]
containsOperator returns [Operator o]
: K_CONTAINS { o = Operator.CONTAINS; } (K_KEY { o =
Operator.CONTAINS_KEY; })?
+ | K_NOT K_CONTAINS { o = Operator.NOT_CONTAINS; } (K_KEY { o =
Operator.NOT_CONTAINS_KEY; })?
+ ;
+
+inOperator returns [Operator o]
+ : K_IN { o = Operator.IN; }
+ | K_NOT K_IN { o = Operator.NOT_IN; }
;
inMarker returns [Terms.Raw marker]
diff --git a/src/java/org/apache/cassandra/cql3/Operator.java
b/src/java/org/apache/cassandra/cql3/Operator.java
index 3b86f83fc9..18c7a9f3f9 100644
--- a/src/java/org/apache/cassandra/cql3/Operator.java
+++ b/src/java/org/apache/cassandra/cql3/Operator.java
@@ -326,7 +326,8 @@ public enum Operator
IN(7)
{
@Override
- public Kind kind() {
+ public Kind kind()
+ {
return Kind.MULTI_VALUE;
}
@@ -408,6 +409,12 @@ public enum Operator
{
return true;
}
+
+ @Override
+ public Operator negate()
+ {
+ return NOT_CONTAINS;
+ }
},
CONTAINS_KEY(6)
{
@@ -443,6 +450,12 @@ public enum Operator
{
return true;
}
+
+ @Override
+ public Operator negate()
+ {
+ return NOT_CONTAINS_KEY;
+ }
},
NEQ(8)
{
@@ -479,10 +492,17 @@ public enum Operator
return leftOperand == null || type.compareCQL(leftOperand,
elements) != 0;
}
+ @Override
+ public void restrict(RangeSet<ClusteringElements> rangeSet,
List<ClusteringElements> args)
+ {
+ assert args.size() == 1;
+ rangeSet.remove(ClusteringElements.notEqualTo(args.get(0)));
+ }
+
@Override
public boolean requiresFilteringOrIndexingFor(ColumnMetadata.Kind
columnKind)
{
- return !columnKind.isPrimaryKeyKind();
+ return columnKind != ColumnMetadata.Kind.CLUSTERING;
}
@Override
@@ -491,11 +511,23 @@ public enum Operator
return EQ;
}
+ @Override
+ public boolean isSupportedByRestrictionsOn(ColumnsExpression
expression)
+ {
+ return true;
+ }
+
@Override
protected boolean isSupportedByReadPath()
{
return false;
}
+
+ @Override
+ public boolean isSlice()
+ {
+ return true;
+ }
},
IS_NOT(9)
{
@@ -606,10 +638,143 @@ public enum Operator
return true;
}
},
+ NOT_IN(16)
+ {
+ @Override
+ public Kind kind()
+ {
+ return Kind.MULTI_VALUE;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "NOT IN";
+ }
+ @Override
+ public boolean isSatisfiedBy(AbstractType<?> type, ByteBuffer
leftOperand, ByteBuffer rightOperand)
+ {
+ return !IN.isSatisfiedBy(type, leftOperand, rightOperand);
+ }
+
+ @Override
+ public boolean isSatisfiedBy(MultiElementType<?> type,
ComplexColumnData leftOperand, ByteBuffer rightOperand)
+ {
+ return !IN.isSatisfiedBy(type, leftOperand, rightOperand);
+ }
+
+ @Override
+ public boolean requiresFilteringOrIndexingFor(ColumnMetadata.Kind
columnKind)
+ {
+ return columnKind != ColumnMetadata.Kind.CLUSTERING;
+ }
+
+ @Override
+ public void restrict(RangeSet<ClusteringElements> rangeSet,
List<ClusteringElements> args)
+ {
+ for (ClusteringElements clustering : args)
+ rangeSet.remove(ClusteringElements.notEqualTo(clustering));
+ }
+
+ @Override
+ public Operator negate()
+ {
+ return IN;
+ }
+
+ @Override
+ public boolean isSlice()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isSupportedByRestrictionsOn(ColumnsExpression
expression)
+ {
+ return expression.kind() == ColumnsExpression.Kind.SINGLE_COLUMN
|| expression.kind() == ColumnsExpression.Kind.MULTI_COLUMN;
+ }
+ },
+ NOT_CONTAINS(17)
+ {
+ @Override
+ public String toString()
+ {
+ return "NOT CONTAINS";
+ }
+
+ @Override
+ public boolean isSatisfiedBy(AbstractType<?> type, ByteBuffer
leftOperand, ByteBuffer rightOperand)
+ {
+ return !CONTAINS.isSatisfiedBy(type, leftOperand, rightOperand);
+ }
+
+ @Override
+ public boolean isSatisfiedBy(MultiElementType<?> type,
ComplexColumnData leftOperand, ByteBuffer rightOperand)
+ {
+ return !CONTAINS.isSatisfiedBy(type, leftOperand, rightOperand);
+ }
+
+ @Override
+ public boolean appliesToColumnValues()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean appliesToCollectionElements()
+ {
+ return true;
+ }
+
+ @Override
+ public Operator negate()
+ {
+ return CONTAINS;
+ }
+ },
+ NOT_CONTAINS_KEY(18)
+ {
+ @Override
+ public String toString()
+ {
+ return "NOT CONTAINS KEY";
+ }
+
+ @Override
+ public boolean isSatisfiedBy(AbstractType<?> type, ByteBuffer
leftOperand, ByteBuffer rightOperand)
+ {
+ return !CONTAINS_KEY.isSatisfiedBy(type, leftOperand,
rightOperand);
+ }
+
+ @Override
+ public boolean isSatisfiedBy(MultiElementType<?> type,
ComplexColumnData leftOperand, ByteBuffer rightOperand)
+ {
+ return !CONTAINS_KEY.isSatisfiedBy(type, leftOperand,
rightOperand);
+ }
+
+ @Override
+ public boolean appliesToColumnValues()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean appliesToMapKeys()
+ {
+ return true;
+ }
+
+ @Override
+ public Operator negate()
+ {
+ return CONTAINS_KEY;
+ }
+ },
BETWEEN(19)
{
@Override
- public Kind kind() {
+ public Kind kind()
+ {
return Kind.TERNARY;
}
@@ -773,7 +938,7 @@ public enum Operator
case SINGLE_COLUMN:
ColumnMetadata firstColumn = expression.firstColumn();
AbstractType<?> columnType = firstColumn.type;
- if (isSlice())
+ if (isSlice() && this != Operator.NEQ)
{
if (columnType.referencesDuration())
{
diff --git a/src/java/org/apache/cassandra/cql3/Relation.java
b/src/java/org/apache/cassandra/cql3/Relation.java
index be9112c817..86d8db1cbb 100644
--- a/src/java/org/apache/cassandra/cql3/Relation.java
+++ b/src/java/org/apache/cassandra/cql3/Relation.java
@@ -188,11 +188,11 @@ public final class Relation
*/
public SingleRestriction toRestriction(TableMetadata table,
VariableSpecifications boundNames)
{
- if (operator == Operator.NEQ)
- throw invalidRequest("Unsupported '!=' relation: %s", this);
-
ColumnsExpression columnsExpression = rawExpressions.prepare(table);
+ if (operator == Operator.NEQ && columnsExpression.kind() ==
ColumnsExpression.Kind.TOKEN)
+ throw invalidRequest("Unsupported '!=' relation: %s", this);
+
// TODO support restrictions on list elements as we do in conditions,
then we can probably move below validations
// to ElementExpression prepare/validateColumns
if (columnsExpression.isMapElementExpression())
diff --git a/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java
b/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java
index 3c0aa7ca19..1d0afcddc2 100644
--- a/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java
+++ b/src/java/org/apache/cassandra/cql3/conditions/ColumnCondition.java
@@ -353,7 +353,7 @@ public final class ColumnCondition
private void validateOperationOnDurations(AbstractType<?> type)
{
- if (type.referencesDuration() && operator.isSlice())
+ if (type.referencesDuration() && operator.isSlice() && operator !=
Operator.NEQ)
{
checkFalse(type.isCollection(), "Slice conditions are not
supported on collections containing durations");
checkFalse(type.isTuple(), "Slice conditions are not supported
on tuples containing durations");
diff --git
a/src/java/org/apache/cassandra/cql3/restrictions/ClusteringElements.java
b/src/java/org/apache/cassandra/cql3/restrictions/ClusteringElements.java
index a7ce83ffb2..f8f04ebb57 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/ClusteringElements.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/ClusteringElements.java
@@ -277,6 +277,11 @@ public class ClusteringElements extends
ForwardingList<ByteBuffer> implements Co
return buildRangeSet(endpoint, false, BoundType.OPEN);
}
+ public static Range<ClusteringElements> notEqualTo(ClusteringElements
endpoint)
+ {
+ return Range.closed(endpoint.bottom(), endpoint.top());
+ }
+
private static RangeSet<ClusteringElements>
buildRangeSet(ClusteringElements endpoint, boolean upperBound, BoundType
boundType)
{
TreeRangeSet<ClusteringElements> rangeSet = TreeRangeSet.create();
diff --git
a/src/java/org/apache/cassandra/cql3/restrictions/MergedRestriction.java
b/src/java/org/apache/cassandra/cql3/restrictions/MergedRestriction.java
index 69b9a840a0..7976b78b7c 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/MergedRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/MergedRestriction.java
@@ -60,7 +60,7 @@ public final class MergedRestriction implements
SingleRestriction
private final boolean isMultiColumn;
/**
- * The number of restrictions that require {@code CONTAINS}, {@code
CONTAINS_KEY} and Map equality restrictions.
+ * The number of restrictions that require {@code CONTAINS}, {@code
CONTAINS_KEY}, {@code NOT_CONTAINS}, {@code NOT_CONTAINS_KEY} and Map equality
restrictions.
*/
private final int containsCount;
@@ -124,7 +124,7 @@ public final class MergedRestriction implements
SingleRestriction
checkOperator(other);
if (restriction.isContains() != other.isContains())
- throw invalidRequest("Collection column %s can only be restricted
by CONTAINS, CONTAINS KEY," +
+ throw invalidRequest("Collection column %s can only be restricted
by CONTAINS, CONTAINS KEY, NOT_CONTAINS, NOT_CONTAINS_KEY" +
" or map-entry equality if it already
restricted by one of those",
restriction.firstColumn().name);
@@ -201,7 +201,7 @@ public final class MergedRestriction implements
SingleRestriction
}
/**
- * Checks if the restriction operator is a CONTAINS, CONTAINS_KEY or is an
equality on a map element.
+ * Checks if the restriction operator is a CONTAINS, CONTAINS_KEY,
NOT_CONTAINS, NOT_CONTAINS_KEY or is an equality on a map element.
* @param restriction the restriction to check
* @return {@code true} if the restriction operator is one of the contains
operations, {@code false} otherwise.
*/
diff --git
a/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
b/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
index ce3dfd4eef..e4df4c7a69 100644
---
a/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
+++
b/src/java/org/apache/cassandra/cql3/restrictions/PartitionKeyRestrictions.java
@@ -110,7 +110,7 @@ final class PartitionKeyRestrictions extends
RestrictionSetWrapper
*/
public List<ByteBuffer> values(IPartitioner partitioner, QueryOptions
options, ClientState state)
{
- // if we need to perform filtering its means that this query is a
partition range query and that
+ // if we need to perform filtering it means that this query is a
partition range query and that
// this method should not be called
if (isEmpty() || needFiltering())
throw new IllegalStateException("the query is a partition range
query and this method should not be called");
diff --git
a/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java
b/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java
index 223930a957..d8b6e7aec8 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java
@@ -135,15 +135,17 @@ public final class SimpleRestriction implements
SingleRestriction
}
/**
- * Checks if this restriction operator is a CONTAINS, CONTAINS_KEY or is
an equality on a map element.
+ * Checks if this restriction operator is a CONTAINS, CONTAINS_KEY,
NOT_CONTAINS, NOT_CONTAINS_KEY or is an equality on a map element.
* @return {@code true} if the restriction operator is one of the contains
operations, {@code false} otherwise.
*/
public boolean isContains()
{
return operator == Operator.CONTAINS
- || operator == Operator.CONTAINS_KEY
+ || operator == Operator.CONTAINS_KEY
+ || operator == Operator.NOT_CONTAINS
+ || operator == Operator.NOT_CONTAINS_KEY
// TODO only map elements supported for now in restrictions
- || columnsExpression.isMapElementExpression();
+ || columnsExpression.isMapElementExpression();
}
@Override
@@ -217,7 +219,9 @@ public final class SimpleRestriction implements
SingleRestriction
@Override
public List<ClusteringElements> values(QueryOptions options)
{
- assert operator == Operator.EQ || operator == Operator.IN || operator
== Operator.ANN;
+ assert operator == Operator.EQ ||
+ operator == Operator.IN ||
+ operator == Operator.ANN;
return bindAndGetClusteringElements(options);
}
@@ -327,7 +331,7 @@ public final class SimpleRestriction implements
SingleRestriction
{
case SINGLE_COLUMN:
List<ByteBuffer> buffers = bindAndGet(options);
- if (operator == Operator.IN || operator == Operator.BETWEEN)
+ if (operator.kind() != Operator.Kind.BINARY)
{
filter.add(column, operator,
multiInputOperatorValues(column, buffers));
}
diff --git a/src/java/org/apache/cassandra/db/filter/RowFilter.java
b/src/java/org/apache/cassandra/db/filter/RowFilter.java
index 6c427873ba..4e126e200d 100644
--- a/src/java/org/apache/cassandra/db/filter/RowFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/RowFilter.java
@@ -734,15 +734,18 @@ public class RowFilter implements
Iterable<RowFilter.Expression>
switch (operator)
{
case CONTAINS:
+ case NOT_CONTAINS:
assert type instanceof CollectionType;
CollectionType<?> ct = (CollectionType<?>)type;
type = ct.kind == CollectionType.Kind.SET ?
ct.nameComparator() : ct.valueComparator();
break;
case CONTAINS_KEY:
+ case NOT_CONTAINS_KEY:
assert type instanceof MapType;
type = ((MapType<?, ?>)type).nameComparator();
break;
case IN:
+ case NOT_IN:
case BETWEEN:
type = ListType.getInstance(type, false);
break;
@@ -783,7 +786,7 @@ public class RowFilter implements
Iterable<RowFilter.Expression>
public MapElementExpression(ColumnMetadata column, ByteBuffer key,
Operator operator, ByteBuffer value)
{
super(column, operator, value);
- assert column.type instanceof MapType && operator == Operator.EQ;
+ assert column.type instanceof MapType && (operator == Operator.EQ
|| operator == Operator.NEQ);
this.key = key;
}
@@ -836,8 +839,8 @@ public class RowFilter implements
Iterable<RowFilter.Expression>
AbstractType<?> nt = mt.nameComparator();
AbstractType<?> vt = mt.valueComparator();
return cql
- ? String.format("%s[%s] = %s", column.name.toCQLString(),
nt.toCQLString(key), vt.toCQLString(value))
- : String.format("%s[%s] = %s", column.name.toString(),
nt.getString(key), vt.getString(value));
+ ? String.format("%s[%s] %s %s", column.name.toCQLString(),
nt.toCQLString(key), operator, vt.toCQLString(value))
+ : String.format("%s[%s] %s %s", column.name.toString(),
nt.getString(key), operator, vt.getString(value));
}
@Override
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 cc8d589c67..1029196754 100644
---
a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
+++
b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
@@ -132,7 +132,7 @@ public class SelectMultiColumnRelationTest extends CQLTester
}
@Test
- public void testMultiAndSingleColumnRelationMix() throws Throwable
+ public void testMultiAndSingleColumnRelationMix()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY
(a, b, c, d))");
@@ -235,7 +235,7 @@ public class SelectMultiColumnRelationTest extends CQLTester
}
@Test
- public void testSeveralMultiColumnRelation() throws Throwable
+ public void testSeveralMultiColumnRelation()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY
(a, b, c, d))");
@@ -390,11 +390,94 @@ public class SelectMultiColumnRelationTest extends
CQLTester
}
@Test
- public void testNonEqualsRelation() throws Throwable
+ public void testNonEqualsRelation()
{
- createTable("CREATE TABLE %s (a int PRIMARY KEY, b int)");
- assertInvalidMessage("Unsupported '!=' relation: (b) != (0)",
- "SELECT * FROM %s WHERE a = 0 AND (b) != (0)");
+ createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b,
c))");
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 0, 0);
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 0, 1);
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 1, 0);
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 1, 1);
+
+ // Excluding subtrees
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b) !=
(?)", 0, 0),
+ row(0, 1, 0),
+ row(0, 1, 1)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b) !=
(?)", 0, 1),
+ row(0, 0, 0),
+ row(0, 0, 1)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b) !=
(?)", 0, -1),
+ row(0, 0, 0),
+ row(0, 0, 1),
+ row(0, 1, 0),
+ row(0, 1, 1)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b) !=
(?)", 0, 2),
+ row(0, 0, 0),
+ row(0, 0, 1),
+ row(0, 1, 0),
+ row(0, 1, 1)
+ );
+
+ // Excluding single rows
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) !=
(?, ?)", 0, -1, -1),
+ row(0, 0, 0),
+ row(0, 0, 1),
+ row(0, 1, 0),
+ row(0, 1, 1)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) !=
(?, ?)", 0, 0, 1),
+ row(0, 0, 0),
+ row(0, 1, 0),
+ row(0, 1, 1)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) !=
(?, ?)", 0, 2, 2),
+ row(0, 0, 0),
+ row(0, 0, 1),
+ row(0, 1, 0),
+ row(0, 1, 1)
+ );
+
+ // Merging multiple != =
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) != ?
AND (b, c) != ?", 0, tuple(0, 1), tuple(1, 0)),
+ row(0, 0, 0),
+ row(0, 1, 1)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND b != ? AND
(b, c) != ?", 0, 1, tuple(0, 1)),
+ row(0, 0, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b) != (?)
AND (b, c) != ?", 0, 1, tuple(0, 1)),
+ row(0, 0, 0)
+ );
+
+ // Merging with < <= >= >
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND b < ? AND
(b, c) != ?", 0, 1, tuple(0, 1)),
+ row(0, 0, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND b <= ? AND
(b, c) != ?", 0, 0, tuple(0, 1)),
+ row(0, 0, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND b > ? AND
(b, c) != ?", 0, 0, tuple(1, 1)),
+ row(0, 1, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND b >= ? AND
(b, c) != ?", 0, 1, tuple(1, 1)),
+ row(0, 1, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) < ?
AND (b, c) != ?", 0, tuple(0, 2), tuple(0, 1)),
+ row(0, 0, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) <= ?
AND (b, c) != ?", 0, tuple(0, 2), tuple(0, 1)),
+ row(0, 0, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) > ?
AND (b, c) != ?", 0, tuple(0, 0), tuple(1, 1)),
+ row(0, 0, 1),
+ row(0, 1, 0)
+ );
+ assertRows(execute("SELECT a, b, c FROM %s WHERE a = ? AND (b, c) >= ?
AND (b, c) != ?", 0, tuple(0, 1), tuple(1, 1)),
+ row(0, 0, 1),
+ row(0, 1, 0)
+ );
}
@Test
@@ -773,7 +856,7 @@ public class SelectMultiColumnRelationTest extends CQLTester
}
@Test
- public void testMultipleClusteringReversedComponents() throws Throwable
+ public void testMultipleClusteringReversedComponents()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY
(a, b, c, d)) WITH CLUSTERING ORDER BY (b DESC, c ASC, d DESC)");
@@ -1134,7 +1217,7 @@ public class SelectMultiColumnRelationTest extends
CQLTester
}
@Test
- public void testINWithDuplicateValue() throws Throwable
+ public void testINWithDuplicateValue()
{
createTable("CREATE TABLE %s (k1 int, k2 int, v int, PRIMARY KEY (k1,
k2))");
execute("INSERT INTO %s (k1, k2, v) VALUES (?, ?, ?)", 1, 1, 1);
@@ -1168,7 +1251,7 @@ public class SelectMultiColumnRelationTest extends
CQLTester
}
@Test
- public void testMixedOrderColumns1() throws Throwable
+ public void testMixedOrderColumns1()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, e int,
PRIMARY KEY (a, b, c, d, e)) WITH " +
" CLUSTERING ORDER BY (b DESC, c ASC, d DESC, e ASC)");
@@ -1650,7 +1733,7 @@ public class SelectMultiColumnRelationTest extends
CQLTester
}
@Test
- public void testMixedOrderColumns2() throws Throwable
+ public void testMixedOrderColumns2()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, e int,
PRIMARY KEY (a, b, c, d, e)) WITH " +
"CLUSTERING ORDER BY (b DESC, c ASC, d ASC, e ASC)");
@@ -1724,7 +1807,7 @@ public class SelectMultiColumnRelationTest extends
CQLTester
}
@Test
- public void testMixedOrderColumns3() throws Throwable
+ public void testMixedOrderColumns3()
{
createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b,
c)) WITH " +
"CLUSTERING ORDER BY (b DESC, c ASC)");
@@ -1760,7 +1843,7 @@ public class SelectMultiColumnRelationTest extends
CQLTester
}
@Test
- public void testMixedOrderColumns4() throws Throwable
+ public void testMixedOrderColumns4()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, e int,
PRIMARY KEY (a, b, c, d, e)) WITH " +
"CLUSTERING ORDER BY (b ASC, c DESC, d DESC, e ASC)");
@@ -2120,7 +2203,7 @@ public class SelectMultiColumnRelationTest extends
CQLTester
}
@Test
- public void testMixedOrderColumnsInReverse() throws Throwable
+ public void testMixedOrderColumnsInReverse()
{
createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b,
c)) WITH CLUSTERING ORDER BY (b ASC, c DESC);");
@@ -2156,7 +2239,7 @@ public class SelectMultiColumnRelationTest extends
CQLTester
* migrated from cql_tests.py:TestCQL.simple_tuple_query_test()
*/
@Test
- public void testSimpleTupleQuery() throws Throwable
+ public void testSimpleTupleQuery()
{
createTable("create table %s (a int, b int, c int, d int , e int,
PRIMARY KEY (a, b, c, d, e))");
@@ -2226,4 +2309,477 @@ public class SelectMultiColumnRelationTest extends
CQLTester
assertInvalidMessage("Multicolumn IN filters are not supported",
"SELECT * FROM %s WHERE (c2, c3) IN ((?, ?), (?,
?)) ALLOW FILTERING", 1, 0, 2, 0);
}
+
+ @Test
+ public void testNotInRestrictionsWithClustering()
+ {
+ createTable("CREATE TABLE %s (pk int, c1 int, c2 int, v int, primary
key(pk, c1, c2))");
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 1,
11);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 2,
12);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 3,
13);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 4,
14);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 1,
21);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 2,
22);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 3,
23);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 4,
24);
+
+ // empty NOT IN
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
()", 1),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+
+ // non existent NOT IN:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
((?, ?))", 1, 2000, 2001),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+
+ // existing values in NOT IN, different ways of passing them:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
((0, 2), (0, 3), (1, 1), (1, 4))", 1),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
((?, ?), (?, ?), (?, ?), (?, ?))",
+ 1, 0, 2, 0, 3, 1, 1, 1, 4),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
(?, ?, ?, ?)",
+ 1, tuple(0, 2), tuple(0, 3), tuple(1, 1), tuple(1,
4)),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
?",
+ 1, list(tuple(0, 2), tuple(0, 3), tuple(1, 1),
tuple(1, 4))),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ // Tuples given in arbitrary order:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
(?, ?, ?, ?)",
+ 1, tuple(0, 3), tuple(1, 4), tuple(1, 1), tuple(0,
2)),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ // Multiple NOT IN:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
(?, ?) AND (c1, c2) NOT IN (?, ?)",
+ 1, tuple(0, 2), tuple(0, 3), tuple(1, 1), tuple(1,
4)),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ // Multiple NOT IN, mixed markers:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
(?, ?) AND (c1, c2) NOT IN ?",
+ 1, tuple(0, 2), tuple(0, 3), list(tuple(1, 1),
tuple(1, 4))),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ // Multiple NOT IN, mixed markers and values:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) NOT IN
((0, 2), (0, 3)) AND (c1, c2) NOT IN ?",
+ 1, list(tuple(1, 1), tuple(1, 4))),
+ row(1, 0, 1, 11),
+ row(1, 0, 4, 14),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ // Mixed single-column and multicolumn restrictions:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 NOT IN ? AND
(c1, c2) NOT IN ?",
+ 1, list(0), list(tuple(1, 1), tuple(1, 4))),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 NOT IN (?)
AND (c1, c2) NOT IN (?, ?)",
+ 1, 0, tuple(1, 1), tuple(1, 4)),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+ }
+
+ @Test
+ public void testNotInRestrictionsWithClusteringAndSlices()
+ {
+ createTable("CREATE TABLE %s (pk int, c1 int, c2 int, v int, primary
key(pk, c1, c2))");
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 1,
11);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 2,
12);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 3,
13);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 4,
14);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 1,
21);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 2,
22);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 3,
23);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 4,
24);
+
+ // NOT IN values outside of slice bounds
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(2, 5)),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14),
+ row(1, 1, 1, 21));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(1, 1)),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+
+ // Empty result set
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?, ?)",
+ 1, tuple(1, 2), tuple(1, 3), tuple(1, 4)));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?, ?)",
+ 1, tuple(0, 3), tuple(0, 2), tuple(0, 1)));
+
+ // NOT IN values inside slice bounds
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(0, 2)),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14),
+ row(1, 1, 1, 21));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) <= ?
AND (c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(0, 2)),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 3)),
+ row(1, 1, 2, 22),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 3)),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 4, 24));
+
+
+ // One NOT IN value exactly the same as the slice bound
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?, ?)",
+ 1, tuple(1, 2), tuple(0, 2), tuple(1, 2)),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14),
+ row(1, 1, 1, 21));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) <= ?
AND (c1, c2) NOT IN (?, ?)",
+ 1, tuple(1, 2), tuple(0, 2), tuple(1, 2)),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14),
+ row(1, 1, 1, 21));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 1)),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 1)),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+
+ // NOT IN with both upper and lower bound
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) < ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 0, 3, 13),
+ row(1, 1, 1, 21));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) < ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 1, 1, 21));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) <= ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 0, 3, 13),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) <= ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22));
+
+ // Mixed multi-column NOT IN with single column slice restriction:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 > ? AND (c1,
c2) NOT IN (?)",
+ 1, 0, tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 >= ? AND (c1,
c2) NOT IN (?)",
+ 1, 1, tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 < ? AND (c1,
c2) NOT IN (?)",
+ 1, 1, tuple(0, 4)),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 <= ? AND (c1,
c2) NOT IN (?)",
+ 1, 0, tuple(0, 4)),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 >= ? AND c1
<= ? AND (c1, c2) NOT IN (?)",
+ 1, 0, 1, tuple(0, 4)),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+
+ // Mixed single-column NOT IN with multi-column slice restriction:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
c1 NOT IN (?)",
+ 1, tuple(0, 1), 1),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND c1 NOT IN (?)",
+ 1, tuple(0, 1), 1),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
c1 NOT IN (?)",
+ 1, tuple(1, 3), 1),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
c1 NOT IN (?)",
+ 1, tuple(1, 3), 0),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) <= ?
AND c1 NOT IN (?)",
+ 1, tuple(1, 3), 0),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) <= ? AND c1 NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 3), 0),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+ }
+
+ @Test
+ public void testNotInRestrictionsWithMixedOrderClusteringAndSlices()
+ {
+ createTable("CREATE TABLE %s (pk int, c1 int, c2 int, v int, primary
key(pk, c1, c2)) WITH CLUSTERING ORDER BY (c1 DESC, c2 ASC)");
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 1,
11);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 2,
12);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 3,
13);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 0, 4,
14);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 1,
21);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 2,
22);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 3,
23);
+ execute("INSERT INTO %s (pk, c1, c2, v) values (?, ?, ?, ?)", 1, 1, 4,
24);
+
+ // NOT IN values outside of slice bounds
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(2, 5)),
+ row(1, 1, 1, 21),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(1, 1)),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+
+ // Empty result set
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?, ?)",
+ 1, tuple(1, 2), tuple(1, 3), tuple(1, 4)));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?, ?)",
+ 1, tuple(0, 3), tuple(0, 2), tuple(0, 1)));
+
+ // NOT IN values inside slice bounds
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(0, 2)),
+ row(1, 1, 1, 21),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) <= ?
AND (c1, c2) NOT IN (?)",
+ 1, tuple(1, 2), tuple(0, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 3)),
+ row(1, 1, 2, 22),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 3)),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 4, 24));
+
+ // One NOT IN value exactly the same as the slice bound
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
(c1, c2) NOT IN (?, ?)",
+ 1, tuple(1, 2), tuple(0, 2), tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) <= ?
AND (c1, c2) NOT IN (?, ?)",
+ 1, tuple(1, 2), tuple(0, 2), tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 0, 1, 11),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 1)),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) NOT IN (?)",
+ 1, tuple(1, 1), tuple(1, 1)),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+
+
+ // NOT IN with both upper and lower bound
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) < ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 1, 1, 21),
+ row(1, 0, 3, 13));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) < ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 1, 1, 21),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
(c1, c2) <= ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 0, 3, 13));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) <= ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 2), tuple(0, 4)),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13));
+
+ // Mixed multi-column NOT IN with single column slice restriction:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 > ? AND (c1,
c2) NOT IN (?)",
+ 1, 0, tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 >= ? AND (c1,
c2) NOT IN (?)",
+ 1, 1, tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 < ? AND (c1,
c2) NOT IN (?)",
+ 1, 1, tuple(0, 4)),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 <= ? AND (c1,
c2) NOT IN (?)",
+ 1, 0, tuple(0, 4)),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 >= ? AND c1
<= ? AND (c1, c2) NOT IN (?)",
+ 1, 0, 1, tuple(0, 4)),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13));
+
+ // Mixed single-column NOT IN with multi-column slice restriction:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
c1 NOT IN (?)",
+ 1, tuple(0, 1), 1),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND c1 NOT IN (?)",
+ 1, tuple(0, 1), 1),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
c1 NOT IN (?)",
+ 1, tuple(1, 3), 1),
+ row(1, 0, 1, 11),
+ row(1, 0, 2, 12),
+ row(1, 0, 3, 13),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) < ? AND
c1 NOT IN (?)",
+ 1, tuple(1, 3), 0),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) <= ?
AND c1 NOT IN (?)",
+ 1, tuple(1, 3), 0),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) >= ?
AND (c1, c2) <= ? AND c1 NOT IN (?)",
+ 1, tuple(0, 2), tuple(1, 3), 0),
+ row(1, 1, 1, 21),
+ row(1, 1, 2, 22),
+ row(1, 1, 3, 23));
+
+ // Mixed single-column and multi column slices with multi column NOT
IN:
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
c1 < ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 1), 1, tuple(0, 3)),
+ row(1, 0, 2, 12),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND (c1, c2) > ? AND
c1 <= ? AND (c1, c2) NOT IN (?)",
+ 1, tuple(0, 1), 0, tuple(0, 3)),
+ row(1, 0, 2, 12),
+ row(1, 0, 4, 14));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 > ? AND (c1,
c2) < ? AND (c1, c2) NOT IN (?)",
+ 1, 0, tuple(1, 4), tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 >= ? AND (c1,
c2) < ? AND (c1, c2) NOT IN (?)",
+ 1, 1, tuple(1, 4), tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 > ? AND c1 <
? AND (c1, c2) NOT IN (?)",
+ 1, 0, 2, tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c1 >= ? AND c1
<= ? AND (c1, c2) NOT IN (?)",
+ 1, 1, 1, tuple(1, 2)),
+ row(1, 1, 1, 21),
+ row(1, 1, 3, 23),
+ row(1, 1, 4, 24));
+ }
}
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 8ecae0d48a..2f683c4e59 100644
---
a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
+++
b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectSingleColumnRelationTest.java
@@ -38,11 +38,11 @@ public class SelectSingleColumnRelationTest extends
CQLTester
createIndex("CREATE INDEX ON %s (d)");
assertInvalidMessage("Collection column 'b' (set<int>) cannot be
restricted by a '=' relation",
- "SELECT * FROM %s WHERE a = 0 AND b=?", set(0));
+ "SELECT * FROM %s WHERE a = 0 AND b = ?", set(0));
assertInvalidMessage("Collection column 'c' (list<int>) cannot be
restricted by a '=' relation",
- "SELECT * FROM %s WHERE a = 0 AND c=?", list(0));
+ "SELECT * FROM %s WHERE a = 0 AND c = ?",
list(0));
assertInvalidMessage("Collection column 'd' (map<int, int>) cannot be
restricted by a '=' relation",
- "SELECT * FROM %s WHERE a = 0 AND d=?", map(0,
0));
+ "SELECT * FROM %s WHERE a = 0 AND d = ?", map(0,
0));
}
@Test
@@ -65,8 +65,10 @@ public class SelectSingleColumnRelationTest extends CQLTester
"SELECT * FROM %s WHERE c = 0 AND b IN (?)",
set(0));
assertInvalidMessage("Collection column 'b' (set<int>) cannot be
restricted by a 'BETWEEN' relation",
"SELECT * FROM %s WHERE c = 0 AND b BETWEEN ? AND
?", set(0), set(0));
- assertInvalidMessage("Unsupported '!=' relation: b != 5",
- "SELECT * FROM %s WHERE c = 0 AND b != 5");
+ assertInvalidMessage("Collection column 'b' (set<int>) cannot be
restricted by a 'NOT IN' relation",
+ "SELECT * FROM %s WHERE c = 0 AND b NOT IN (?)",
set(0));
+ assertInvalidMessage("Collection column 'b' (set<int>) cannot be
restricted by a '!=' relation",
+ "SELECT * FROM %s WHERE c = 0 AND b != 5");
assertInvalidMessage("Unsupported restriction: b IS NOT NULL",
"SELECT * FROM %s WHERE c = 0 AND b IS NOT NULL");
}
@@ -216,7 +218,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testClusteringColumnRelationsWithClusteringOrder() throws
Throwable
+ public void testClusteringColumnRelationsWithClusteringOrder()
{
createTable("CREATE TABLE %s (a text, b int, c int, d int, primary
key(a, b, c)) WITH CLUSTERING ORDER BY (b DESC, c ASC);");
execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "first", 1,
5, 1);
@@ -313,7 +315,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testAllowFilteringWithIndexedColumnAndStaticColumns() throws
Throwable
+ public void testAllowFilteringWithIndexedColumnAndStaticColumns()
{
createTable("CREATE TABLE %s (a int, b int, c int, s int static,
PRIMARY KEY(a, b))");
createIndex("CREATE INDEX ON %s(c)");
@@ -340,7 +342,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testIndexQueriesOnComplexPrimaryKey() throws Throwable
+ public void testIndexQueriesOnComplexPrimaryKey()
{
createTable("CREATE TABLE %s (pk0 int, pk1 int, ck0 int, ck1 int, ck2
int, value int, PRIMARY KEY ((pk0, pk1), ck0, ck1, ck2))");
@@ -464,7 +466,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testINWithDuplicateValue() throws Throwable
+ public void testINWithDuplicateValue()
{
createTable("CREATE TABLE %s (k1 int, k2 int, v int, PRIMARY KEY (k1,
k2))");
execute("INSERT INTO %s (k1, k2, v) VALUES (?, ?, ?)", 1, 1, 1);
@@ -480,7 +482,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testLargeClusteringINValues() throws Throwable
+ public void testLargeClusteringINValues()
{
createTable("CREATE TABLE %s (k int, c int, v int, PRIMARY KEY (k,
c))");
execute("INSERT INTO %s (k, c, v) VALUES (0, 0, 0)");
@@ -595,7 +597,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testLimitWithUnset() throws Throwable
+ public void testLimitWithUnset()
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, i int)");
execute("INSERT INTO %s (k, i) VALUES (1, 1)");
@@ -616,12 +618,18 @@ public class SelectSingleColumnRelationTest extends
CQLTester
assertInvalidMessage("Invalid unset value for column k", "SELECT *
from %s WHERE k IN ?", unset());
assertInvalidMessage("Invalid unset value for column k", "SELECT *
from %s WHERE k IN(?)", unset());
assertInvalidMessage("Invalid unset value for column k", "SELECT *
from %s WHERE k IN(?,?)", 1, unset());
+ assertInvalidMessage("Invalid unset value for column k", "SELECT *
from %s WHERE k NOT IN ? ALLOW FILTERING", unset());
+ assertInvalidMessage("Invalid unset value for column k", "SELECT *
from %s WHERE k NOT IN(?) ALLOW FILTERING", unset());
+ assertInvalidMessage("Invalid unset value for column k", "SELECT *
from %s WHERE k NOT IN(?,?) ALLOW FILTERING", 1, unset());
// clustering column
assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE k = 1 AND i = ?", unset());
assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE k = 1 AND i IN ?", unset());
assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE k = 1 AND i IN(?)", unset());
assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE k = 1 AND i IN(?,?)", 1, unset());
assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE i = ? ALLOW FILTERING", unset());
+ assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE k = 1 AND i NOT IN ?", unset());
+ assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE k = 1 AND i NOT IN(?)", unset());
+ assertInvalidMessage("Invalid unset value for column i", "SELECT *
from %s WHERE k = 1 AND i NOT IN(?,?)", 1, unset());
// indexed column
assertInvalidMessage("Invalid unset value for column s", "SELECT *
from %s WHERE s = ?", unset());
// range
@@ -670,11 +678,16 @@ public class SelectSingleColumnRelationTest extends
CQLTester
assertInvalidMessage("Undefined column name d", "SELECT * FROM %s
WHERE d > 0 and d <= 2");
assertInvalidMessage("Undefined column name d", "SELECT * FROM %s
WHERE d CONTAINS 0");
assertInvalidMessage("Undefined column name d", "SELECT * FROM %s
WHERE d CONTAINS KEY 0");
+ assertInvalidMessage("Undefined column name d", "SELECT * FROM %s
WHERE d NOT CONTAINS 0");
+ assertInvalidMessage("Undefined column name d", "SELECT * FROM %s
WHERE d NOT CONTAINS KEY 0");
assertInvalidMessage("Undefined column name d", "SELECT a AS d FROM %s
WHERE d = 0");
assertInvalidMessage("Undefined column name d", "SELECT b AS d FROM %s
WHERE d IN (0, 1)");
+ assertInvalidMessage("Undefined column name d", "SELECT b AS d FROM %s
WHERE d NOT IN (0, 1)");
assertInvalidMessage("Undefined column name d", "SELECT b AS d FROM %s
WHERE d > 0 and d <= 2");
assertInvalidMessage("Undefined column name d", "SELECT c AS d FROM %s
WHERE d CONTAINS 0");
assertInvalidMessage("Undefined column name d", "SELECT c AS d FROM %s
WHERE d CONTAINS KEY 0");
+ assertInvalidMessage("Undefined column name d", "SELECT c AS d FROM %s
WHERE d NOT CONTAINS 0");
+ assertInvalidMessage("Undefined column name d", "SELECT c AS d FROM %s
WHERE d NOT CONTAINS KEY 0");
assertInvalidMessage("Undefined column name d", "SELECT d FROM %s
WHERE a = 0");
assertInvalidMessage("Undefined column name d", "SELECT d FROM %s
WHERE b BETWEEN 0 AND 0");
}
@@ -695,13 +708,18 @@ public class SelectSingleColumnRelationTest extends
CQLTester
assertInvalidMessage(msg, "SELECT * FROM %s WHERE b <= ?", udt);
assertInvalidMessage(msg, "SELECT * FROM %s WHERE b BETWEEN ? AND ?",
udt, udt);
assertInvalidMessage(msg, "SELECT * FROM %s WHERE b IN (?)", udt);
+ assertInvalidMessage(msg, "SELECT * FROM %s WHERE b NOT IN (?)", udt);
assertInvalidMessage(msg, "SELECT * FROM %s WHERE b LIKE ?", udt);
- assertInvalidMessage("Unsupported '!=' relation: b != {a: 0}",
- "SELECT * FROM %s WHERE b != {a: 0}", udt);
+ assertInvalidMessage(msg, "SELECT * FROM %s WHERE b != {a: 0}", udt);
+ assertInvalidMessage(msg, "SELECT * FROM %s WHERE b != {a: 0}", udt);
assertInvalidMessage("Unsupported restriction: b IS NOT NULL",
"SELECT * FROM %s WHERE b IS NOT NULL", udt);
assertInvalidMessage("Cannot use CONTAINS on non-collection column b",
"SELECT * FROM %s WHERE b CONTAINS ?", udt);
+ assertInvalidMessage("Cannot use NOT CONTAINS on non-collection column
b",
+ "SELECT * FROM %s WHERE b NOT CONTAINS ?", udt);
+ assertInvalidMessage("Cannot use NOT CONTAINS on non-collection column
b",
+ "SELECT * FROM %s WHERE b NOT CONTAINS ?", udt);
}
@Test
@@ -739,7 +757,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testInRestrictionsWithAllowFiltering() throws Throwable
+ public void testInRestrictionsWithAllowFiltering()
{
createTable("CREATE TABLE %s (pk1 int, pk2 int, c text, s int static,
v int, primary key((pk1, pk2), c))");
execute("INSERT INTO %s (pk1, pk2, c, s, v) values (?, ?, ?, ?, ?)",
1, 0, "5", 1, 3);
@@ -792,7 +810,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testInRestrictionsWithAllowFilteringAndOrdering() throws
Throwable
+ public void testInRestrictionsWithAllowFilteringAndOrdering()
{
createTable("CREATE TABLE %s (pk int, c text, v int, primary key(pk,
c)) WITH CLUSTERING ORDER BY (c DESC)");
execute("INSERT INTO %s (pk, c, v) values (?, ?, ?)", 1, "0", 5);
@@ -839,7 +857,7 @@ public class SelectSingleColumnRelationTest extends
CQLTester
}
@Test
- public void testSliceRestrictionWithNegativeClusteringColumnValues()
throws Throwable
+ public void testSliceRestrictionWithNegativeClusteringColumnValues()
{
createTable("CREATE TABLE %s (pk int, c int, v int, PRIMARY KEY (pk,
c))");
@@ -861,4 +879,453 @@ public class SelectSingleColumnRelationTest extends
CQLTester
row(1, -2, -2),
row(1, -1, -1));
}
+
+ @Test
+ public void testClusteringSlicesWithNotIn()
+ {
+ createTable("CREATE TABLE %s (a text, b int, c int, d int, primary
key(a, b, c))");
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 1,
4, 1);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 2,
5, 2);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 2,
6, 3);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 2,
7, 4);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 3,
8, 5);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 3,
9, 6);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 4,
1, 7);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 4,
2, 8);
+
+ // restrict first clustering column by NOT IN
+ assertRows(execute("select * from %s where a = ? and b not in ?",
"key", list(2, 4, 5)),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?,
?)", "key", 2, 4, 5),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+
+ // use different order of items in NOT IN list:
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?,
?)", "key", 5, 2, 4),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?,
?)", "key", 5, 4, 2),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+
+ // restrict last clustering column by NOT IN
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in ?", "key", 2, list(5, 6)),
+ row("key", 2, 7, 4));
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in (?, ?)", "key", 2, 5, 6),
+ row("key", 2, 7, 4));
+
+ // empty NOT IN should have no effect:
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in ?", "key", 2, list()),
+ row("key", 2, 5, 2),
+ row("key", 2, 6, 3),
+ row("key", 2, 7, 4));
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in ()", "key", 2),
+ row("key", 2, 5, 2),
+ row("key", 2, 6, 3),
+ row("key", 2, 7, 4));
+
+ // NOT IN value that doesn't match any data should have no effect:
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in (?)", "key", 2, 0),
+ row("key", 2, 5, 2),
+ row("key", 2, 6, 3),
+ row("key", 2, 7, 4));
+
+ // Duplicate NOT IN values:
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in (?, ?)", "key", 2, 5, 5),
+ row("key", 2, 6, 3),
+ row("key", 2, 7, 4));
+
+ // mix NOT IN and '<' and '<=' comparison on the same column
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
< ?", "key", list(2, 5), 1)); // empty
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
< ?", "key", list(2, 5), 3),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
<= ?", "key", list(2), 2),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
<= ?", "key", list(2), 3),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
<= ?", "key", list(2), 10),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+
+ // mix NOT IN and '>' and '>=' comparison on the same column
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ?", "key", list(2), 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ?", "key", list(2), 2),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ?", "key", list(2), 2),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ?", "key", list(2), 4),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ?", "key", list(2), 0),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+
+ // mix NOT IN and range slice
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b < ?", "key", list(2), 1, 4),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ? and b < ?", "key", list(2), 1, 4),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b <= ?", "key", list(2), 1, 4),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ? and b <= ?", "key", list(2), 1, 4),
+ row("key", 1, 4, 1),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+
+ // Collision between a slice bound and NOT IN value:
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
< ?", "key", list(2), 2),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ?", "key", list(2), 2),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6),
+ row("key", 4, 1, 7),
+ row("key", 4, 2, 8));
+
+ // NOT IN value outside the slice range:
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b < ?", "key", list(0), 2, 4),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b < ?", "key", list(10), 2, 4),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+
+ // multiple NOT IN on the same column, use different ways of passing a
list
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
not in ?", "key", list(1, 2), list(4)),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?)
and b not in (?)", "key", 1, 2, 4),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?)
and b not in ?", "key", 1, 2, list(4)),
+ row("key", 3, 8, 5),
+ row("key", 3, 9, 6));
+
+ // mix IN and NOT IN
+ assertRows(execute("select * from %s where a = ? and b in ? and c not
in ?", "key", list(2, 3), list(5, 6, 9)),
+ row("key", 2, 7, 4),
+ row("key", 3, 8, 5));
+ }
+
+ @Test
+ public void testClusteringSlicesWithNotInAndReverseOrdering()
+ {
+ createTable("CREATE TABLE %s (a text, b int, c int, d int, primary
key(a, b, c)) with clustering order by (b desc, c desc)");
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 1,
4, 1);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 2,
5, 2);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 2,
6, 3);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 2,
7, 4);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 3,
8, 5);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 3,
9, 6);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 4,
1, 7);
+ execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "key", 4,
2, 8);
+
+ // restrict first clustering column by NOT IN
+ assertRows(execute("select * from %s where a = ? and b not in ?",
"key", list(2, 4, 5)),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?,
?)", "key", 2, 4, 5),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5),
+ row("key", 1, 4, 1));
+
+ // restrict last clustering column by NOT IN
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in ?", "key", 2, list(5, 6)),
+ row("key", 2, 7, 4));
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in (?, ?)", "key", 2, 5, 6),
+ row("key", 2, 7, 4));
+
+ // empty NOT IN should have no effect:
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in ?", "key", 2, list()),
+ row("key", 2, 7, 4),
+ row("key", 2, 6, 3),
+ row("key", 2, 5, 2));
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in ()", "key", 2),
+ row("key", 2, 7, 4),
+ row("key", 2, 6, 3),
+ row("key", 2, 5, 2));
+
+ // NOT IN value that doesn't match any data should have no effect:
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in (?)", "key", 2, 0),
+ row("key", 2, 7, 4),
+ row("key", 2, 6, 3),
+ row("key", 2, 5, 2));
+
+ // Duplicate NOT IN values:
+ assertRows(execute("select * from %s where a = ? and b = ? and c not
in (?, ?)", "key", 2, 5, 5),
+ row("key", 2, 7, 4),
+ row("key", 2, 6, 3));
+
+ // mix NOT IN and '<' and '<=' comparison on the same column
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
< ?", "key", list(2, 5), 1)); // empty
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
< ?", "key", list(2, 5), 3),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
<= ?", "key", list(2), 2),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
<= ?", "key", list(2), 3),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
<= ?", "key", list(2), 10),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5),
+ row("key", 1, 4, 1));
+
+ // mix NOT IN and '>' and '>=' comparison on the same column
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ?", "key", list(2), 1),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ?", "key", list(2), 2),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ?", "key", list(2), 2),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ?", "key", list(2), 4),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ?", "key", list(2), 0),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5),
+ row("key", 1, 4, 1));
+
+ // mix NOT IN and range slice
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b < ?", "key", list(2), 1, 4),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ? and b < ?", "key", list(2), 1, 4),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b <= ?", "key", list(2), 1, 4),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
>= ? and b <= ?", "key", list(2), 1, 4),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5),
+ row("key", 1, 4, 1));
+
+ // Collision between a slice bound and NOT IN value:
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
< ?", "key", list(2), 2),
+ row("key", 1, 4, 1));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ?", "key", list(2), 2),
+ row("key", 4, 2, 8),
+ row("key", 4, 1, 7),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+
+ // NOT IN value outside the slice range:
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b < ?", "key", list(0), 2, 4),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
> ? and b < ?", "key", list(10), 2, 4),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+
+ // multiple NOT IN on the same column, use different ways of passing a
list
+ assertRows(execute("select * from %s where a = ? and b not in ? and b
not in ?", "key", list(1, 2), list(4)),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?)
and b not in (?)", "key", 1, 2, 4),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+ assertRows(execute("select * from %s where a = ? and b not in (?, ?)
and b not in ?", "key", 1, 2, list(4)),
+ row("key", 3, 9, 6),
+ row("key", 3, 8, 5));
+
+ // mix IN and NOT IN
+ assertRows(execute("select * from %s where a = ? and b in ? and c not
in ?", "key", list(2, 3), list(5, 6, 9)),
+ row("key", 3, 8, 5),
+ row("key", 2, 7, 4));
+ }
+
+ @Test
+ public void testNotInRestrictionsWithAllowFiltering()
+ {
+ createTable("CREATE TABLE %s (pk int, c int, v int, primary key(pk,
c))");
+ execute("insert into %s (pk, c, v) values (?, ?, ?)", 1, 1, 1);
+ execute("insert into %s (pk, c, v) values (?, ?, ?)", 1, 2, 2);
+ execute("insert into %s (pk, c, v) values (?, ?, ?)", 1, 3, 3);
+ execute("insert into %s (pk, c, v) values (?, ?, ?)", 1, 4, 4);
+ execute("insert into %s (pk, c, v) values (?, ?, ?)", 1, 5, 5);
+
+ // empty NOT IN set
+ assertRows(execute("select * from %s where pk = ? and v not in ? allow
filtering", 1, list()),
+ row(1, 1, 1),
+ row(1, 2, 2),
+ row(1, 3, 3),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ assertRows(execute("select * from %s where pk = ? and v not in ()
allow filtering", 1),
+ row(1, 1, 1),
+ row(1, 2, 2),
+ row(1, 3, 3),
+ row(1, 4, 4),
+ row(1, 5, 5));
+
+ // NOT IN with values that don't match any data
+ assertRows(execute("select * from %s where pk = ? and v not in (?, ?)
allow filtering", 1, -6, 20),
+ row(1, 1, 1),
+ row(1, 2, 2),
+ row(1, 3, 3),
+ row(1, 4, 4),
+ row(1, 5, 5));
+
+ // NOT IN that excludes a few values
+ assertRows(execute("select * from %s where pk = ? and v not in ? allow
filtering", 1, list(2, 3)),
+ row(1, 1, 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ assertRows(execute("select * from %s where pk = ? and v not in (?, ?)
allow filtering", 1, 2, 3),
+ row(1, 1, 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+
+ // NOT IN with one-sided slice filters:
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
< ? allow filtering", 1, list(2, 3), 5),
+ row(1, 1, 1),
+ row(1, 4, 4));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
< ? allow filtering", 1, list(2, 3, 10), 5),
+ row(1, 1, 1),
+ row(1, 4, 4));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
<= ? allow filtering", 1, list(2, 3), 5),
+ row(1, 1, 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
<= ? allow filtering", 1, list(2, 3, 10), 5),
+ row(1, 1, 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
> ? allow filtering", 1, list(2, 3), 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
> ? allow filtering", 1, list(0, 2, 3), 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
>= ? allow filtering", 1, list(2, 3), 1),
+ row(1, 1, 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
>= ? allow filtering", 1, list(0, 2, 3), 1),
+ row(1, 1, 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+
+ // NOT IN with range filters:
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
> ? and v < ? allow filtering", 1, list(2, 3), 1, 4)); // empty
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
> ? and v < ? allow filtering", 1, list(2, 3), 1, 4)); // empty
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
> ? and v < ? allow filtering", 1, list(2, 3), 0, 5),
+ row(1, 1, 1),
+ row(1, 4, 4));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
>= ? and v < ? allow filtering", 1, list(2, 3), 1, 4),
+ row(1, 1, 1));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
> ? and v <= ? allow filtering", 1, list(2, 3), 1, 4),
+ row(1, 4, 4));
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
>= ? and v <= ? allow filtering", 1, list(2, 3), 1, 4),
+ row(1, 1, 1),
+ row(1, 4, 4));
+
+ // more than one NOT IN clause
+ assertRows(execute("select * from %s where pk = ? and v not in ? and v
not in ? allow filtering", 1, list(2), list(3)),
+ row(1, 1, 1),
+ row(1, 4, 4),
+ row(1, 5, 5));
+ }
+
+ @Test
+ public void testNonEqualsRelationWithFiltering()
+ {
+ createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a,
b))");
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 0, 0);
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 1, 1);
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 2, 2);
+ execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, 3, 3);
+
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? ALLOW
FILTERING", 0, 0),
+ row(0, 1),
+ row(0, 2),
+ row(0, 3)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? ALLOW
FILTERING", 0, 1),
+ row(0, 0),
+ row(0, 2),
+ row(0, 3)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? ALLOW
FILTERING", 0, -1),
+ row(0, 0),
+ row(0, 1),
+ row(0, 2),
+ row(0, 3)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? ALLOW
FILTERING", 0, 5),
+ row(0, 0),
+ row(0, 1),
+ row(0, 2),
+ row(0, 3)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? AND c
!= ? ALLOW FILTERING", 0, 1, 2),
+ row(0, 0),
+ row(0, 3)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? AND c <
? ALLOW FILTERING", 0, 1, 2),
+ row(0, 0)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? AND c
<= ? ALLOW FILTERING", 0, 1, 2),
+ row(0, 0),
+ row(0, 2)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? AND c >
? ALLOW FILTERING", 0, 2, 0),
+ row(0, 1),
+ row(0, 3)
+ );
+ assertRows(execute("SELECT a, b FROM %s WHERE a = ? AND c != ? AND c
>= ? ALLOW FILTERING", 0, 2, 1),
+ row(0, 1),
+ row(0, 3)
+ );
+ }
}
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 b21944fc7d..5bdff0f831 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
@@ -32,10 +32,9 @@ import
org.apache.cassandra.cql3.restrictions.StatementRestrictions;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.index.internal.CassandraIndex;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.apache.cassandra.utils.ByteBufferUtil.EMPTY_BYTE_BUFFER;
import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
+import static org.junit.Assert.*;
/**
@@ -301,7 +300,7 @@ public class SelectTest extends CQLTester
* migrated from cql_tests.py:TestCQL.select_key_in_test()
*/
@Test
- public void testSelectKeyIn() throws Throwable
+ public void testSelectKeyIn()
{
createTable("CREATE TABLE %s (userid uuid PRIMARY KEY, firstname text,
lastname text, age int)");
@@ -635,7 +634,7 @@ public class SelectTest extends CQLTester
* migrated from cql_tests.py:TestCQL.token_range_test()
*/
@Test
- public void testTokenRange() throws Throwable
+ public void testTokenRange()
{
createTable(" CREATE TABLE %s (k int PRIMARY KEY, c int, v int)");
@@ -668,7 +667,7 @@ public class SelectTest extends CQLTester
* migrated from cql_tests.py:TestCQL.count_test()
*/
@Test
- public void testSelectCount() throws Throwable
+ public void testSelectCount()
{
createTable(" CREATE TABLE %s (kind text, time int, value1 int, value2
int, PRIMARY KEY(kind, time))");
@@ -691,7 +690,7 @@ public class SelectTest extends CQLTester
* migrated from cql_tests.py:TestCQL.range_query_test()
*/
@Test
- public void testRangeQuery() throws Throwable
+ public void testRangeQuery()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, f
text, PRIMARY KEY (a, b, c, d, e) )");
@@ -765,7 +764,7 @@ public class SelectTest extends CQLTester
* Migrated from cql_tests.py:TestCQL.bug_4882_test()
*/
@Test
- public void testDifferentOrdering() throws Throwable
+ public void testDifferentOrdering()
{
createTable(" CREATE TABLE %s ( k int, c1 int, c2 int, v int, PRIMARY
KEY (k, c1, c2) ) WITH CLUSTERING ORDER BY (c1 ASC, c2 DESC)");
@@ -910,7 +909,7 @@ public class SelectTest extends CQLTester
* Migrated from cql_tests.py:TestCQL.ticket_5230_test()
*/
@Test
- public void testMultipleClausesOnPrimaryKey() throws Throwable
+ public void testMultipleClausesOnPrimaryKey()
{
createTable("CREATE TABLE %s (key text, c text, v text, PRIMARY
KEY(key, c))");
@@ -930,7 +929,7 @@ public class SelectTest extends CQLTester
{
createTable("CREATE TABLE %s (key text PRIMARY KEY)");
- // We just want to make sure this doesn 't NPE server side
+ // We just want to make sure this doesn't NPE server side
assertInvalid("select * from %s where token(key) >
token(int(3030343330393233)) limit 1");
}
@@ -938,7 +937,7 @@ public class SelectTest extends CQLTester
* Migrated from cql_tests.py:TestCQL.clustering_order_and_functions_test()
*/
@Test
- public void testFunctionsWithClusteringDesc() throws Throwable
+ public void testFunctionsWithClusteringDesc()
{
createTable("CREATE TABLE %s ( k int, t timeuuid, PRIMARY KEY (k, t) )
WITH CLUSTERING ORDER BY (t DESC)");
@@ -1026,7 +1025,7 @@ public class SelectTest extends CQLTester
* Migrated from cql_tests.py:TestCQL.select_distinct_with_deletions_test()
*/
@Test
- public void testSelectDistinctWithDeletions() throws Throwable
+ public void testSelectDistinctWithDeletions()
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, c int, v int)");
@@ -1127,7 +1126,7 @@ public class SelectTest extends CQLTester
* Migrated from cql_tests.py:TestCQL.bug_6327_test()
*/
@Test
- public void testSelectInClauseAtOne() throws Throwable
+ public void testSelectInClauseAtOne()
{
createTable("CREATE TABLE %s ( k int, v int, PRIMARY KEY (k, v))");
@@ -1144,7 +1143,7 @@ public class SelectTest extends CQLTester
* migrated from cql_tests.py:TestCQL.select_count_paging_test()
*/
@Test
- public void testSelectCountPaging() throws Throwable
+ public void testSelectCountPaging()
{
createTable("create table %s (field1 text, field2 timeuuid, field3
boolean, primary key(field1, field2))");
createIndex("create index on %s (field3)");
@@ -1161,7 +1160,7 @@ public class SelectTest extends CQLTester
* migrated from cql_tests.py:TestCQL.clustering_order_in_test()
*/
@Test
- public void testClusteringOrder() throws Throwable
+ public void testClusteringOrder()
{
createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY ((a,
b), c) ) with clustering order by (c desc)");
@@ -1180,7 +1179,7 @@ public class SelectTest extends CQLTester
* migrated from cql_tests.py:TestCQL.bug7105_test()
*/
@Test
- public void testSelectInFinalColumn() throws Throwable
+ public void testSelectInFinalColumn()
{
createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY
(a, b))");
@@ -1380,17 +1379,34 @@ public class SelectTest extends CQLTester
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE c CONTAINS 2");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE c NOT CONTAINS 2");
+
assertRows(execute("SELECT * FROM %s WHERE c CONTAINS 2 ALLOW
FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
assertRows(execute("SELECT * FROM %s WHERE c CONTAINS 2 AND c
CONTAINS 3 ALLOW FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE c NOT CONTAINS 2 ALLOW
FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)),
+ row(2, 3, list(3, 6), set(6, 12), map(3, 6)));
+
+ assertRows(execute("SELECT * FROM %s WHERE c NOT CONTAINS 2 AND c
NOT CONTAINS 3 ALLOW FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+
+ assertRows(execute("SELECT * FROM %s WHERE c CONTAINS 2 AND c NOT
CONTAINS 3 ALLOW FILTERING"),
+ row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
// Checks filtering for sets
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE d CONTAINS 4");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE d NOT CONTAINS 4");
+
assertRows(execute("SELECT * FROM %s WHERE d CONTAINS 4 ALLOW
FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
@@ -1398,26 +1414,71 @@ public class SelectTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE d CONTAINS 4 AND d
CONTAINS 6 ALLOW FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE d NOT CONTAINS 4 ALLOW
FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)),
+ row(2, 3, list(3, 6), set(6, 12), map(3, 6)));
+
+ assertRows(execute("SELECT * FROM %s WHERE d NOT CONTAINS 4 AND d
NOT CONTAINS 6 ALLOW FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+
+ assertRows(execute("SELECT * FROM %s WHERE d CONTAINS 4 AND d NOT
CONTAINS 6 ALLOW FILTERING"),
+ row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
// Checks filtering for maps
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE e CONTAINS 2");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE e NOT CONTAINS 2");
+
assertRows(execute("SELECT * FROM %s WHERE e CONTAINS 2 ALLOW
FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE e NOT CONTAINS 2 ALLOW
FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)),
+ row(2, 3, list(3, 6), set(6, 12), map(3, 6)));
+
assertRows(execute("SELECT * FROM %s WHERE e CONTAINS KEY 1 ALLOW
FILTERING"),
row(1, 2, list(1, 6), set(2, 12), map(1, 6)),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE e NOT CONTAINS KEY 1
ALLOW FILTERING"),
+ row(1, 3, list(3, 2), set(6, 4), map(3, 2)),
+ row(2, 3, list(3, 6), set(6, 12), map(3, 6)));
+
+ assertRows(execute("SELECT * FROM %s WHERE e CONTAINS 2 AND e NOT
CONTAINS KEY 1 ALLOW FILTERING"),
+ row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+
assertRows(execute("SELECT * FROM %s WHERE e[1] = 6 ALLOW
FILTERING"),
row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+ execute("INSERT INTO %s (a, b, c, d, e) VALUES (1, 2, [1, 6], {2,
12}, {1: 6})");
+ execute("INSERT INTO %s (a, b, c, d, e) VALUES (1, 3, [3, 2], {6,
4}, {3: 2})");
+ execute("INSERT INTO %s (a, b, c, d, e) VALUES (1, 4, [1, 2], {2,
4}, {1: 2})");
+ execute("INSERT INTO %s (a, b, c, d, e) VALUES (2, 3, [3, 6], {6,
12}, {3: 6})");
+
+ assertRows(execute("SELECT * FROM %s WHERE e[1] != 6 ALLOW
FILTERING"),
+ row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE e[1] != 6 AND e[3] !=
2 ALLOW FILTERING"));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE e[1] = 6 AND e[3] = 2
ALLOW FILTERING"));
+
+ assertRows(execute("SELECT * FROM %s WHERE e CONTAINS KEY 1 AND
e[1] != 6 ALLOW FILTERING"),
+ row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
assertRows(execute("SELECT * FROM %s WHERE e CONTAINS KEY 1 AND e
CONTAINS 2 ALLOW FILTERING"),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE e CONTAINS KEY 1 AND e
NOT CONTAINS 2 ALLOW FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+
assertRows(execute("SELECT * FROM %s WHERE c CONTAINS 2 AND d
CONTAINS 4 AND e CONTAINS KEY 3 ALLOW FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+
+ assertRows(execute("SELECT * FROM %s WHERE c CONTAINS 2 AND d
CONTAINS 4 AND e NOT CONTAINS KEY 1 ALLOW FILTERING"),
+ row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
});
// Checks filtering with null
@@ -1434,6 +1495,19 @@ public class SelectTest extends CQLTester
assertInvalidMessage("Invalid null value for e[1]",
"SELECT * FROM %s WHERE e[1] = null ALLOW
FILTERING");
+ assertInvalidMessage("Invalid null value for column c",
+ "SELECT * FROM %s WHERE c NOT CONTAINS null ALLOW
FILTERING");
+ assertInvalidMessage("Invalid null value for column d",
+ "SELECT * FROM %s WHERE d NOT CONTAINS null ALLOW
FILTERING");
+ assertInvalidMessage("Invalid null value for column e",
+ "SELECT * FROM %s WHERE e NOT CONTAINS null ALLOW
FILTERING");
+ assertInvalidMessage("Invalid null value for column e",
+ "SELECT * FROM %s WHERE e NOT CONTAINS KEY null
ALLOW FILTERING");
+ assertInvalidMessage("Invalid null map key for column e",
+ "SELECT * FROM %s WHERE e[null] != 2 ALLOW
FILTERING");
+ assertInvalidMessage("Invalid null value for e[1]",
+ "SELECT * FROM %s WHERE e[1] != null ALLOW
FILTERING");
+
// Checks filtering with unset
assertInvalidMessage("Invalid unset value for column c",
"SELECT * FROM %s WHERE c CONTAINS ? ALLOW
FILTERING",
@@ -1453,6 +1527,25 @@ public class SelectTest extends CQLTester
assertInvalidMessage("Invalid unset value for e[1]",
"SELECT * FROM %s WHERE e[1] = ? ALLOW FILTERING",
unset());
+
+ assertInvalidMessage("Invalid unset value for column c",
+ "SELECT * FROM %s WHERE c NOT CONTAINS ? ALLOW
FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for column d",
+ "SELECT * FROM %s WHERE d NOT CONTAINS ? ALLOW
FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for column e",
+ "SELECT * FROM %s WHERE e NOT CONTAINS ? ALLOW
FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for column e",
+ "SELECT * FROM %s WHERE e NOT CONTAINS KEY ?
ALLOW FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset map key for column e",
+ "SELECT * FROM %s WHERE e[?] != 2 ALLOW
FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for e[1]",
+ "SELECT * FROM %s WHERE e[1] != ? ALLOW
FILTERING",
+ unset());
}
@Test
@@ -1554,6 +1647,9 @@ public class SelectTest extends CQLTester
assertInvalidMessage("Map-entry predicates on frozen map column e
are not supported",
"SELECT * FROM %s WHERE e[1] = 6 ALLOW
FILTERING");
+ assertInvalidMessage("Map-entry predicates on frozen map column e
are not supported",
+ "SELECT * FROM %s WHERE e[1] != 6 ALLOW
FILTERING");
+
assertRows(execute("SELECT * FROM %s WHERE e CONTAINS KEY 1 AND e
CONTAINS 2 ALLOW FILTERING"),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
@@ -1639,7 +1735,7 @@ public class SelectTest extends CQLTester
}
@Test
- public void testCKQueryWithValueOver64K() throws Throwable
+ public void testCKQueryWithValueOver64K()
{
createTable("CREATE TABLE %s (a text, b text, PRIMARY KEY (a, b))");
@@ -1922,42 +2018,80 @@ public class SelectTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE b >= 4 AND c CONTAINS 2
ALLOW FILTERING"),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE b < 0 AND c NOT
CONTAINS 2");
+
assertRows(
execute("SELECT * FROM %s WHERE a > 0 AND b <= 3 AND c
CONTAINS 2 AND c CONTAINS 3 ALLOW FILTERING"),
- row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+ row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+
+ assertRows(
+ execute("SELECT * FROM %s WHERE a > 0 AND b <= 3 AND c NOT
CONTAINS 1 AND c NOT CONTAINS 6 ALLOW FILTERING"),
+ row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
// Checks filtering for sets
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE a = 1 AND d CONTAINS 4");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE a = 1 AND d NOT CONTAINS 4");
+
assertRows(execute("SELECT * FROM %s WHERE d CONTAINS 4 ALLOW
FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE d NOT CONTAINS 4 ALLOW
FILTERING"),
+ row(2, 3, list(3, 6), set(6, 12), map(3, 6)),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+
assertRows(execute("SELECT * FROM %s WHERE d CONTAINS 4 AND d
CONTAINS 6 ALLOW FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE d NOT CONTAINS 4 AND d
NOT CONTAINS 6 ALLOW FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+
// Checks filtering for maps
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE e CONTAINS 2");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE e NOT CONTAINS 2");
+
assertRows(execute("SELECT * FROM %s WHERE a < 2 AND b >= 3 AND e
CONTAINS 2 ALLOW FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE a < 2 AND b >= 3 AND e
NOT CONTAINS 6 ALLOW FILTERING"),
+ row(1, 3, list(3, 2), set(6, 4), map(3, 2)),
+ row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
assertRows(execute("SELECT * FROM %s WHERE a = 1 AND e CONTAINS
KEY 1 ALLOW FILTERING"),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)),
row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+ assertRows(execute("SELECT * FROM %s WHERE a = 1 AND e NOT
CONTAINS KEY 3 ALLOW FILTERING"),
+ row(1, 4, list(1, 2), set(2, 4), map(1, 2)),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+
assertRows(execute("SELECT * FROM %s WHERE a in (1) AND b in (2)
AND e[1] = 6 ALLOW FILTERING"),
row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+ assertRows(execute("SELECT * FROM %s WHERE a in (1) AND b in (2)
AND e[1] != 2 ALLOW FILTERING"),
+ row(1, 2, list(1, 6), set(2, 12), map(1, 6)));
+
assertRows(execute("SELECT * FROM %s WHERE a = 1 AND e CONTAINS
KEY 1 AND e CONTAINS 2 ALLOW FILTERING"),
row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+ assertRows(execute("SELECT * FROM %s WHERE a = 1 AND e CONTAINS
KEY 1 AND e NOT CONTAINS 6 ALLOW FILTERING"),
+ row(1, 4, list(1, 2), set(2, 4), map(1, 2)));
+
assertRows(
execute("SELECT * FROM %s WHERE a >= 1 AND b in (3) AND c
CONTAINS 2 AND d CONTAINS 4 AND e CONTAINS KEY 3 ALLOW FILTERING"),
row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
+
+ assertRows(
+ execute("SELECT * FROM %s WHERE a >= 1 AND b in (3) AND c
CONTAINS 2 AND d CONTAINS 4 AND e NOT CONTAINS KEY 1 ALLOW FILTERING"),
+ row(1, 3, list(3, 2), set(6, 4), map(3, 2)));
});
// Checks filtering with null
@@ -1973,6 +2107,19 @@ public class SelectTest extends CQLTester
"SELECT * FROM %s WHERE a >= 1 AND b < 1 AND
e[null] = 2 ALLOW FILTERING");
assertInvalidMessage("Invalid null value for e[1]",
"SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e[1]
= null ALLOW FILTERING");
+ assertInvalidMessage("Invalid null value for column c",
+ "SELECT * FROM %s WHERE a > 1 AND c NOT CONTAINS
null ALLOW FILTERING");
+ assertInvalidMessage("Invalid null value for column d",
+ "SELECT * FROM %s WHERE b < 1 AND d NOT CONTAINS
null ALLOW FILTERING");
+ assertInvalidMessage("Invalid null value for column e",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e
NOT CONTAINS null ALLOW FILTERING");
+ assertInvalidMessage("Invalid null value for column e",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e
NOT CONTAINS KEY null ALLOW FILTERING");
+ assertInvalidMessage("Invalid null map key for column e",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND
e[null] != 2 ALLOW FILTERING");
+ assertInvalidMessage("Invalid null value for e[1]",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e[1]
!= null ALLOW FILTERING");
+
// Checks filtering with unset
assertInvalidMessage("Invalid unset value for column c",
@@ -1993,6 +2140,24 @@ public class SelectTest extends CQLTester
assertInvalidMessage("Invalid unset value for e[1]",
"SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e[1]
= ? ALLOW FILTERING",
unset());
+ assertInvalidMessage("Invalid unset value for column c",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND c
NOT CONTAINS ? ALLOW FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for column d",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND d
NOT CONTAINS ? ALLOW FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for column e",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e
NOT CONTAINS ? ALLOW FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for column e",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e
NOT CONTAINS KEY ? ALLOW FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset map key for column e",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e[?]
!= 2 ALLOW FILTERING",
+ unset());
+ assertInvalidMessage("Invalid unset value for e[1]",
+ "SELECT * FROM %s WHERE a >= 1 AND b < 1 AND e[1]
!= ? ALLOW FILTERING",
+ unset());
}
@Test
@@ -2157,12 +2322,26 @@ public class SelectTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE a = 21 AND b CONTAINS 2
ALLOW FILTERING"),
row(21, list(2, 3), 24));
+
+ assertRows(execute("SELECT * FROM %s WHERE a = 21 AND b NOT
CONTAINS 2 ALLOW FILTERING"),
+ row(21, list(3, 3), 34));
+
assertInvalidMessage("Clustering column restrictions require the
use of secondary indices" +
" or filtering for map-element restrictions
and for the following operators: CONTAINS, CONTAINS KEY, LIKE, ANN",
"SELECT * FROM %s WHERE a = 21 AND b CONTAINS
2");
+ assertInvalidMessage("Clustering column restrictions require the
use of secondary indices or " +
+ "filtering for map-element restrictions and
for the following operators: CONTAINS, " +
+ "CONTAINS KEY, LIKE, ANN, NOT CONTAINS, NOT
CONTAINS KEY",
+ "SELECT * FROM %s WHERE b NOT CONTAINS 2");
+
assertRows(execute("SELECT * FROM %s WHERE b CONTAINS 2 ALLOW
FILTERING"),
row(21, list(2, 3), 24));
+
+ assertRows(execute("SELECT * FROM %s WHERE b NOT CONTAINS 2 ALLOW
FILTERING"),
+ row(11, list(1, 3), 14),
+ row(21, list(3, 3), 34));
+
assertInvalidMessage("Clustering column restrictions require the
use of secondary indices" +
" or filtering for map-element restrictions
and for the following operators: CONTAINS, CONTAINS KEY, LIKE, ANN",
"SELECT * FROM %s WHERE b CONTAINS 2");
@@ -2171,6 +2350,8 @@ public class SelectTest extends CQLTester
row(11, list(1, 3), 14),
row(21, list(2, 3), 24),
row(21, list(3, 3), 34));
+
+ assertRows(execute("SELECT * FROM %s WHERE b NOT CONTAINS 3 ALLOW
FILTERING"));
});
// non-first clustering column
@@ -2184,12 +2365,28 @@ public class SelectTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE a = 21 AND c CONTAINS 2
ALLOW FILTERING"),
row(21, 22, list(2, 3), 24));
+
+ assertRows(execute("SELECT * FROM %s WHERE a = 21 AND c NOT
CONTAINS 2 ALLOW FILTERING"),
+ row(21, 22, list(3, 3), 34));
+
assertInvalidMessage("Clustering column restrictions require the
use of secondary indices" +
" or filtering for map-element restrictions
and for the following operators: CONTAINS, CONTAINS KEY, LIKE, ANN",
"SELECT * FROM %s WHERE a = 21 AND c CONTAINS
2");
+ assertInvalidMessage("Clustering column restrictions require the
use of secondary indices or filtering" +
+ " for map-element restrictions and for the
following operators: CONTAINS, CONTAINS KEY, LIKE, " +
+ "ANN, NOT CONTAINS, NOT CONTAINS KEY",
+ "SELECT * FROM %s WHERE a = 21 AND c NOT
CONTAINS 2");
+
assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c CONTAINS 2
ALLOW FILTERING"),
row(21, 22, list(2, 3), 24));
+
+ assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c NOT
CONTAINS 2 ALLOW FILTERING"),
+ row(21, 22, list(3, 3), 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 NOT
CONTAINS 2");
+
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");
@@ -2197,6 +2394,8 @@ public class SelectTest extends CQLTester
row(11, 12, list(1, 3), 14),
row(21, 22, list(2, 3), 24),
row(21, 22, list(3, 3), 34));
+
+ assertEmpty(execute("SELECT * FROM %s WHERE c NOT CONTAINS 3 ALLOW
FILTERING"));
});
createTable("CREATE TABLE %s (a int, b int, c frozen<map<text, text>>,
d int, PRIMARY KEY (a, b, c))");
@@ -2208,8 +2407,15 @@ public class SelectTest extends CQLTester
beforeAndAfterFlush(() -> {
assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c CONTAINS
KEY '2' ALLOW FILTERING"),
row(21, 22, map("2", "3"), 24));
+
+ assertRows(execute("SELECT * FROM %s WHERE b > 20 AND c NOT
CONTAINS KEY '2' ALLOW FILTERING"),
+ row(21, 22, map("3", "3"), 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 CONTAINS
KEY '2'");
+
+ 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 NOT
CONTAINS KEY '2'");
});
}
@@ -2241,6 +2447,9 @@ public class SelectTest extends CQLTester
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT * FROM %s WHERE pk CONTAINS KEY 1");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
+ "SELECT * FROM %s WHERE pk NOT CONTAINS KEY 1");
+
beforeAndAfterFlush(() -> {
assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk
CONTAINS KEY 1 ALLOW FILTERING"),
row(map(1, 2), 1, 1),
@@ -2262,6 +2471,23 @@ public class SelectTest extends CQLTester
assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk
CONTAINS KEY 1 AND ck = 1 AND v = 3 ALLOW FILTERING"),
row(map(1, 2, 3, 4), 1, 3));
+
+ assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk NOT
CONTAINS KEY 1 ALLOW FILTERING"),
+ row(map(5, 6), 5, 5),
+ row(map(7, 8), 6, 6));
+
+ assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk
CONTAINS KEY 1 AND pk NOT CONTAINS 4 ALLOW FILTERING"),
+ row(map(1, 2), 1, 1),
+ row(map(1, 2), 2, 2));
+
+ assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk NOT
CONTAINS KEY 1 AND pk CONTAINS 8 ALLOW FILTERING"),
+ row(map(7, 8), 6, 6));
+
+ assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk NOT
CONTAINS KEY 1 AND pk NOT CONTAINS 8 ALLOW FILTERING"),
+ row(map(5, 6), 5, 5));
+
+ assertRowsIgnoringOrder(execute("SELECT * FROM %s WHERE pk NOT
CONTAINS KEY 1 AND v = 5 ALLOW FILTERING"),
+ row(map(5, 6), 5, 5));
});
}
@@ -2343,8 +2569,16 @@ public class SelectTest extends CQLTester
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"),
+ assertRows(executeFilteringOnly("SELECT a, b, c, d FROM %s WHERE b
> 20 AND d NOT CONTAINS 2"),
+ row(31, 32, 33, list(3, 4)));
+
+ 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)));
+
+ assertRows(executeFilteringOnly("SELECT a, b, c, d FROM %s WHERE b
> 20 AND d NOT CONTAINS 2 AND d CONTAINS 4"),
+ row(31, 32, 33, list(3, 4)));
+
+ assertRows(executeFilteringOnly("SELECT a, b, c, d FROM %s WHERE b
> 20 AND d NOT CONTAINS 2 AND d NOT CONTAINS 4"));
});
}
@@ -2413,7 +2647,7 @@ public class SelectTest extends CQLTester
* Check select with ith different column order. See CASSANDRA-10988
*/
@Test
- public void testClusteringOrderWithSlice() throws Throwable
+ public void testClusteringOrderWithSlice()
{
// non-compound, ASC order
createTable("CREATE TABLE %s (a text, b int, PRIMARY KEY (a, b)) WITH
CLUSTERING ORDER BY (b ASC)");
@@ -2844,7 +3078,7 @@ public class SelectTest extends CQLTester
}
@Test
- public void testWithDistinctAndJsonAsColumnName() throws Throwable
+ public void testWithDistinctAndJsonAsColumnName()
{
createTable("CREATE TABLE %s (distinct int, json int, value int,
PRIMARY KEY(distinct, json))");
execute("INSERT INTO %s (distinct, json, value) VALUES (0, 0, 0)");
@@ -2947,6 +3181,9 @@ public class SelectTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE m IN ({1:1s, 2:2s},
{1:1s, 3:3s}) ALLOW FILTERING"),
row(0, map(1, Duration.from("1s"), 2,
Duration.from("2s"))),
row(2, map(1, Duration.from("1s"), 3,
Duration.from("3s"))));
+
+ assertRows(execute("SELECT * FROM %s WHERE m NOT CONTAINS 1s
ALLOW FILTERING"),
+ row(1, map(2, Duration.from("2s"), 3,
Duration.from("3s"))));
}
else
{
@@ -3066,30 +3303,41 @@ public class SelectTest extends CQLTester
beforeAndAfterFlush(() -> {
// lists
assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 1 ALLOW
FILTERING"), row(1, 0), row(0, 0), row(0, 2));
+ assertRows(execute("SELECT k, v FROM %s WHERE l NOT CONTAINS 4
ALLOW FILTERING"), row(0, 0), row(0, 2));
assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND l CONTAINS
1 ALLOW FILTERING"), row(0, 0), row(0, 2));
+ assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND l NOT
CONTAINS 4 ALLOW FILTERING"), row(0, 0), row(0, 2));
assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 2 ALLOW
FILTERING"), row(1, 0), row(0, 0));
assertEmpty(execute("SELECT k, v FROM %s WHERE l CONTAINS 6 ALLOW
FILTERING"));
// sets
assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'a' ALLOW
FILTERING" ), row(0, 0), row(0, 2));
+ assertRowsIgnoringOrder(execute("SELECT k, v FROM %s WHERE s NOT
CONTAINS 'a' ALLOW FILTERING" ), row(0, 1), row(1, 1));
assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND s CONTAINS
'a' ALLOW FILTERING"), row(0, 0), row(0, 2));
+ assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND s NOT
CONTAINS 'a' ALLOW FILTERING" ), row(0, 1));
assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'd' ALLOW
FILTERING"), row(1, 1));
assertEmpty(execute("SELECT k, v FROM %s WHERE s CONTAINS 'e'
ALLOW FILTERING"));
+ assertRows(execute("SELECT k, v FROM %s WHERE s NOT CONTAINS 'a'
AND s NOT CONTAINS 'c' ALLOW FILTERING"), row(1, 1));
// maps
assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 1 ALLOW
FILTERING"), row(1, 0), row(1, 1), row(0, 0), row(0, 1));
+ assertRows(execute("SELECT k, v FROM %s WHERE m NOT CONTAINS 1
ALLOW FILTERING"), row(0, 2));
assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS
1 ALLOW FILTERING"), row(0, 0), row(0, 1));
+ assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m NOT
CONTAINS 1 ALLOW FILTERING"), row(0, 2));
assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 2 ALLOW
FILTERING"), row(0, 1));
assertEmpty(execute("SELECT k, v FROM %s WHERE m CONTAINS 4 ALLOW
FILTERING"));
+ assertEmpty(execute("SELECT k, v FROM %s WHERE m NOT CONTAINS 1
AND m NOT CONTAINS 3 ALLOW FILTERING"));
assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS KEY 'a'
ALLOW FILTERING"), row(1, 1), row(0, 0), row(0, 1));
+ assertRows(execute("SELECT k, v FROM %s WHERE m NOT CONTAINS KEY
'a' ALLOW FILTERING"), row(1, 0), row(0, 2));
assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS
KEY 'a' ALLOW FILTERING"), row(0, 0), row(0, 1));
+ assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m NOT
CONTAINS KEY 'a' ALLOW FILTERING"), row(0, 2));
assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS
KEY 'c' ALLOW FILTERING"), row(0, 2));
+ assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m NOT
CONTAINS KEY 'c' ALLOW FILTERING"), row(0, 0), row(0, 1));
});
}
@Test
- public void testMixedTTLOnColumns() throws Throwable
+ public void testMixedTTLOnColumns()
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, i int)");
execute("INSERT INTO %s (k) VALUES (2);");
@@ -3108,14 +3356,14 @@ public class SelectTest extends CQLTester
if ( i % 2 == 0) // Every odd row has a null i/ttl
assertTrue(row.getInt("name_ttl") >= 90 &&
row.getInt("name_ttl") <= 100);
else
- assertTrue(row.has("name_ttl") == false);
+ assertFalse(row.has("name_ttl"));
i++;
}
}
@Test
- public void testMixedTTLOnColumnsWide() throws Throwable
+ public void testMixedTTLOnColumnsWide()
{
createTable("CREATE TABLE %s (k int, c int, i int, PRIMARY KEY (k,
c))");
execute("INSERT INTO %s (k, c) VALUES (2, 2);");
@@ -3138,14 +3386,14 @@ public class SelectTest extends CQLTester
if ( i % 2 == 0) // Every odd row has a null i/ttl
assertTrue(row.getInt("name_ttl") >= 90 &&
row.getInt("name_ttl") <= 100);
else
- assertTrue(row.has("name_ttl") == false);
+ assertFalse(row.has("name_ttl"));
i++;
}
}
@Test // CASSANDRA-14989
- public void testTokenFctAcceptsValidArguments() throws Throwable
+ public void testTokenFctAcceptsValidArguments()
{
createTable("CREATE TABLE %s (k1 uuid, k2 text, PRIMARY KEY ((k1,
k2)))");
execute("INSERT INTO %s (k1, k2) VALUES (uuid(), 'k2')");
@@ -3219,7 +3467,7 @@ public class SelectTest extends CQLTester
}
@Test
- public void testQuotedMapTextData() throws Throwable
+ public void testQuotedMapTextData()
{
createTable("CREATE TABLE " + KEYSPACE + ".t1 (id int, data text,
PRIMARY KEY (id))");
createTable("CREATE TABLE " + KEYSPACE + ".t2 (id int, data map<int,
text>, PRIMARY KEY (id))");
@@ -3232,7 +3480,7 @@ public class SelectTest extends CQLTester
}
@Test
- public void testQuotedSimpleCollectionsData() throws Throwable
+ public void testQuotedSimpleCollectionsData()
{
createTable("CREATE TABLE " + KEYSPACE + ".t3 (id int, set_data
set<text>, list_data list<text>, tuple_data tuple<int, text>, PRIMARY KEY
(id))");
@@ -3244,7 +3492,7 @@ public class SelectTest extends CQLTester
}
@Test
- public void testQuotedUDTData() throws Throwable
+ public void testQuotedUDTData()
{
createType("CREATE TYPE " + KEYSPACE + ".random (data text)");
createTable("CREATE TABLE " + KEYSPACE + ".t4 (id int, udt_data
frozen<random>, PRIMARY KEY (id))");
@@ -3268,12 +3516,12 @@ public class SelectTest extends CQLTester
assertInvalidMessage("Collection column 'm' (map<text, text>) cannot
be restricted by a '>' relation",
"SELECT * FROM %s WHERE m > {'lmn' : 'f'} AND
m['lmn'] = 'foo2'");
- assertInvalidMessage("Collection column fm can only be restricted by
CONTAINS, CONTAINS KEY," +
- " or map-entry equality if it already restricted
by one of those",
+ assertInvalidMessage("Collection column fm can only be restricted by
CONTAINS, CONTAINS KEY, NOT_CONTAINS, " +
+ "NOT_CONTAINS_KEY or map-entry equality if it
already restricted by one of those",
"SELECT * FROM %s WHERE fm > {'lmn' : 'f'} AND fm
CONTAINS 'foo'");
- assertInvalidMessage("Collection column fm can only be restricted by
CONTAINS, CONTAINS KEY," +
- " or map-entry equality if it already restricted
by one of those",
+ assertInvalidMessage("Collection column fm can only be restricted by
CONTAINS, CONTAINS KEY, NOT_CONTAINS, " +
+ "NOT_CONTAINS_KEY or map-entry equality if it
already restricted by one of those",
"SELECT * FROM %s WHERE fm > {'lmn' : 'f'} AND fm
CONTAINS KEY 'lmn'");
assertInvalidMessage("Map-entry predicates on frozen map column fm are
not supported",
diff --git
a/test/unit/org/apache/cassandra/index/sai/cql/TokenRangeReadTest.java
b/test/unit/org/apache/cassandra/index/sai/cql/TokenRangeReadTest.java
index 67a030ef9f..d63c2631e6 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/TokenRangeReadTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/TokenRangeReadTest.java
@@ -18,6 +18,7 @@
package org.apache.cassandra.index.sai.cql;
+import org.apache.cassandra.cql3.restrictions.StatementRestrictions;
import org.junit.Test;
import org.apache.cassandra.index.sai.SAITester;
@@ -41,4 +42,34 @@ public class TokenRangeReadTest extends SAITester
assertRows(execute("SELECT * FROM %s WHERE token(k1) >= token(1)
AND token(k1) <= token(1) AND v1 = '1'"), row(1, "1"));
});
}
+
+ @Test
+ public void testTokenRangeWithNotContains() throws Throwable
+ {
+ createTable("CREATE TABLE %s (k1 int, v1 set<text>, PRIMARY KEY
(k1))");
+ createIndex(format("CREATE CUSTOM INDEX ON %%s(v1) USING '%s'",
StorageAttachedIndex.class.getName()));
+
+ execute("INSERT INTO %S(k1, v1) values(1, {'a', 'b', 'c'})");
+ execute("INSERT INTO %S(k1, v1) values(2, {'a', 'd'})");
+
+ beforeAndAfterFlush(() -> {
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT k1 FROM %s WHERE v1 NOT CONTAINS 'd'");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT k1 FROM %s WHERE token(k1) >= token(1) AND token(k1) <= token(1) AND v1
NOT CONTAINS 'z'");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT k1 FROM %s WHERE token(k1) >= token(2) AND token(k1) <= token(2) AND v1
NOT CONTAINS 'z'");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT k1 FROM %s WHERE token(k1) > token(2) AND token(k1) <= token(2) AND v1
NOT CONTAINS 'z'");
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT k1 FROM %s WHERE token(k1) >= token(2) AND token(k1) < token(2) AND v1
NOT CONTAINS 'z'");
+ });
+ }
+
+ @Test
+ public void testInvalidOperatorTokenRangeRead() throws Throwable
+ {
+ createTable("CREATE TABLE %s (k1 int, v1 set<text>, PRIMARY KEY
(k1))");
+ createIndex(format("CREATE CUSTOM INDEX ON %%s(v1) USING '%s'",
StorageAttachedIndex.class.getName()));
+
+ execute("INSERT INTO %S(k1, v1) values(1, {'a', 'b', 'c'})");
+ execute("INSERT INTO %S(k1, v1) values(2, {'a', 'd'})");
+
+ assertInvalidMessage("Unsupported '!=' relation: token(k1) !=
'token(2)","SELECT k1 FROM %s WHERE token(k1) != 'token(2)'");
+ }
}
diff --git
a/test/unit/org/apache/cassandra/index/sai/cql/UnindexedExpressionsTest.java
b/test/unit/org/apache/cassandra/index/sai/cql/UnindexedExpressionsTest.java
index 6caec99445..6818f0edc2 100644
--- a/test/unit/org/apache/cassandra/index/sai/cql/UnindexedExpressionsTest.java
+++ b/test/unit/org/apache/cassandra/index/sai/cql/UnindexedExpressionsTest.java
@@ -69,9 +69,7 @@ public class UnindexedExpressionsTest extends SAITester
// The IS NOT operator is only valid on materialized views
assertInvalidMessage("Unsupported restriction:", "SELECT pk FROM %s
WHERE val1 = 1 AND val2 is not null");
- // The != operator is currently not supported at all
- assertInvalidMessage("Unsupported '!=' relation: val2 != '22'",
"SELECT pk FROM %s WHERE val1 = 1 AND val2 != '22'");
-
+
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT pk FROM %s WHERE val1 = 1 AND val2 != '22'");
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT pk FROM %s WHERE val1 = 1 AND val2 < '22'");
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT pk FROM %s WHERE val1 = 1 AND val2 <= '11'");
assertInvalidMessage(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE,
"SELECT pk FROM %s WHERE val1 = 1 AND val2 >= '11'");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]