Merge branch cassandra-3.11 into trunk
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/10b397e2 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/10b397e2 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/10b397e2 Branch: refs/heads/trunk Commit: 10b397e2a9c90e0fe3a229659952a56a03795a22 Parents: 9fdec0a b5df3b4 Author: Benjamin Lerer <b.le...@gmail.com> Authored: Fri Jul 7 13:40:48 2017 +0200 Committer: Benjamin Lerer <b.le...@gmail.com> Committed: Fri Jul 7 13:42:19 2017 +0200 ---------------------------------------------------------------------- CHANGES.txt | 3 +- .../org/apache/cassandra/cql3/UserTypes.java | 27 +++++--- .../apache/cassandra/db/marshal/TupleType.java | 45 ++++--------- .../apache/cassandra/db/marshal/UserType.java | 51 +++++---------- .../cassandra/serializers/TupleSerializer.java | 64 +++++++++++++++++++ .../serializers/UserTypeSerializer.java | 67 ++++++++++++++++++++ .../validation/entities/CollectionsTest.java | 36 +++++++++++ .../cql3/validation/entities/TupleTypeTest.java | 10 ++- .../cql3/validation/entities/UserTypesTest.java | 15 ++++- 9 files changed, 239 insertions(+), 79 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/10b397e2/CHANGES.txt ---------------------------------------------------------------------- diff --cc CHANGES.txt index 4f2d2a1,679d55b..569a807 --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -96,10 -1,11 +96,11 @@@ 3.11.1 * Properly evict pstmts from prepared statements cache (CASSANDRA-13641) Merged from 3.0: - * Allow different NUMACTL_ARGS to be passed in (CASSANDRA-13557) - * Fix secondary index queries on COMPACT tables (CASSANDRA-13627) - * Nodetool listsnapshots output is missing a newline, if there are no snapshots (CASSANDRA-13568) + * Allow different NUMACTL_ARGS to be passed in (CASSANDRA-13557) + * Fix secondary index queries on COMPACT tables (CASSANDRA-13627) + * Nodetool listsnapshots output is missing a newline, if there are no snapshots (CASSANDRA-13568) - + Merged from 2.2: - * Fix nested Tuples/UDTs validation (CASSANDRA-13646) ++ * Fix nested Tuples/UDTs validation (CASSANDRA-13646) 3.11.0 * Allow native function calls in CQLSSTableWriter (CASSANDRA-12606) http://git-wip-us.apache.org/repos/asf/cassandra/blob/10b397e2/src/java/org/apache/cassandra/cql3/UserTypes.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/10b397e2/src/java/org/apache/cassandra/db/marshal/TupleType.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/10b397e2/src/java/org/apache/cassandra/db/marshal/UserType.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/db/marshal/UserType.java index f139edd,febd91c..6149e94 --- a/src/java/org/apache/cassandra/db/marshal/UserType.java +++ b/src/java/org/apache/cassandra/db/marshal/UserType.java @@@ -426,8 -404,9 +403,14 @@@ public class UserType extends TupleTyp return sb.toString(); } + public String toCQLString() + { + return String.format("%s.%s", ColumnIdentifier.maybeQuote(keyspace), ColumnIdentifier.maybeQuote(getNameAsString())); + } ++ + @Override + public TypeSerializer<ByteBuffer> getSerializer() + { + return serializer; + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/10b397e2/test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java index dad5d68,22e6e66..6f67609 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java @@@ -1107,786 -1037,38 +1107,822 @@@ public class CollectionsTest extends CQ } @Test + public void testMapOperation() throws Throwable + { + createTable("CREATE TABLE %s (k int, c int, l text, " + + "m map<text, text>, " + + "fm frozen<map<text, text>>, " + + "sm map<text, text> STATIC, " + + "fsm frozen<map<text, text>> STATIC, " + + "o int, PRIMARY KEY (k, c))"); + + execute("INSERT INTO %s(k, c, l, m, fm, sm, fsm, o) VALUES (0, 0, 'foobar', ?, ?, ?, ?, 42)", + map("22", "value22", "333", "value333"), + map("1", "fvalue1", "22", "fvalue22", "333", "fvalue333"), + map("22", "svalue22", "333", "svalue333"), + map("1", "fsvalue1", "22", "fsvalue22", "333", "fsvalue333")); + + execute("INSERT INTO %s(k, c, l, m, fm, sm, fsm, o) VALUES (2, 0, 'row2', ?, ?, ?, ?, 88)", + map("22", "2value22", "333", "2value333"), + map("1", "2fvalue1", "22", "2fvalue22", "333", "2fvalue333"), + map("22", "2svalue22", "333", "2svalue333"), + map("1", "2fsvalue1", "22", "2fsvalue22", "333", "2fsvalue333")); + + flush(); + + execute("UPDATE %s SET m = m + ? WHERE k = 0 AND c = 0", + map("1", "value1")); + + execute("UPDATE %s SET sm = sm + ? WHERE k = 0", + map("1", "svalue1")); + + flush(); + + assertRows(execute("SELECT m['22'] FROM %s WHERE k = 0 AND c = 0"), + row("value22") + ); + assertRows(execute("SELECT m['1'], m['22'], m['333'] FROM %s WHERE k = 0 AND c = 0"), + row("value1", "value22", "value333") + ); + assertRows(execute("SELECT m['2'..'3'] FROM %s WHERE k = 0 AND c = 0"), + row(map("22", "value22")) + ); + + execute("INSERT INTO %s(k, c, l, m, fm, o) VALUES (0, 1, 'foobar', ?, ?, 42)", + map("1", "value1_2", "333", "value333_2"), + map("1", "fvalue1_2", "333", "fvalue333_2")); + + assertRows(execute("SELECT c, m['1'], fm['1'] FROM %s WHERE k = 0"), + row(0, "value1", "fvalue1"), + row(1, "value1_2", "fvalue1_2") + ); + assertRows(execute("SELECT c, sm['1'], fsm['1'] FROM %s WHERE k = 0"), + row(0, "svalue1", "fsvalue1"), + row(1, "svalue1", "fsvalue1") + ); + + assertRows(execute("SELECT c, m['1'], fm['1'] FROM %s WHERE k = 0 AND c = 0"), + row(0, "value1", "fvalue1") + ); + + assertRows(execute("SELECT c, m['1'], fm['1'] FROM %s WHERE k = 0"), + row(0, "value1", "fvalue1"), + row(1, "value1_2", "fvalue1_2") + ); + + assertColumnNames(execute("SELECT k, l, m['1'] as mx, o FROM %s WHERE k = 0"), + "k", "l", "mx", "o"); + assertColumnNames(execute("SELECT k, l, m['1'], o FROM %s WHERE k = 0"), + "k", "l", "m['1']", "o"); + + assertRows(execute("SELECT k, l, m['22'], o FROM %s WHERE k = 0"), + row(0, "foobar", "value22", 42), + row(0, "foobar", null, 42) + ); + assertColumnNames(execute("SELECT k, l, m['22'], o FROM %s WHERE k = 0"), + "k", "l", "m['22']", "o"); + + assertRows(execute("SELECT k, l, m['333'], o FROM %s WHERE k = 0"), + row(0, "foobar", "value333", 42), + row(0, "foobar", "value333_2", 42) + ); + + assertRows(execute("SELECT k, l, m['foobar'], o FROM %s WHERE k = 0"), + row(0, "foobar", null, 42), + row(0, "foobar", null, 42) + ); + + assertRows(execute("SELECT k, l, m['1'..'22'], o FROM %s WHERE k = 0"), + row(0, "foobar", map("1", "value1", + "22", "value22"), 42), + row(0, "foobar", map("1", "value1_2"), 42) + ); + + assertRows(execute("SELECT k, l, m[''..'23'], o FROM %s WHERE k = 0"), + row(0, "foobar", map("1", "value1", + "22", "value22"), 42), + row(0, "foobar", map("1", "value1_2"), 42) + ); + assertColumnNames(execute("SELECT k, l, m[''..'23'], o FROM %s WHERE k = 0"), + "k", "l", "m[''..'23']", "o"); + + assertRows(execute("SELECT k, l, m['2'..'3'], o FROM %s WHERE k = 0"), + row(0, "foobar", map("22", "value22"), 42), + row(0, "foobar", map(), 42) + ); + + assertRows(execute("SELECT k, l, m['22'..], o FROM %s WHERE k = 0"), + row(0, "foobar", map("22", "value22", + "333", "value333"), 42), + row(0, "foobar", map("333", "value333_2"), 42) + ); + + assertRows(execute("SELECT k, l, m[..'22'], o FROM %s WHERE k = 0"), + row(0, "foobar", map("1", "value1", + "22", "value22"), 42), + row(0, "foobar", map("1", "value1_2"), 42) + ); + + assertRows(execute("SELECT k, l, m, o FROM %s WHERE k = 0"), + row(0, "foobar", map("1", "value1", + "22", "value22", + "333", "value333"), 42), + row(0, "foobar", map("1", "value1_2", + "333", "value333_2"), 42) + ); + + assertRows(execute("SELECT k, l, m, m as m2, o FROM %s WHERE k = 0"), + row(0, "foobar", map("1", "value1", + "22", "value22", + "333", "value333"), + map("1", "value1", + "22", "value22", + "333", "value333"), 42), + row(0, "foobar", map("1", "value1_2", + "333", "value333_2"), + map("1", "value1_2", + "333", "value333_2"), 42) + ); + + // with UDF as slice arg + + String f = createFunction(KEYSPACE, "text", + "CREATE FUNCTION %s(arg text) " + + "CALLED ON NULL INPUT " + + "RETURNS TEXT " + + "LANGUAGE java AS 'return arg;'"); + + assertRows(execute("SELECT k, c, l, m[" + f +"('1').." + f +"('22')], o FROM %s WHERE k = 0"), + row(0, 0, "foobar", map("1", "value1", + "22", "value22"), 42), + row(0, 1, "foobar", map("1", "value1_2"), 42) + ); + + assertRows(execute("SELECT k, c, l, m[" + f +"(?).." + f +"(?)], o FROM %s WHERE k = 0", "1", "22"), + row(0, 0, "foobar", map("1", "value1", + "22", "value22"), 42), + row(0, 1, "foobar", map("1", "value1_2"), 42) + ); + + // with UDF taking a map + + f = createFunction(KEYSPACE, "map<text,text>", + "CREATE FUNCTION %s(m text) " + + "CALLED ON NULL INPUT " + + "RETURNS TEXT " + + "LANGUAGE java AS $$return m;$$"); + + assertRows(execute("SELECT k, c, " + f + "(m['1']) FROM %s WHERE k = 0"), + row(0, 0, "value1"), + row(0, 1, "value1_2")); + + // with UDF taking multiple cols + + f = createFunction(KEYSPACE, "map<text,text>,map<text,text>,int,int", + "CREATE FUNCTION %s(m1 map<text,text>, m2 text, k int, c int) " + + "CALLED ON NULL INPUT " + + "RETURNS TEXT " + + "LANGUAGE java AS $$return m1.get(\"1\") + ':' + m2 + ':' + k + ':' + c;$$"); + + assertRows(execute("SELECT " + f + "(m, m['1'], k, c) FROM %s WHERE k = 0"), + row("value1:value1:0:0"), + row("value1_2:value1_2:0:1")); + + // with nested UDF + aggregation and multiple cols + + f = createFunction(KEYSPACE, "int,int", + "CREATE FUNCTION %s(k int, c int) " + + "CALLED ON NULL INPUT " + + "RETURNS int " + + "LANGUAGE java AS $$return k + c;$$"); + + assertColumnNames(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s WHERE k = 0"), + "sel1", "system.max(" + f + "(k, c))"); + assertRows(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s WHERE k = 0"), + row(1, 1)); + + assertColumnNames(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s"), + "sel1", "system.max(" + f + "(k, c))"); + assertRows(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s"), + row(2, 2)); + + // prepared parameters + + assertRows(execute("SELECT c, m[?], fm[?] FROM %s WHERE k = 0", "1", "1"), + row(0, "value1", "fvalue1"), + row(1, "value1_2", "fvalue1_2") + ); + assertRows(execute("SELECT c, sm[?], fsm[?] FROM %s WHERE k = 0", "1", "1"), + row(0, "svalue1", "fsvalue1"), + row(1, "svalue1", "fsvalue1") + ); + assertRows(execute("SELECT k, l, m[?..?], o FROM %s WHERE k = 0", "1", "22"), + row(0, "foobar", map("1", "value1", + "22", "value22"), 42), + row(0, "foobar", map("1", "value1_2"), 42) + ); + } + + @Test + public void testMapOperationWithIntKey() throws Throwable + { + // used type "int" as map key intentionally since CQL parsing relies on "BigInteger" + + createTable("CREATE TABLE %s (k int, c int, l text, " + + "m map<int, text>, " + + "fm frozen<map<int, text>>, " + + "sm map<int, text> STATIC, " + + "fsm frozen<map<int, text>> STATIC, " + + "o int, PRIMARY KEY (k, c))"); + + execute("INSERT INTO %s(k, c, l, m, fm, sm, fsm, o) VALUES (0, 0, 'foobar', ?, ?, ?, ?, 42)", + map(22, "value22", 333, "value333"), + map(1, "fvalue1", 22, "fvalue22", 333, "fvalue333"), + map(22, "svalue22", 333, "svalue333"), + map(1, "fsvalue1", 22, "fsvalue22", 333, "fsvalue333")); + + execute("INSERT INTO %s(k, c, l, m, fm, sm, fsm, o) VALUES (2, 0, 'row2', ?, ?, ?, ?, 88)", + map(22, "2value22", 333, "2value333"), + map(1, "2fvalue1", 22, "2fvalue22", 333, "2fvalue333"), + map(22, "2svalue22", 333, "2svalue333"), + map(1, "2fsvalue1", 22, "2fsvalue22", 333, "2fsvalue333")); + + flush(); + + execute("UPDATE %s SET m = m + ? WHERE k = 0 AND c = 0", + map(1, "value1")); + + execute("UPDATE %s SET sm = sm + ? WHERE k = 0", + map(1, "svalue1")); + + flush(); + + assertRows(execute("SELECT m[22] FROM %s WHERE k = 0 AND c = 0"), + row("value22") + ); + assertRows(execute("SELECT m[1], m[22], m[333] FROM %s WHERE k = 0 AND c = 0"), + row("value1", "value22", "value333") + ); + assertRows(execute("SELECT m[20 .. 25] FROM %s WHERE k = 0 AND c = 0"), + row(map(22, "value22")) + ); + + execute("INSERT INTO %s(k, c, l, m, fm, o) VALUES (0, 1, 'foobar', ?, ?, 42)", + map(1, "value1_2", 333, "value333_2"), + map(1, "fvalue1_2", 333, "fvalue333_2")); + + assertRows(execute("SELECT c, m[1], fm[1] FROM %s WHERE k = 0"), + row(0, "value1", "fvalue1"), + row(1, "value1_2", "fvalue1_2") + ); + assertRows(execute("SELECT c, sm[1], fsm[1] FROM %s WHERE k = 0"), + row(0, "svalue1", "fsvalue1"), + row(1, "svalue1", "fsvalue1") + ); + + // with UDF as slice arg + + String f = createFunction(KEYSPACE, "int", + "CREATE FUNCTION %s(arg int) " + + "CALLED ON NULL INPUT " + + "RETURNS int " + + "LANGUAGE java AS 'return arg;'"); + + assertRows(execute("SELECT k, c, l, m[" + f +"(1).." + f +"(22)], o FROM %s WHERE k = 0"), + row(0, 0, "foobar", map(1, "value1", + 22, "value22"), 42), + row(0, 1, "foobar", map(1, "value1_2"), 42) + ); + + assertRows(execute("SELECT k, c, l, m[" + f +"(?).." + f +"(?)], o FROM %s WHERE k = 0", 1, 22), + row(0, 0, "foobar", map(1, "value1", + 22, "value22"), 42), + row(0, 1, "foobar", map(1, "value1_2"), 42) + ); + + // with UDF taking a map + + f = createFunction(KEYSPACE, "map<int,text>", + "CREATE FUNCTION %s(m text) " + + "CALLED ON NULL INPUT " + + "RETURNS TEXT " + + "LANGUAGE java AS $$return m;$$"); + + assertRows(execute("SELECT k, c, " + f + "(m[1]) FROM %s WHERE k = 0"), + row(0, 0, "value1"), + row(0, 1, "value1_2")); + + // with UDF taking multiple cols + + f = createFunction(KEYSPACE, "map<int,text>,map<int,text>,int,int", + "CREATE FUNCTION %s(m1 map<int,text>, m2 text, k int, c int) " + + "CALLED ON NULL INPUT " + + "RETURNS TEXT " + + "LANGUAGE java AS $$return m1.get(1) + ':' + m2 + ':' + k + ':' + c;$$"); + + assertRows(execute("SELECT " + f + "(m, m[1], k, c) FROM %s WHERE k = 0"), + row("value1:value1:0:0"), + row("value1_2:value1_2:0:1")); + + // with nested UDF + aggregation and multiple cols + + f = createFunction(KEYSPACE, "int,int", + "CREATE FUNCTION %s(k int, c int) " + + "CALLED ON NULL INPUT " + + "RETURNS int " + + "LANGUAGE java AS $$return k + c;$$"); + + assertColumnNames(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s WHERE k = 0"), + "sel1", "system.max(" + f + "(k, c))"); + assertRows(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s WHERE k = 0"), + row(1, 1)); + + assertColumnNames(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s"), + "sel1", "system.max(" + f + "(k, c))"); + assertRows(execute("SELECT max(" + f + "(k, c)) as sel1, max(" + f + "(k, c)) FROM %s"), + row(2, 2)); + + // prepared parameters + + assertRows(execute("SELECT c, m[?], fm[?] FROM %s WHERE k = 0", 1, 1), + row(0, "value1", "fvalue1"), + row(1, "value1_2", "fvalue1_2") + ); + assertRows(execute("SELECT c, sm[?], fsm[?] FROM %s WHERE k = 0", 1, 1), + row(0, "svalue1", "fsvalue1"), + row(1, "svalue1", "fsvalue1") + ); + assertRows(execute("SELECT k, l, m[?..?], o FROM %s WHERE k = 0", 1, 22), + row(0, "foobar", map(1, "value1", + 22, "value22"), 42), + row(0, "foobar", map(1, "value1_2"), 42) + ); + } + + @Test + public void testMapOperationOnPartKey() throws Throwable + { + createTable("CREATE TABLE %s (k frozen<map<text, text>> PRIMARY KEY, l text, o int)"); + + execute("INSERT INTO %s(k, l, o) VALUES (?, 'foobar', 42)", map("1", "value1", "22", "value22", "333", "value333")); + + assertRows(execute("SELECT l, k['1'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", "value1", 42) + ); + + assertRows(execute("SELECT l, k['22'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", "value22", 42) + ); + + assertRows(execute("SELECT l, k['333'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", "value333", 42) + ); + + assertRows(execute("SELECT l, k['foobar'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", null, 42) + ); + + assertRows(execute("SELECT l, k['1'..'22'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", map("1", "value1", + "22", "value22"), 42) + ); + + assertRows(execute("SELECT l, k[''..'23'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", map("1", "value1", + "22", "value22"), 42) + ); + + assertRows(execute("SELECT l, k['2'..'3'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", map("22", "value22"), 42) + ); + + assertRows(execute("SELECT l, k['22'..], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", map("22", "value22", + "333", "value333"), 42) + ); + + assertRows(execute("SELECT l, k[..'22'], o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", map("1", "value1", + "22", "value22"), 42) + ); + + assertRows(execute("SELECT l, k, o FROM %s WHERE k = ?", map("1", "value1", "22", "value22", "333", "value333")), + row("foobar", map("1", "value1", + "22", "value22", + "333", "value333"), 42) + ); + } + + @Test + public void testMapOperationOnClustKey() throws Throwable + { + createTable("CREATE TABLE %s (k int, c frozen<map<text, text>>, l text, o int, PRIMARY KEY (k, c))"); + + execute("INSERT INTO %s(k, c, l, o) VALUES (0, ?, 'foobar', 42)", map("1", "value1", "22", "value22", "333", "value333")); + + assertRows(execute("SELECT k, l, c['1'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", "value1", 42) + ); + + assertRows(execute("SELECT k, l, c['22'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", "value22", 42) + ); + + assertRows(execute("SELECT k, l, c['333'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", "value333", 42) + ); + + assertRows(execute("SELECT k, l, c['foobar'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", null, 42) + ); + + assertRows(execute("SELECT k, l, c['1'..'22'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", map("1", "value1", + "22", "value22"), 42) + ); + + assertRows(execute("SELECT k, l, c[''..'23'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", map("1", "value1", + "22", "value22"), 42) + ); + + assertRows(execute("SELECT k, l, c['2'..'3'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", map("22", "value22"), 42) + ); + + assertRows(execute("SELECT k, l, c['22'..], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", map("22", "value22", + "333", "value333"), 42) + ); + + assertRows(execute("SELECT k, l, c[..'22'], o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", map("1", "value1", + "22", "value22"), 42) + ); + + assertRows(execute("SELECT k, l, c, o FROM %s WHERE k = 0 AND c = ?", map("1", "value1", "22", "value22", "333", "value333")), + row(0, "foobar", map("1", "value1", + "22", "value22", + "333", "value333"), 42) + ); + } + + @Test + public void testSetOperation() throws Throwable + { + createTable("CREATE TABLE %s (k int, c int, l text, " + + "s set<text>, " + + "fs frozen<set<text>>, " + + "ss set<text> STATIC, " + + "fss frozen<set<text>> STATIC, " + + "o int, PRIMARY KEY (k, c))"); + + execute("INSERT INTO %s(k, c, l, s, fs, ss, fss, o) VALUES (0, 0, 'foobar', ?, ?, ?, ?, 42)", + set("1", "22", "333"), + set("f1", "f22", "f333"), + set("s1", "s22", "s333"), + set("fs1", "fs22", "fs333")); + + flush(); + + execute("UPDATE %s SET s = s + ? WHERE k = 0 AND c = 0", set("22_2")); + + execute("UPDATE %s SET ss = ss + ? WHERE k = 0", set("s22_2")); + + flush(); + + execute("INSERT INTO %s(k, c, l, s, o) VALUES (0, 1, 'foobar', ?, 42)", + set("22", "333")); + + assertRows(execute("SELECT c, s, fs, ss, fss FROM %s WHERE k = 0"), + row(0, set("1", "22", "22_2", "333"), set("f1", "f22", "f333"), set("s1", "s22", "s22_2", "s333"), set("fs1", "fs22", "fs333")), + row(1, set("22", "333"), null, set("s1", "s22", "s22_2", "s333"), set("fs1", "fs22", "fs333")) + ); + + assertRows(execute("SELECT c, s['1'], fs['f1'], ss['s1'], fss['fs1'] FROM %s WHERE k = 0"), + row(0, "1", "f1", "s1", "fs1"), + row(1, null, null, "s1", "fs1") + ); + + assertRows(execute("SELECT s['1'], fs['f1'], ss['s1'], fss['fs1'] FROM %s WHERE k = 0 AND c = 0"), + row("1", "f1", "s1", "fs1") + ); + + assertRows(execute("SELECT k, c, l, s['1'], fs['f1'], ss['s1'], fss['fs1'], o FROM %s WHERE k = 0"), + row(0, 0, "foobar", "1", "f1", "s1", "fs1", 42), + row(0, 1, "foobar", null, null, "s1", "fs1", 42) + ); + + assertColumnNames(execute("SELECT k, l, s['1'], o FROM %s WHERE k = 0"), + "k", "l", "s['1']", "o"); + + assertRows(execute("SELECT k, l, s['22'], o FROM %s WHERE k = 0 AND c = 0"), + row(0, "foobar", "22", 42) + ); + + assertRows(execute("SELECT k, l, s['333'], o FROM %s WHERE k = 0 AND c = 0"), + row(0, "foobar", "333", 42) + ); + + assertRows(execute("SELECT k, l, s['foobar'], o FROM %s WHERE k = 0 AND c = 0"), + row(0, "foobar", null, 42) + ); + + assertRows(execute("SELECT k, l, s['1'..'22'], o FROM %s WHERE k = 0 AND c = 0"), + row(0, "foobar", set("1", "22"), 42) + ); + assertColumnNames(execute("SELECT k, l, s[''..'22'], o FROM %s WHERE k = 0"), + "k", "l", "s[''..'22']", "o"); + + assertRows(execute("SELECT k, l, s[''..'23'], o FROM %s WHERE k = 0 AND c = 0"), + row(0, "foobar", set("1", "22", "22_2"), 42) + ); + + assertRows(execute("SELECT k, l, s['2'..'3'], o FROM %s WHERE k = 0 AND c = 0"), + row(0, "foobar", set("22", "22_2"), 42) + ); + + assertRows(execute("SELECT k, l, s['22'..], o FROM %s WHERE k = 0"), + row(0, "foobar", set("22", "22_2", "333"), 42), + row(0, "foobar", set("22", "333"), 42) + ); + + assertRows(execute("SELECT k, l, s[..'22'], o FROM %s WHERE k = 0"), + row(0, "foobar", set("1", "22"), 42), + row(0, "foobar", set("22"), 42) + ); + + assertRows(execute("SELECT k, l, s, o FROM %s WHERE k = 0"), + row(0, "foobar", set("1", "22", "22_2", "333"), 42), + row(0, "foobar", set("22", "333"), 42) + ); + } + + @Test + public void testCollectionSliceOnMV() throws Throwable + { + createTable("CREATE TABLE %s (k int, c int, l text, m map<text, text>, o int, PRIMARY KEY (k, c))"); + assertInvalidMessage("Cannot use collection element selection when defining a materialized view", + "CREATE MATERIALIZED VIEW " + KEYSPACE + ".view1 AS SELECT m['abc'] FROM %s WHERE k IS NOT NULL AND c IS NOT NULL AND m IS NOT NULL PRIMARY KEY (c, k)"); + assertInvalidMessage("Cannot use collection slice selection when defining a materialized view", + "CREATE MATERIALIZED VIEW " + KEYSPACE + ".view1 AS SELECT m['abc'..'def'] FROM %s WHERE k IS NOT NULL AND c IS NOT NULL AND m IS NOT NULL PRIMARY KEY (c, k)"); + } + + @Test + public void testElementAccessOnList() throws Throwable + { + createTable("CREATE TABLE %s (pk int PRIMARY KEY, l list<int>)"); + execute("INSERT INTO %s (pk, l) VALUES (1, [1, 2, 3])"); + + assertInvalidMessage("Element selection is only allowed on sets and maps, but l is a list", + "SELECT pk, l[0] FROM %s"); + + assertInvalidMessage("Slice selection is only allowed on sets and maps, but l is a list", + "SELECT pk, l[1..3] FROM %s"); + } + + @Test + public void testCollectionOperationResultSetMetadata() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY," + + "m map<text, text>," + + "fm frozen<map<text, text>>," + + "s set<text>," + + "fs frozen<set<text>>)"); + + execute("INSERT INTO %s (k, m, fm, s, fs) VALUES (?, ?, ?, ?, ?)", + 0, + map("1", "one", "2", "two"), + map("1", "one", "2", "two"), + set("1", "2", "3"), + set("1", "2", "3")); + + String cql = "SELECT k, " + + "m, m['2'], m['2'..'3'], m[..'2'], m['3'..], " + + "fm, fm['2'], fm['2'..'3'], fm[..'2'], fm['3'..], " + + "s, s['2'], s['2'..'3'], s[..'2'], s['3'..], " + + "fs, fs['2'], fs['2'..'3'], fs[..'2'], fs['3'..] " + + "FROM " + KEYSPACE + '.' + currentTable() + " WHERE k = 0"; + UntypedResultSet result = execute(cql); + Iterator<ColumnSpecification> meta = result.metadata().iterator(); + meta.next(); + for (int i = 0; i < 4; i++) + { + // take the "full" collection selection + ColumnSpecification ref = meta.next(); + ColumnSpecification selSingle = meta.next(); + assertEquals(ref.toString(), UTF8Type.instance, selSingle.type); + for (int selOrSlice = 0; selOrSlice < 3; selOrSlice++) + { + ColumnSpecification selSlice = meta.next(); + assertEquals(ref.toString(), ref.type, selSlice.type); + } + } + + assertRows(result, + row(0, + map("1", "one", "2", "two"), "two", map("2", "two"), map("1", "one", "2", "two"), map(), + map("1", "one", "2", "two"), "two", map("2", "two"), map("1", "one", "2", "two"), map(), + set("1", "2", "3"), "2", set("2", "3"), set("1", "2"), set("3"), + set("1", "2", "3"), "2", set("2", "3"), set("1", "2"), set("3"))); + + Session session = sessionNet(); + ResultSet rset = session.execute(cql); + ColumnDefinitions colDefs = rset.getColumnDefinitions(); + Iterator<ColumnDefinitions.Definition> colDefIter = colDefs.asList().iterator(); + colDefIter.next(); + for (int i = 0; i < 4; i++) + { + // take the "full" collection selection + ColumnDefinitions.Definition ref = colDefIter.next(); + ColumnDefinitions.Definition selSingle = colDefIter.next(); + assertEquals(ref.getName(), DataType.NativeType.text(), selSingle.getType()); + for (int selOrSlice = 0; selOrSlice < 3; selOrSlice++) + { + ColumnDefinitions.Definition selSlice = colDefIter.next(); + assertEquals(ref.getName() + ' ' + ref.getType(), ref.getType(), selSlice.getType()); + } + } + } + + @Test + public void testFrozenCollectionNestedAccess() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, m map<text, frozen<map<text, set<int>>>>)"); + + execute("INSERT INTO %s(k, m) VALUES (0, ?)", map("1", map("a", set(1, 2, 4), "b", set(3)), "2", map("a", set(2, 4)))); + + assertRows(execute("SELECT m[?] FROM %s WHERE k = 0", "1"), row(map("a", set(1, 2, 4), "b", set(3)))); + assertRows(execute("SELECT m[?][?] FROM %s WHERE k = 0", "1", "a"), row(set(1, 2, 4))); + assertRows(execute("SELECT m[?][?][?] FROM %s WHERE k = 0", "1", "a", 2), row(2)); + assertRows(execute("SELECT m[?][?][?..?] FROM %s WHERE k = 0", "1", "a", 2, 3), row(set(2))); + + // Checks it still work after flush + flush(); + + assertRows(execute("SELECT m[?] FROM %s WHERE k = 0", "1"), row(map("a", set(1, 2, 4), "b", set(3)))); + assertRows(execute("SELECT m[?][?] FROM %s WHERE k = 0", "1", "a"), row(set(1, 2, 4))); + assertRows(execute("SELECT m[?][?][?] FROM %s WHERE k = 0", "1", "a", 2), row(2)); + assertRows(execute("SELECT m[?][?][?..?] FROM %s WHERE k = 0", "1", "a", 2, 3), row(set(2))); + } + + @Test + public void testUDTAndCollectionNestedAccess() throws Throwable + { + String type = createType("CREATE TYPE %s (s set<int>, m map<text, text>)"); + + assertInvalidMessage("Non-frozen UDTs are not allowed inside collections", + "CREATE TABLE " + KEYSPACE + "t (k int PRIMARY KEY, v map<text, " + type + ">)"); + + String mapType = "map<text, frozen<" + type + ">>"; + for (boolean frozen : new boolean[]{false, true}) + { + mapType = frozen ? "frozen<" + mapType + ">" : mapType; + + createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + mapType + ")"); + + execute("INSERT INTO %s(k, v) VALUES (0, ?)", map("abc", userType("s", set(2, 4, 6), "m", map("a", "v1", "d", "v2")))); + + beforeAndAfterFlush(() -> + { + assertRows(execute("SELECT v[?].s FROM %s WHERE k = 0", "abc"), row(set(2, 4, 6))); + assertRows(execute("SELECT v[?].m[..?] FROM %s WHERE k = 0", "abc", "b"), row(map("a", "v1"))); + assertRows(execute("SELECT v[?].m[?] FROM %s WHERE k = 0", "abc", "d"), row("v2")); + }); + } + + assertInvalidMessage("Non-frozen UDTs with nested non-frozen collections are not supported", + "CREATE TABLE " + KEYSPACE + ".t (k int PRIMARY KEY, v " + type + ")"); + + type = createType("CREATE TYPE %s (s frozen<set<int>>, m frozen<map<text, text>>)"); + + for (boolean frozen : new boolean[]{false, true}) + { + type = frozen ? "frozen<" + type + ">" : type; + + createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + type + ")"); + + execute("INSERT INTO %s(k, v) VALUES (0, ?)", userType("s", set(2, 4, 6), "m", map("a", "v1", "d", "v2"))); + + beforeAndAfterFlush(() -> + { + assertRows(execute("SELECT v.s[?] FROM %s WHERE k = 0", 2), row(2)); + assertRows(execute("SELECT v.s[?..?] FROM %s WHERE k = 0", 2, 5), row(set(2, 4))); + assertRows(execute("SELECT v.s[..?] FROM %s WHERE k = 0", 3), row(set(2))); + assertRows(execute("SELECT v.m[..?] FROM %s WHERE k = 0", "b"), row(map("a", "v1"))); + assertRows(execute("SELECT v.m[?] FROM %s WHERE k = 0", "d"), row("v2")); + }); + } + } + + @Test + public void testMapOverlappingSlices() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, m map<int, int>)"); + + execute("INSERT INTO %s(k, m) VALUES (?, ?)", 0, map(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5)); + + flush(); + + assertRows(execute("SELECT m[7..8] FROM %s WHERE k=?", 0), + row(map())); + + assertRows(execute("SELECT m[0..3] FROM %s WHERE k=?", 0), + row(map(0, 0, 1, 1, 2, 2, 3, 3))); + + assertRows(execute("SELECT m[0..3], m[2..4] FROM %s WHERE k=?", 0), + row(map(0, 0, 1, 1, 2, 2, 3, 3), map(2, 2, 3, 3, 4, 4))); + + assertRows(execute("SELECT m, m[2..4] FROM %s WHERE k=?", 0), + row(map(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5), map(2, 2, 3, 3, 4, 4))); + + assertRows(execute("SELECT m[..3], m[3..4] FROM %s WHERE k=?", 0), + row(map(0, 0, 1, 1, 2, 2, 3, 3), map(3, 3, 4, 4))); + + assertRows(execute("SELECT m[1..3], m[2] FROM %s WHERE k=?", 0), + row(map(1, 1, 2, 2, 3, 3), 2)); + } + + @Test + public void testMapOverlappingSlicesWithDoubles() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, m map<double, double>)"); + + execute("INSERT INTO %s(k, m) VALUES (?, ?)", 0, map(0.0, 0.0, 1.1, 1.1, 2.2, 2.2, 3.0, 3.0, 4.4, 4.4, 5.5, 5.5)); + + flush(); + + assertRows(execute("SELECT m[0.0..3.0] FROM %s WHERE k=?", 0), + row(map(0.0, 0.0, 1.1, 1.1, 2.2, 2.2, 3.0, 3.0))); + + assertRows(execute("SELECT m[0...3.], m[2.2..4.4] FROM %s WHERE k=?", 0), + row(map(0.0, 0.0, 1.1, 1.1, 2.2, 2.2, 3.0, 3.0), map(2.2, 2.2, 3.0, 3.0, 4.4, 4.4))); + + assertRows(execute("SELECT m, m[2.2..4.4] FROM %s WHERE k=?", 0), + row(map(0.0, 0.0, 1.1, 1.1, 2.2, 2.2, 3.0, 3.0, 4.4, 4.4, 5.5, 5.5), map(2.2, 2.2, 3.0, 3.0, 4.4, 4.4))); + + assertRows(execute("SELECT m[..3.], m[3...4.4] FROM %s WHERE k=?", 0), + row(map(0.0, 0.0, 1.1, 1.1, 2.2, 2.2, 3.0, 3.0), map(3.0, 3.0, 4.4, 4.4))); + + assertRows(execute("SELECT m[1.1..3.0], m[2.2] FROM %s WHERE k=?", 0), + row(map(1.1, 1.1, 2.2, 2.2, 3.0, 3.0), 2.2)); + } + + @Test + public void testNestedAccessWithNestedMap() throws Throwable + { + createTable("CREATE TABLE %s (id text PRIMARY KEY, m map<float, frozen<map<int, text>>>)"); + + execute("INSERT INTO %s (id,m) VALUES ('1', {1: {2: 'one-two'}})"); + + flush(); + + assertRows(execute("SELECT m[1][2] FROM %s WHERE id = '1'"), + row("one-two")); + + assertRows(execute("SELECT m[1..][2] FROM %s WHERE id = '1'"), + row((Map) null)); + + assertRows(execute("SELECT m[1][..2] FROM %s WHERE id = '1'"), + row(map(2, "one-two"))); + + assertRows(execute("SELECT m[1..][..2] FROM %s WHERE id = '1'"), + row(map(1F, map(2, "one-two")))); + } ++ ++ @Test + public void testInsertingCollectionsWithInvalidElements() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, s frozen<set<tuple<int, text, double>>>)"); + assertInvalidMessage("Invalid remaining data after end of tuple value", + "INSERT INTO %s (k, s) VALUES (0, ?)", + set(tuple(1, "1", 1.0, 1), tuple(2, "2", 2.0, 2))); + + assertInvalidMessage("Invalid set literal for s: value (1, '1', 1.0, 1) is not of type frozen<tuple<int, text, double>>", + "INSERT INTO %s (k, s) VALUES (0, {(1, '1', 1.0, 1)})"); + + createTable("CREATE TABLE %s (k int PRIMARY KEY, l frozen<list<tuple<int, text, double>>>)"); + assertInvalidMessage("Invalid remaining data after end of tuple value", + "INSERT INTO %s (k, l) VALUES (0, ?)", + list(tuple(1, "1", 1.0, 1), tuple(2, "2", 2.0, 2))); + + assertInvalidMessage("Invalid list literal for l: value (1, '1', 1.0, 1) is not of type frozen<tuple<int, text, double>>", + "INSERT INTO %s (k, l) VALUES (0, [(1, '1', 1.0, 1)])"); + + createTable("CREATE TABLE %s (k int PRIMARY KEY, m frozen<map<tuple<int, text, double>, int>>)"); + assertInvalidMessage("Invalid remaining data after end of tuple value", + "INSERT INTO %s (k, m) VALUES (0, ?)", + map(tuple(1, "1", 1.0, 1), 1, tuple(2, "2", 2.0, 2), 2)); + + assertInvalidMessage("Invalid map literal for m: key (1, '1', 1.0, 1) is not of type frozen<tuple<int, text, double>>", + "INSERT INTO %s (k, m) VALUES (0, {(1, '1', 1.0, 1) : 1})"); + + createTable("CREATE TABLE %s (k int PRIMARY KEY, m frozen<map<int, tuple<int, text, double>>>)"); + assertInvalidMessage("Invalid remaining data after end of tuple value", + "INSERT INTO %s (k, m) VALUES (0, ?)", + map(1, tuple(1, "1", 1.0, 1), 2, tuple(2, "2", 2.0, 2))); + + assertInvalidMessage("Invalid map literal for m: value (1, '1', 1.0, 1) is not of type frozen<tuple<int, text, double>>", + "INSERT INTO %s (k, m) VALUES (0, {1 : (1, '1', 1.0, 1)})"); + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/10b397e2/test/unit/org/apache/cassandra/cql3/validation/entities/TupleTypeTest.java ---------------------------------------------------------------------- --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org