Merge branch cassandra-3.11 into trunk

This commit is contained in:
Benjamin Lerer 2017-02-23 14:26:29 +01:00
commit cd29d44dfe
10 changed files with 488 additions and 5 deletions

View File

@ -36,6 +36,7 @@
3.11.0
* Fix equality comparisons of columns using the duration type (CASSANDRA-13174)
* Move to FastThreadLocalThread and FastThreadLocal (CASSANDRA-13034)
* nodetool stopdaemon errors out (CASSANDRA-13030)
* Tables in system_distributed should not use gcgs of 0 (CASSANDRA-12954)

View File

@ -316,6 +316,15 @@ public enum Operator
return 4;
}
/**
* Checks if this operator is a slice operator.
* @return {@code true} if this operator is a slice operator, {@code false} otherwise.
*/
public boolean isSlice()
{
return this == LT || this == LTE || this == GT || this == GTE;
}
@Override
public String toString()
{

View File

@ -28,7 +28,6 @@ import org.apache.cassandra.cql3.restrictions.Restriction;
import org.apache.cassandra.cql3.restrictions.SingleColumnRestriction;
import org.apache.cassandra.cql3.statements.Bound;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.DurationType;
import org.apache.cassandra.db.marshal.ListType;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.exceptions.InvalidRequestException;
@ -196,7 +195,14 @@ public final class SingleColumnRelation extends Relation
boolean inclusive)
{
ColumnMetadata columnDef = entity.prepare(table);
checkFalse(columnDef.type instanceof DurationType, "Slice restriction are not supported on duration columns");
if (columnDef.type.referencesDuration())
{
checkFalse(columnDef.type.isCollection(), "Slice restrictions are not supported on collections containing durations");
checkFalse(columnDef.type.isTuple(), "Slice restrictions are not supported on tuples containing durations");
checkFalse(columnDef.type.isUDT(), "Slice restrictions are not supported on UDTs containing durations");
throw invalidRequest("Slice restrictions are not supported on duration columns");
}
Term term = toTerm(toReceivers(columnDef), value, table.keyspace, boundNames);
return new SingleColumnRestriction.SliceRestriction(columnDef, bound, inclusive, term);

View File

@ -783,6 +783,7 @@ public abstract class ColumnCondition
throw new AssertionError();
}
validateOperationOnDurations(valueSpec.type);
return condition(receiver, collectionElement.prepare(keyspace, elementSpec), operator, prepareTerms(keyspace, valueSpec));
}
@ -794,9 +795,11 @@ public abstract class ColumnCondition
throw invalidRequest("Unknown field %s for column %s", udtField, receiver.name);
ColumnSpecification fieldReceiver = UserTypes.fieldSpecOf(receiver, fieldPosition);
validateOperationOnDurations(fieldReceiver.type);
return condition(receiver, udtField, operator, prepareTerms(keyspace, fieldReceiver));
}
validateOperationOnDurations(receiver.type);
return condition(receiver, operator, prepareTerms(keyspace, receiver));
}
@ -821,5 +824,16 @@ public abstract class ColumnCondition
}
return terms;
}
private void validateOperationOnDurations(AbstractType<?> type)
{
if (type.referencesDuration() && operator.isSlice())
{
checkFalse(type.isCollection(), "Slice conditions are not supported on collections containing durations");
checkFalse(type.isTuple(), "Slice conditions are not supported on tuples containing durations");
checkFalse(type.isUDT(), "Slice conditions are not supported on UDTs containing durations");
throw invalidRequest("Slice conditions are not supported on durations", operator);
}
}
}
}

View File

@ -44,6 +44,9 @@ import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.QueryState;
import org.apache.cassandra.transport.Event;
import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
/** A <code>CREATE INDEX</code> statement parsed from a CQL query. */
public class CreateIndexStatement extends SchemaAlteringStatement
{
@ -102,6 +105,14 @@ public class CreateIndexStatement extends SchemaAlteringStatement
if (cd == null)
throw new InvalidRequestException("No column definition found for column " + target.column);
if (cd.type.referencesDuration())
{
checkFalse(cd.type.isCollection(), "Secondary indexes are not supported on collections containing durations");
checkFalse(cd.type.isTuple(), "Secondary indexes are not supported on tuples containing durations");
checkFalse(cd.type.isUDT(), "Secondary indexes are not supported on UDTs containing durations");
throw invalidRequest("Secondary indexes are not supported on duration columns");
}
// TODO: we could lift that limitation
if (table.isCompactTable() && cd.isPrimaryKeyColumn())
throw new InvalidRequestException("Secondary indexes are not supported on PRIMARY KEY columns in COMPACT STORAGE tables");

View File

@ -28,6 +28,7 @@ import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.transport.ProtocolVersion;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FastByteOperations;
/**
* Represents a duration. The duration is stored as months, days, and nanoseconds. This is done
@ -39,7 +40,7 @@ public class DurationType extends AbstractType<Duration>
DurationType()
{
super(ComparisonType.NOT_COMPARABLE);
super(ComparisonType.BYTE_ORDER);
} // singleton
public ByteBuffer fromString(String source) throws MarshalException

View File

@ -1330,6 +1330,32 @@ public class SecondaryIndexTest extends CQLTester
row(1, 1, 9, 1));
}
@Test
public void testIndexOnDurationColumn() throws Throwable
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, d duration)");
assertInvalidMessage("Secondary indexes are not supported on duration columns",
"CREATE INDEX ON %s (d)");
createTable("CREATE TABLE %s (k int PRIMARY KEY, l list<duration>)");
assertInvalidMessage("Secondary indexes are not supported on collections containing durations",
"CREATE INDEX ON %s (l)");
createTable("CREATE TABLE %s (k int PRIMARY KEY, m map<int, duration>)");
assertInvalidMessage("Secondary indexes are not supported on collections containing durations",
"CREATE INDEX ON %s (m)");
createTable("CREATE TABLE %s (k int PRIMARY KEY, t tuple<int, duration>)");
assertInvalidMessage("Secondary indexes are not supported on tuples containing durations",
"CREATE INDEX ON %s (t)");
String udt = createType("CREATE TYPE %s (i int, d duration)");
createTable("CREATE TABLE %s (k int PRIMARY KEY, t " + udt + ")");
assertInvalidMessage("Secondary indexes are not supported on UDTs containing durations",
"CREATE INDEX ON %s (t)");
}
private ResultMessage.Prepared prepareStatement(String cql)
{
return QueryProcessor.prepare(String.format(cql, KEYSPACE, currentTable()),

View File

@ -148,10 +148,10 @@ public class CreateTest extends CQLTester
row(1, 21, Duration.newInstance(12, 10, 0)),
row(1, 22, Duration.newInstance(-12, -10, 0)));
assertInvalidMessage("Slice restriction are not supported on duration columns",
assertInvalidMessage("Slice restrictions are not supported on duration columns",
"SELECT * FROM %s WHERE c > 1y ALLOW FILTERING");
assertInvalidMessage("Slice restriction are not supported on duration columns",
assertInvalidMessage("Slice restrictions are not supported on duration columns",
"SELECT * FROM %s WHERE c <= 1y ALLOW FILTERING");
assertInvalidMessage("Expected at least 3 bytes for a duration (1)",

View File

@ -25,6 +25,7 @@ import org.junit.Test;
import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.cql3.Duration;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.schema.SchemaKeyspace;
@ -2032,6 +2033,99 @@ public class InsertUpdateIfConditionTest extends CQLTester
}
}
@Test
public void testConditionalOnDurationColumns() throws Throwable
{
createTable(" CREATE TABLE %s (k int PRIMARY KEY, v int, d duration)");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF d > 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF d >= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF d <= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF d < 1s");
execute("INSERT INTO %s (k, v, d) VALUES (1, 1, 2s)");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF d = 1s"), row(false, Duration.from("2s")));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF d = 2s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, Duration.from("2s"), 3));
assertRows(execute("UPDATE %s SET d = 10s WHERE k = 1 IF d != 2s"), row(false, Duration.from("2s")));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF d != 1s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, Duration.from("2s"), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF d IN (1s, 5s)"), row(false, Duration.from("2s")));
assertRows(execute("UPDATE %s SET d = 10s WHERE k = 1 IF d IN (1s, 2s)"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, Duration.from("10s"), 6));
}
@Test
public void testConditionalOnDurationWithinLists() throws Throwable
{
for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE})
{
String listType = String.format(frozen ? "frozen<%s>" : "%s", "list<duration>");
createTable("CREATE TABLE %s (k int PRIMARY KEY, v int, l " + listType + " )");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l > [1s, 2s]");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l >= [1s, 2s]");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l <= [1s, 2s]");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l < [1s, 2s]");
execute("INSERT INTO %s (k, v, l) VALUES (1, 1, [1s, 2s])");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF l = [2s]"), row(false, list(Duration.from("1000ms"), Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF l = [1s, 2s]"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, list(Duration.from("1000ms"), Duration.from("2s")), 3));
assertRows(execute("UPDATE %s SET l = [10s] WHERE k = 1 IF l != [1s, 2s]"), row(false, list(Duration.from("1000ms"), Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF l != [1s]"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, list(Duration.from("1000ms"), Duration.from("2s")), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF l IN ([1s], [1s, 5s])"), row(false, list(Duration.from("1000ms"), Duration.from("2s"))));
assertRows(execute("UPDATE %s SET l = [5s, 10s] WHERE k = 1 IF l IN ([1s], [1s, 2s])"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, list(Duration.from("5s"), Duration.from("10s")), 6));
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l[0] > 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l[0] >= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l[0] <= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF l[0] < 1s");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF l[0] = 2s"), row(false, list(Duration.from("5s"), Duration.from("10s"))));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF l[0] = 5s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, list(Duration.from("5s"), Duration.from("10s")), 3));
assertRows(execute("UPDATE %s SET l = [10s] WHERE k = 1 IF l[1] != 10s"), row(false, list(Duration.from("5s"), Duration.from("10s"))));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF l[1] != 1s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, list(Duration.from("5s"), Duration.from("10s")), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF l[0] IN (2s, 10s)"), row(false, list(Duration.from("5s"), Duration.from("10s"))));
assertRows(execute("UPDATE %s SET l = [6s, 12s] WHERE k = 1 IF l[0] IN (5s, 10s)"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, list(Duration.from("6s"), Duration.from("12s")), 6));
}
}
@Test
public void testInMarkerWithLists() throws Throwable
{
@ -2089,6 +2183,67 @@ public class InsertUpdateIfConditionTest extends CQLTester
}
}
@Test
public void testConditionalOnDurationWithinMaps() throws Throwable
{
for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE})
{
String mapType = String.format(frozen ? "frozen<%s>" : "%s", "map<int, duration>");
createTable("CREATE TABLE %s (k int PRIMARY KEY, v int, m " + mapType + " )");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m > {1: 1s, 2: 2s}");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m >= {1: 1s, 2: 2s}");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m <= {1: 1s, 2: 2s}");
assertInvalidMessage("Slice conditions are not supported on collections containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m < {1: 1s, 2: 2s}");
execute("INSERT INTO %s (k, v, m) VALUES (1, 1, {1: 1s, 2: 2s})");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF m = {2: 2s}"), row(false, map(1, Duration.from("1000ms"), 2, Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF m = {1: 1s, 2: 2s}"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, map(1, Duration.from("1000ms"), 2, Duration.from("2s")), 3));
assertRows(execute("UPDATE %s SET m = {1 :10s} WHERE k = 1 IF m != {1: 1s, 2: 2s}"), row(false, map(1, Duration.from("1000ms"), 2, Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF m != {1: 1s}"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, map(1, Duration.from("1000ms"), 2, Duration.from("2s")), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF m IN ({1: 1s}, {1: 5s})"), row(false, map(1, Duration.from("1000ms"), 2, Duration.from("2s"))));
assertRows(execute("UPDATE %s SET m = {1: 5s, 2: 10s} WHERE k = 1 IF m IN ({1: 1s}, {1: 1s, 2: 2s})"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, map(1, Duration.from("5s"), 2, Duration.from("10s")), 6));
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m[1] > 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m[1] >= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m[1] <= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF m[1] < 1s");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF m[1] = 2s"), row(false, map(1, Duration.from("5s"), 2, Duration.from("10s"))));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF m[1] = 5s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, map(1, Duration.from("5s"), 2, Duration.from("10s")), 3));
assertRows(execute("UPDATE %s SET m = {1: 10s} WHERE k = 1 IF m[2] != 10s"), row(false, map(1, Duration.from("5s"), 2, Duration.from("10s"))));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF m[2] != 1s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, map(1, Duration.from("5s"), 2, Duration.from("10s")), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF m[1] IN (2s, 10s)"), row(false, map(1, Duration.from("5s"), 2, Duration.from("10s"))));
assertRows(execute("UPDATE %s SET m = {1: 6s, 2: 12s} WHERE k = 1 IF m[1] IN (5s, 10s)"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, map(1, Duration.from("6s"), 2, Duration.from("12s")), 6));
}
}
@Test
public void testInMarkerWithMaps() throws Throwable
{
@ -2145,4 +2300,99 @@ public class InsertUpdateIfConditionTest extends CQLTester
"UPDATE %s SET m = {'foo' : 'foobar'} WHERE k = 0 IF m[?] IN ?", "foo", unset());
}
}
@Test
public void testConditionalOnDurationWithinUdts() throws Throwable
{
String udt = createType("CREATE TYPE %s (i int, d duration)");
for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE})
{
udt = String.format(frozen ? "frozen<%s>" : "%s", udt);
createTable("CREATE TABLE %s (k int PRIMARY KEY, v int, u " + udt + " )");
assertInvalidMessage("Slice conditions are not supported on UDTs containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u > {i: 1, d: 2s}");
assertInvalidMessage("Slice conditions are not supported on UDTs containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u >= {i: 1, d: 2s}");
assertInvalidMessage("Slice conditions are not supported on UDTs containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u <= {i: 1, d: 2s}");
assertInvalidMessage("Slice conditions are not supported on UDTs containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u < {i: 1, d: 2s}");
execute("INSERT INTO %s (k, v, u) VALUES (1, 1, {i:1, d:2s})");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF u = {i: 2, d: 2s}"), row(false, userType("i", 1, "d", Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF u = {i: 1, d: 2s}"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, userType("i", 1, "d", Duration.from("2s")), 3));
assertRows(execute("UPDATE %s SET u = {i: 1, d: 10s} WHERE k = 1 IF u != {i: 1, d: 2s}"), row(false, userType("i", 1, "d", Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF u != {i: 1, d: 1s}"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, userType("i", 1, "d", Duration.from("2s")), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF u IN ({i: 1, d: 1s}, {i: 1, d: 5s})"), row(false, userType("i", 1, "d", Duration.from("2s"))));
assertRows(execute("UPDATE %s SET u = {i: 1, d: 10s} WHERE k = 1 IF u IN ({i: 1, d: 1s}, {i: 1, d: 2s})"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, userType("i", 1, "d", Duration.from("10s")), 6));
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u.d > 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u.d >= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u.d <= 1s");
assertInvalidMessage("Slice conditions are not supported on durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u.d < 1s");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF u.d = 2s"), row(false, userType("i", 1, "d", Duration.from("10s"))));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF u.d = 10s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, userType("i", 1, "d", Duration.from("10s")), 3));
assertRows(execute("UPDATE %s SET u = {i: 1, d: 10s} WHERE k = 1 IF u.d != 10s"), row(false, userType("i", 1, "d", Duration.from("10s"))));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF u.d != 1s"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, userType("i", 1, "d", Duration.from("10s")), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF u.d IN (2s, 5s)"), row(false, userType("i", 1, "d", Duration.from("10s"))));
assertRows(execute("UPDATE %s SET u = {i: 6, d: 12s} WHERE k = 1 IF u.d IN (5s, 10s)"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, userType("i", 6, "d", Duration.from("12s")), 6));
}
}
@Test
public void testConditionalOnDurationWithinTuples() throws Throwable
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, v int, u tuple<int, duration> )");
assertInvalidMessage("Slice conditions are not supported on tuples containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u > (1, 2s)");
assertInvalidMessage("Slice conditions are not supported on tuples containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u >= (1, 2s)");
assertInvalidMessage("Slice conditions are not supported on tuples containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u <= (1, 2s)");
assertInvalidMessage("Slice conditions are not supported on tuples containing durations",
"UPDATE %s SET v = 3 WHERE k = 0 IF u < (1, 2s)");
execute("INSERT INTO %s (k, v, u) VALUES (1, 1, (1, 2s))");
assertRows(execute("UPDATE %s SET v = 4 WHERE k = 1 IF u = (2, 2s)"), row(false, tuple(1, Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 3 WHERE k = 1 IF u = (1, 2s)"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, tuple(1, Duration.from("2s")), 3));
assertRows(execute("UPDATE %s SET u = (1, 10s) WHERE k = 1 IF u != (1, 2s)"), row(false, tuple(1, Duration.from("2s"))));
assertRows(execute("UPDATE %s SET v = 6 WHERE k = 1 IF u != (1, 1s)"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, tuple(1, Duration.from("2s")), 6));
assertRows(execute("UPDATE %s SET v = 5 WHERE k = 1 IF u IN ((1, 1s), (1, 5s))"), row(false, tuple(1, Duration.from("2s"))));
assertRows(execute("UPDATE %s SET u = (1, 10s) WHERE k = 1 IF u IN ((1, 1s), (1, 2s))"), row(true));
assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, tuple(1, Duration.from("10s")), 6));
}
}

View File

@ -24,6 +24,7 @@ import org.junit.Test;
import org.junit.Assert;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.cql3.Duration;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.cql3.restrictions.StatementRestrictions;
import org.apache.cassandra.exceptions.InvalidRequestException;
@ -4488,4 +4489,168 @@ public class SelectTest extends CQLTester
assertRows(execute("SELECT distinct, json FROM %s"), row(0, 0));
assertRows(execute("SELECT distinct distinct FROM %s"), row(0));
}
@Test
public void testFilteringOnDurationColumn() throws Throwable
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, d duration)");
execute("INSERT INTO %s (k, d) VALUES (0, 1s)");
execute("INSERT INTO %s (k, d) VALUES (1, 2s)");
execute("INSERT INTO %s (k, d) VALUES (2, 1s)");
assertRows(execute("SELECT * FROM %s WHERE d=1s ALLOW FILTERING"),
row(0, Duration.from("1s")),
row(2, Duration.from("1s")));
assertInvalidMessage("IN predicates on non-primary-key columns (d) is not yet supported",
"SELECT * FROM %s WHERE d IN (1s, 2s) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on duration columns",
"SELECT * FROM %s WHERE d > 1s ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on duration columns",
"SELECT * FROM %s WHERE d >= 1s ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on duration columns",
"SELECT * FROM %s WHERE d <= 1s ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on duration columns",
"SELECT * FROM %s WHERE d < 1s ALLOW FILTERING");
}
@Test
public void testFilteringOnListContainingDurations() throws Throwable
{
for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE})
{
String listType = String.format(frozen ? "frozen<%s>" : "%s", "list<duration>");
createTable("CREATE TABLE %s (k int PRIMARY KEY, l " + listType + ")");
execute("INSERT INTO %s (k, l) VALUES (0, [1s, 2s])");
execute("INSERT INTO %s (k, l) VALUES (1, [2s, 3s])");
execute("INSERT INTO %s (k, l) VALUES (2, [1s, 3s])");
if (frozen)
assertRows(execute("SELECT * FROM %s WHERE l = [1s, 2s] ALLOW FILTERING"),
row(0, list(Duration.from("1s"), Duration.from("2s"))));
assertInvalidMessage("IN predicates on non-primary-key columns (l) is not yet supported",
"SELECT * FROM %s WHERE l IN ([1s, 2s], [2s, 3s]) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE l > [2s, 3s] ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE l >= [2s, 3s] ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE l <= [2s, 3s] ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE l < [2s, 3s] ALLOW FILTERING");
assertRows(execute("SELECT * FROM %s WHERE l CONTAINS 1s ALLOW FILTERING"),
row(0, list(Duration.from("1s"), Duration.from("2s"))),
row(2, list(Duration.from("1s"), Duration.from("3s"))));
}
}
@Test
public void testFilteringOnMapContainingDurations() throws Throwable
{
for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE})
{
String mapType = String.format(frozen ? "frozen<%s>" : "%s", "map<int, duration>");
createTable("CREATE TABLE %s (k int PRIMARY KEY, m " + mapType + ")");
execute("INSERT INTO %s (k, m) VALUES (0, {1:1s, 2:2s})");
execute("INSERT INTO %s (k, m) VALUES (1, {2:2s, 3:3s})");
execute("INSERT INTO %s (k, m) VALUES (2, {1:1s, 3:3s})");
if (frozen)
assertRows(execute("SELECT * FROM %s WHERE m = {1:1s, 2:2s} ALLOW FILTERING"),
row(0, map(1, Duration.from("1s"), 2, Duration.from("2s"))));
assertInvalidMessage("IN predicates on non-primary-key columns (m) is not yet supported",
"SELECT * FROM %s WHERE m IN ({1:1s, 2:2s}, {1:1s, 3:3s}) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE m > {1:1s, 3:3s} ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE m >= {1:1s, 3:3s} ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE m <= {1:1s, 3:3s} ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on collections containing durations",
"SELECT * FROM %s WHERE m < {1:1s, 3:3s} ALLOW FILTERING");
assertRows(execute("SELECT * FROM %s WHERE m CONTAINS 1s ALLOW FILTERING"),
row(0, map(1, Duration.from("1s"), 2, Duration.from("2s"))),
row(2, map(1, Duration.from("1s"), 3, Duration.from("3s"))));
}
}
@Test
public void testFilteringOnTupleContainingDurations() throws Throwable
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, t tuple<int, duration>)");
execute("INSERT INTO %s (k, t) VALUES (0, (1, 2s))");
execute("INSERT INTO %s (k, t) VALUES (1, (2, 3s))");
execute("INSERT INTO %s (k, t) VALUES (2, (1, 3s))");
assertRows(execute("SELECT * FROM %s WHERE t = (1, 2s) ALLOW FILTERING"),
row(0, tuple(1, Duration.from("2s"))));
assertInvalidMessage("IN predicates on non-primary-key columns (t) is not yet supported",
"SELECT * FROM %s WHERE t IN ((1, 2s), (1, 3s)) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on tuples containing durations",
"SELECT * FROM %s WHERE t > (1, 2s) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on tuples containing durations",
"SELECT * FROM %s WHERE t >= (1, 2s) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on tuples containing durations",
"SELECT * FROM %s WHERE t <= (1, 2s) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on tuples containing durations",
"SELECT * FROM %s WHERE t < (1, 2s) ALLOW FILTERING");
}
@Test
public void testFilteringOnUdtContainingDurations() throws Throwable
{
String udt = createType("CREATE TYPE %s (i int, d duration)");
for (Boolean frozen : new Boolean[]{Boolean.FALSE, Boolean.TRUE})
{
udt = String.format(frozen ? "frozen<%s>" : "%s", udt);
createTable("CREATE TABLE %s (k int PRIMARY KEY, u " + udt + ")");
execute("INSERT INTO %s (k, u) VALUES (0, {i: 1, d:2s})");
execute("INSERT INTO %s (k, u) VALUES (1, {i: 2, d:3s})");
execute("INSERT INTO %s (k, u) VALUES (2, {i: 1, d:3s})");
if (frozen)
assertRows(execute("SELECT * FROM %s WHERE u = {i: 1, d:2s} ALLOW FILTERING"),
row(0, userType("i", 1, "d", Duration.from("2s"))));
assertInvalidMessage("IN predicates on non-primary-key columns (u) is not yet supported",
"SELECT * FROM %s WHERE u IN ({i: 2, d:3s}, {i: 1, d:3s}) ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations",
"SELECT * FROM %s WHERE u > {i: 1, d:3s} ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations",
"SELECT * FROM %s WHERE u >= {i: 1, d:3s} ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations",
"SELECT * FROM %s WHERE u <= {i: 1, d:3s} ALLOW FILTERING");
assertInvalidMessage("Slice restrictions are not supported on UDTs containing durations",
"SELECT * FROM %s WHERE u < {i: 1, d:3s} ALLOW FILTERING");
}
}
}