You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jm...@apache.org on 2015/06/24 18:14:58 UTC

[05/32] cassandra git commit: Migrate CQL tests from dtest to unit tests

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f797bfa4/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java
new file mode 100644
index 0000000..beed560
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/FrozenCollectionsTest.java
@@ -0,0 +1,1111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.cql3.validation.entities;
+
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.db.marshal.*;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class FrozenCollectionsTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUpClass()
+    {
+        DatabaseDescriptor.setPartitioner(new ByteOrderedPartitioner());
+    }
+
+    @Test
+    public void testPartitionKeyUsage() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k frozen<set<int>> PRIMARY KEY, v int)");
+
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", set(), 1);
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", set(1, 2, 3), 1);
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", set(4, 5, 6), 0);
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", set(7, 8, 9), 0);
+
+        // overwrite with an update
+        execute("UPDATE %s SET v=? WHERE k=?", 0, set());
+        execute("UPDATE %s SET v=? WHERE k=?", 0, set(1, 2, 3));
+
+        assertRows(execute("SELECT * FROM %s"),
+            row(set(), 0),
+            row(set(1, 2, 3), 0),
+            row(set(4, 5, 6), 0),
+            row(set(7, 8, 9), 0)
+        );
+
+        assertRows(execute("SELECT k FROM %s"),
+            row(set()),
+            row(set(1, 2, 3)),
+            row(set(4, 5, 6)),
+            row(set(7, 8, 9))
+        );
+
+        assertRows(execute("SELECT * FROM %s LIMIT 2"),
+                row(set(), 0),
+                row(set(1, 2, 3), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE k=?", set(4, 5, 6)),
+            row(set(4, 5, 6), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE k=?", set()),
+                row(set(), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE k IN ?", list(set(4, 5, 6), set())),
+                row(set(4, 5, 6), 0),
+                row(set(), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE token(k) >= token(?)", set(4, 5, 6)),
+                row(set(4, 5, 6), 0),
+                row(set(7, 8, 9), 0)
+        );
+
+        assertInvalid("INSERT INTO %s (k, v) VALUES (null, 0)");
+
+        execute("DELETE FROM %s WHERE k=?", set());
+        execute("DELETE FROM %s WHERE k=?", set(4, 5, 6));
+        assertRows(execute("SELECT * FROM %s"),
+            row(set(1, 2, 3), 0),
+            row(set(7, 8, 9), 0)
+        );
+    }
+
+    @Test
+    public void testNestedPartitionKeyUsage() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k frozen<map<set<int>, list<int>>> PRIMARY KEY, v int)");
+
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", map(), 1);
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", map(set(), list(1, 2, 3)), 0);
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", map(set(1, 2, 3), list(1, 2, 3)), 1);
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", map(set(4, 5, 6), list(1, 2, 3)), 0);
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", map(set(7, 8, 9), list(1, 2, 3)), 0);
+
+        // overwrite with an update
+        execute("UPDATE %s SET v=? WHERE k=?", 0, map());
+        execute("UPDATE %s SET v=? WHERE k=?", 0, map(set(1, 2, 3), list(1, 2, 3)));
+
+        assertRows(execute("SELECT * FROM %s"),
+            row(map(), 0),
+            row(map(set(), list(1, 2, 3)), 0),
+            row(map(set(1, 2, 3), list(1, 2, 3)), 0),
+            row(map(set(4, 5, 6), list(1, 2, 3)), 0),
+            row(map(set(7, 8, 9), list(1, 2, 3)), 0)
+        );
+
+        assertRows(execute("SELECT k FROM %s"),
+            row(map()),
+            row(map(set(), list(1, 2, 3))),
+            row(map(set(1, 2, 3), list(1, 2, 3))),
+            row(map(set(4, 5, 6), list(1, 2, 3))),
+            row(map(set(7, 8, 9), list(1, 2, 3)))
+        );
+
+        assertRows(execute("SELECT * FROM %s LIMIT 3"),
+            row(map(), 0),
+            row(map(set(), list(1, 2, 3)), 0),
+            row(map(set(1, 2, 3), list(1, 2, 3)), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE k=?", map(set(4, 5, 6), list(1, 2, 3))),
+            row(map(set(4, 5, 6), list(1, 2, 3)), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE k=?", map()),
+                row(map(), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE k=?", map(set(), list(1, 2, 3))),
+                row(map(set(), list(1, 2, 3)), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE k IN ?", list(map(set(4, 5, 6), list(1, 2, 3)), map(), map(set(), list(1, 2, 3)))),
+            row(map(set(4, 5, 6), list(1, 2, 3)), 0),
+            row(map(), 0),
+            row(map(set(), list(1, 2, 3)), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE token(k) >= token(?)", map(set(4, 5, 6), list(1, 2, 3))),
+            row(map(set(4, 5, 6), list(1, 2, 3)), 0),
+            row(map(set(7, 8, 9), list(1, 2, 3)), 0)
+        );
+
+        execute("DELETE FROM %s WHERE k=?", map());
+        execute("DELETE FROM %s WHERE k=?", map(set(), list(1, 2, 3)));
+        execute("DELETE FROM %s WHERE k=?", map(set(4, 5, 6), list(1, 2, 3)));
+        assertRows(execute("SELECT * FROM %s"),
+            row(map(set(1, 2, 3), list(1, 2, 3)), 0),
+            row(map(set(7, 8, 9), list(1, 2, 3)), 0)
+        );
+
+    }
+
+    @Test
+    public void testClusteringKeyUsage() throws Throwable
+    {
+        for (String option : Arrays.asList("", " WITH COMPACT STORAGE"))
+        {
+            createTable("CREATE TABLE %s (a int, b frozen<set<int>>, c int, PRIMARY KEY (a, b))" + option);
+
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, set(), 1);
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, set(1, 2, 3), 1);
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, set(4, 5, 6), 0);
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, set(7, 8, 9), 0);
+
+            // overwrite with an update
+            execute("UPDATE %s SET c=? WHERE a=? AND b=?", 0, 0, set());
+            execute("UPDATE %s SET c=? WHERE a=? AND b=?", 0, 0, set(1, 2, 3));
+
+            assertRows(execute("SELECT * FROM %s"),
+                row(0, set(), 0),
+                row(0, set(1, 2, 3), 0),
+                row(0, set(4, 5, 6), 0),
+                row(0, set(7, 8, 9), 0)
+            );
+
+            assertRows(execute("SELECT b FROM %s"),
+                row(set()),
+                row(set(1, 2, 3)),
+                row(set(4, 5, 6)),
+                row(set(7, 8, 9))
+            );
+
+            assertRows(execute("SELECT * FROM %s LIMIT 2"),
+                row(0, set(), 0),
+                row(0, set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b=?", 0, set(4, 5, 6)),
+                row(0, set(4, 5, 6), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b=?", 0, set()),
+                row(0, set(), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b IN ?", 0, list(set(4, 5, 6), set())),
+                row(0, set(), 0),
+                row(0, set(4, 5, 6), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b > ?", 0, set(4, 5, 6)),
+                row(0, set(7, 8, 9), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b >= ?", 0, set(4, 5, 6)),
+                row(0, set(4, 5, 6), 0),
+                row(0, set(7, 8, 9), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b < ?", 0, set(4, 5, 6)),
+                row(0, set(), 0),
+                row(0, set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b <= ?", 0, set(4, 5, 6)),
+                row(0, set(), 0),
+                row(0, set(1, 2, 3), 0),
+                row(0, set(4, 5, 6), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b > ? AND b <= ?", 0, set(1, 2, 3), set(4, 5, 6)),
+                row(0, set(4, 5, 6), 0)
+            );
+
+            execute("DELETE FROM %s WHERE a=? AND b=?", 0, set());
+            execute("DELETE FROM %s WHERE a=? AND b=?", 0, set(4, 5, 6));
+            assertRows(execute("SELECT * FROM %s"),
+                row(0, set(1, 2, 3), 0),
+                row(0, set(7, 8, 9), 0)
+            );
+        }
+    }
+
+    @Test
+    public void testNestedClusteringKeyUsage() throws Throwable
+    {
+        for (String option : Arrays.asList("", " WITH COMPACT STORAGE"))
+        {
+            createTable("CREATE TABLE %s (a int, b frozen<map<set<int>, list<int>>>, c frozen<set<int>>, d int, PRIMARY KEY (a, b, c))" + option);
+
+            execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, map(), set(), 0);
+            execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, map(set(), list(1, 2, 3)), set(), 0);
+            execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0);
+            execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3), 0);
+            execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3), 0);
+
+            assertRows(execute("SELECT * FROM %s"),
+                row(0, map(), set(), 0),
+                row(0, map(set(), list(1, 2, 3)), set(), 0),
+                row(0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0),
+                row(0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3), 0),
+                row(0, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT b FROM %s"),
+                row(map()),
+                row(map(set(), list(1, 2, 3))),
+                row(map(set(1, 2, 3), list(1, 2, 3))),
+                row(map(set(4, 5, 6), list(1, 2, 3))),
+                row(map(set(7, 8, 9), list(1, 2, 3)))
+            );
+
+            assertRows(execute("SELECT c FROM %s"),
+                row(set()),
+                row(set()),
+                row(set(1, 2, 3)),
+                row(set(1, 2, 3)),
+                row(set(1, 2, 3))
+            );
+
+            assertRows(execute("SELECT * FROM %s LIMIT 3"),
+                row(0, map(), set(), 0),
+                row(0, map(set(), list(1, 2, 3)), set(), 0),
+                row(0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=0 ORDER BY b DESC LIMIT 4"),
+                row(0, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3), 0),
+                row(0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3), 0),
+                row(0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0),
+                row(0, map(set(), list(1, 2, 3)), set(), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b=?", 0, map()),
+                row(0, map(), set(), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b=?", 0, map(set(), list(1, 2, 3))),
+                row(0, map(set(), list(1, 2, 3)), set(), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b=?", 0, map(set(1, 2, 3), list(1, 2, 3))),
+                row(0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b=? AND c=?", 0, map(set(), list(1, 2, 3)), set()),
+                    row(0, map(set(), list(1, 2, 3)), set(), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND (b, c) IN ?", 0, list(tuple(map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3)),
+                                                                                     tuple(map(), set()))),
+                row(0, map(), set(), 0),
+                row(0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b > ?", 0, map(set(4, 5, 6), list(1, 2, 3))),
+                row(0, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b >= ?", 0, map(set(4, 5, 6), list(1, 2, 3))),
+                row(0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3), 0),
+                row(0, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b < ?", 0, map(set(4, 5, 6), list(1, 2, 3))),
+                row(0, map(), set(), 0),
+                row(0, map(set(), list(1, 2, 3)), set(), 0),
+                row(0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b <= ?", 0, map(set(4, 5, 6), list(1, 2, 3))),
+                row(0, map(), set(), 0),
+                row(0, map(set(), list(1, 2, 3)), set(), 0),
+                row(0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0),
+                row(0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=? AND b > ? AND b <= ?", 0, map(set(1, 2, 3), list(1, 2, 3)), map(set(4, 5, 6), list(1, 2, 3))),
+                row(0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+
+            execute("DELETE FROM %s WHERE a=? AND b=? AND c=?", 0, map(), set());
+            assertEmpty(execute("SELECT * FROM %s WHERE a=? AND b=? AND c=?", 0, map(), set()));
+
+            execute("DELETE FROM %s WHERE a=? AND b=? AND c=?", 0, map(set(), list(1, 2, 3)), set());
+            assertEmpty(execute("SELECT * FROM %s WHERE a=? AND b=? AND c=?", 0, map(set(), list(1, 2, 3)), set()));
+
+            execute("DELETE FROM %s WHERE a=? AND b=? AND c=?", 0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3));
+            assertEmpty(execute("SELECT * FROM %s WHERE a=? AND b=? AND c=?", 0, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3)));
+
+            assertRows(execute("SELECT * FROM %s"),
+                    row(0, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3), 0),
+                    row(0, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3), 0)
+            );
+        }
+    }
+
+    @Test
+    public void testNormalColumnUsage() throws Throwable
+    {
+        for (String option : Arrays.asList("", " WITH COMPACT STORAGE"))
+        {
+            createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<set<int>, list<int>>>, c frozen<set<int>>)" + option);
+
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 0, map(), set());
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 1, map(set(), list(99999, 999999, 99999)), set());
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 2, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3));
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 3, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3));
+            execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 4, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3));
+
+            // overwrite with update
+            execute ("UPDATE %s SET b=? WHERE a=?", map(set(), list(1, 2, 3)), 1);
+
+            assertRows(execute("SELECT * FROM %s"),
+                row(0, map(), set()),
+                row(1, map(set(), list(1, 2, 3)), set()),
+                row(2, map(set(1, 2, 3), list(1, 2, 3)), set(1, 2, 3)),
+                row(3, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3)),
+                row(4, map(set(7, 8, 9), list(1, 2, 3)), set(1, 2, 3))
+            );
+
+            assertRows(execute("SELECT b FROM %s"),
+                row(map()),
+                row(map(set(), list(1, 2, 3))),
+                row(map(set(1, 2, 3), list(1, 2, 3))),
+                row(map(set(4, 5, 6), list(1, 2, 3))),
+                row(map(set(7, 8, 9), list(1, 2, 3)))
+            );
+
+            assertRows(execute("SELECT c FROM %s"),
+                row(set()),
+                row(set()),
+                row(set(1, 2, 3)),
+                row(set(1, 2, 3)),
+                row(set(1, 2, 3))
+            );
+
+            assertRows(execute("SELECT * FROM %s WHERE a=?", 3),
+                row(3, map(set(4, 5, 6), list(1, 2, 3)), set(1, 2, 3))
+            );
+
+            execute("UPDATE %s SET b=? WHERE a=?", null, 1);
+            assertRows(execute("SELECT * FROM %s WHERE a=?", 1),
+                row(1, null, set())
+            );
+
+            execute("UPDATE %s SET b=? WHERE a=?", map(), 1);
+            assertRows(execute("SELECT * FROM %s WHERE a=?", 1),
+                row(1, map(), set())
+            );
+
+            execute("UPDATE %s SET c=? WHERE a=?", null, 2);
+            assertRows(execute("SELECT * FROM %s WHERE a=?", 2),
+                row(2, map(set(1, 2, 3), list(1, 2, 3)), null)
+            );
+
+            execute("UPDATE %s SET c=? WHERE a=?", set(), 2);
+            assertRows(execute("SELECT * FROM %s WHERE a=?", 2),
+                    row(2, map(set(1, 2, 3), list(1, 2, 3)), set())
+            );
+
+            execute("DELETE b FROM %s WHERE a=?", 3);
+            assertRows(execute("SELECT * FROM %s WHERE a=?", 3),
+                row(3, null, set(1, 2, 3))
+            );
+
+            execute("DELETE c FROM %s WHERE a=?", 4);
+            assertRows(execute("SELECT * FROM %s WHERE a=?", 4),
+                row(4, map(set(7, 8, 9), list(1, 2, 3)), null)
+            );
+        }
+    }
+
+    @Test
+    public void testStaticColumnUsage() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, c frozen<map<set<int>, list<int>>> static, d int, PRIMARY KEY (a, b))");
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, map(), 0);
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, map(), 0);
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 0, map(set(), list(1, 2, 3)), 0);
+        execute("INSERT INTO %s (a, b, d) VALUES (?, ?, ?)", 1, 1, 0);
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 2, 0, map(set(1, 2, 3), list(1, 2, 3)), 0);
+
+        assertRows(execute("SELECT * FROM %s"),
+            row(0, 0, map(), 0),
+            row(0, 1, map(), 0),
+            row(1, 0, map(set(), list(1, 2, 3)), 0),
+            row(1, 1, map(set(), list(1, 2, 3)), 0),
+            row(2, 0, map(set(1, 2, 3), list(1, 2, 3)), 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE a=? AND b=?", 0, 1),
+            row(0, 1, map(), 0)
+        );
+
+        execute("DELETE c FROM %s WHERE a=?", 0);
+        assertRows(execute("SELECT * FROM %s"),
+                row(0, 0, null, 0),
+                row(0, 1, null, 0),
+                row(1, 0, map(set(), list(1, 2, 3)), 0),
+                row(1, 1, map(set(), list(1, 2, 3)), 0),
+                row(2, 0, map(set(1, 2, 3), list(1, 2, 3)), 0)
+        );
+
+        execute("DELETE FROM %s WHERE a=?", 0);
+        assertRows(execute("SELECT * FROM %s"),
+                row(1, 0, map(set(), list(1, 2, 3)), 0),
+                row(1, 1, map(set(), list(1, 2, 3)), 0),
+                row(2, 0, map(set(1, 2, 3), list(1, 2, 3)), 0)
+        );
+
+        execute("UPDATE %s SET c=? WHERE a=?", map(set(1, 2, 3), list(1, 2, 3)), 1);
+        assertRows(execute("SELECT * FROM %s"),
+                row(1, 0, map(set(1, 2, 3), list(1, 2, 3)), 0),
+                row(1, 1, map(set(1, 2, 3), list(1, 2, 3)), 0),
+                row(2, 0, map(set(1, 2, 3), list(1, 2, 3)), 0)
+        );
+    }
+
+    private void assertInvalidCreateWithMessage(String createTableStatement, String errorMessage) throws Throwable
+    {
+         try
+        {
+            createTableMayThrow(createTableStatement);
+            Assert.fail("Expected CREATE TABLE statement to error: " + createTableStatement);
+        }
+        catch (InvalidRequestException | ConfigurationException | SyntaxException ex)
+        {
+            Assert.assertTrue("Expected error message to contain '" + errorMessage + "', but got '" + ex.getMessage() + "'",
+                    ex.getMessage().contains(errorMessage));
+        }
+    }
+
+    private void assertInvalidAlterWithMessage(String createTableStatement, String errorMessage) throws Throwable
+    {
+        try
+        {
+            alterTableMayThrow(createTableStatement);
+            Assert.fail("Expected CREATE TABLE statement to error: " + createTableStatement);
+        }
+        catch (InvalidRequestException | ConfigurationException ex)
+        {
+            Assert.assertTrue("Expected error message to contain '" + errorMessage + "', but got '" + ex.getMessage() + "'",
+                    ex.getMessage().contains(errorMessage));
+        }
+    }
+
+    @Test
+    public void testInvalidOperations() throws Throwable
+    {
+        // lists
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, l frozen<list<int>>)");
+        assertInvalid("UPDATE %s SET l[?]=? WHERE k=?", 0, 0, 0);
+        assertInvalid("UPDATE %s SET l = ? + l WHERE k=?", list(0), 0);
+        assertInvalid("UPDATE %s SET l = l + ? WHERE k=?", list(4), 0);
+        assertInvalid("UPDATE %s SET l = l - ? WHERE k=?", list(3), 0);
+        assertInvalid("DELETE l[?] FROM %s WHERE k=?", 0, 0);
+
+        // sets
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, s frozen<set<int>>)");
+        assertInvalid("UPDATE %s SET s = s + ? WHERE k=?", set(0), 0);
+        assertInvalid("UPDATE %s SET s = s - ? WHERE k=?", set(3), 0);
+
+        // maps
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, m frozen<map<int, int>>)");
+        assertInvalid("UPDATE %s SET m[?]=? WHERE k=?", 0, 0, 0);
+        assertInvalid("UPDATE %s SET m = m + ? WHERE k=?", map(4, 4), 0);
+        assertInvalid("DELETE m[?] FROM %s WHERE k=?", 0, 0);
+
+        assertInvalidCreateWithMessage("CREATE TABLE %s (k int PRIMARY KEY, t set<set<int>>)",
+                "Non-frozen collections are not allowed inside collections");
+
+        assertInvalidCreateWithMessage("CREATE TABLE %s (k int PRIMARY KEY, t frozen<set<counter>>)",
+                                       "Counters are not allowed inside collections");
+
+        assertInvalidCreateWithMessage("CREATE TABLE %s (k int PRIMARY KEY, t frozen<text>)",
+                "frozen<> is only allowed on collections, tuples, and user-defined types");
+    }
+
+    @Test
+    public void testAltering() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b frozen<list<int>>, c frozen<list<int>>, PRIMARY KEY (a, b))");
+
+        alterTable("ALTER TABLE %s ALTER c TYPE frozen<list<blob>>");
+
+        assertInvalidAlterWithMessage("ALTER TABLE %s ALTER b TYPE frozen<list<blob>>",
+                                      "types are not order-compatible");
+
+        assertInvalidAlterWithMessage("ALTER TABLE %s ALTER b TYPE list<int>",
+                                      "types are not order-compatible");
+
+        assertInvalidAlterWithMessage("ALTER TABLE %s ALTER c TYPE list<blob>",
+                                      "types are incompatible");
+
+        alterTable("ALTER TABLE %s DROP c");
+        alterTable("ALTER TABLE %s ADD c frozen<set<int>>");
+        assertInvalidAlterWithMessage("ALTER TABLE %s ALTER c TYPE frozen<set<blob>>",
+                                      "types are incompatible");
+
+        alterTable("ALTER TABLE %s DROP c");
+        alterTable("ALTER TABLE %s ADD c frozen<map<int, int>>");
+        assertInvalidAlterWithMessage("ALTER TABLE %s ALTER c TYPE frozen<map<blob, int>>",
+                                      "types are incompatible");
+        alterTable("ALTER TABLE %s ALTER c TYPE frozen<map<int, blob>>");
+    }
+
+    private void assertInvalidIndexCreationWithMessage(String statement, String errorMessage) throws Throwable
+    {
+        try
+        {
+            createIndexMayThrow(statement);
+            Assert.fail("Expected index creation to fail: " + statement);
+        }
+        catch (InvalidRequestException ex)
+        {
+            Assert.assertTrue("Expected error message to contain '" + errorMessage + "', but got '" + ex.getMessage() + "'",
+                              ex.getMessage().contains(errorMessage));
+        }
+    }
+
+    @Test
+    public void testSecondaryIndex() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a frozen<map<int, text>> PRIMARY KEY, b frozen<map<int, text>>)");
+
+        // for now, we don't support indexing values or keys of collections in the primary key
+        assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (full(a))", "Cannot create secondary index on partition key column");
+        assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (keys(a))", "Cannot create index on keys of frozen<map> column");
+        assertInvalidIndexCreationWithMessage("CREATE INDEX ON %s (keys(b))", "Cannot create index on keys of frozen<map> column");
+
+        createTable("CREATE TABLE %s (a int, b frozen<list<int>>, c frozen<set<int>>, d frozen<map<int, text>>, PRIMARY KEY (a, b))");
+
+        createIndex("CREATE INDEX ON %s (full(b))");
+        createIndex("CREATE INDEX ON %s (full(c))");
+        createIndex("CREATE INDEX ON %s (full(d))");
+
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, list(1, 2, 3), set(1, 2, 3), map(1, "a"));
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, list(4, 5, 6), set(1, 2, 3), map(1, "a"));
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, list(1, 2, 3), set(4, 5, 6), map(2, "b"));
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, list(4, 5, 6), set(4, 5, 6), map(2, "b"));
+
+        // CONTAINS KEY doesn't work on non-maps
+        assertInvalidMessage("Cannot use CONTAINS KEY on non-map column",
+                             "SELECT * FROM %s WHERE b CONTAINS KEY ?", 1);
+
+        assertInvalidMessage("Cannot use CONTAINS KEY on non-map column",
+                             "SELECT * FROM %s WHERE b CONTAINS KEY ? ALLOW FILTERING", 1);
+
+        assertInvalidMessage("Cannot use CONTAINS KEY on non-map column",
+                             "SELECT * FROM %s WHERE c CONTAINS KEY ?", 1);
+
+        // normal indexes on frozen collections don't support CONTAINS or CONTAINS KEY
+        assertInvalidMessage("Cannot restrict column \"b\" by a CONTAINS relation without a secondary index",
+                             "SELECT * FROM %s WHERE b CONTAINS ?", 1);
+
+        assertInvalidMessage("Cannot restrict column \"b\" by a CONTAINS relation without a secondary index",
+                             "SELECT * FROM %s WHERE b CONTAINS ? ALLOW FILTERING", 1);
+
+        assertInvalidMessage("No secondary indexes on the restricted columns support the provided operator",
+                             "SELECT * FROM %s WHERE d CONTAINS KEY ?", 1);
+
+        assertInvalidMessage("No secondary indexes on the restricted columns support the provided operator",
+                             "SELECT * FROM %s WHERE d CONTAINS KEY ? ALLOW FILTERING", 1);
+
+        assertInvalidMessage("Cannot restrict column \"b\" by a CONTAINS relation without a secondary index",
+                             "SELECT * FROM %s WHERE b CONTAINS ? AND d CONTAINS KEY ? ALLOW FILTERING", 1, 1);
+
+        // index lookup on b
+        assertRows(execute("SELECT * FROM %s WHERE b=?", list(1, 2, 3)),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a")),
+            row(1, list(1, 2, 3), set(4, 5, 6), map(2, "b"))
+        );
+
+        assertEmpty(execute("SELECT * FROM %s WHERE b=?", list(-1)));
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE b=? AND c=?", list(1, 2, 3), set(4, 5, 6));
+        assertRows(execute("SELECT * FROM %s WHERE b=? AND c=? ALLOW FILTERING", list(1, 2, 3), set(4, 5, 6)),
+            row(1, list(1, 2, 3), set(4, 5, 6), map(2, "b"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE b=? AND c CONTAINS ?", list(1, 2, 3), 5);
+        assertRows(execute("SELECT * FROM %s WHERE b=? AND c CONTAINS ? ALLOW FILTERING", list(1, 2, 3), 5),
+            row(1, list(1, 2, 3), set(4, 5, 6), map(2, "b"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE b=? AND d=?", list(1, 2, 3), map(1, "a"));
+        assertRows(execute("SELECT * FROM %s WHERE b=? AND d=? ALLOW FILTERING", list(1, 2, 3), map(1, "a")),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE b=? AND d CONTAINS ?", list(1, 2, 3), "a");
+        assertRows(execute("SELECT * FROM %s WHERE b=? AND d CONTAINS ? ALLOW FILTERING", list(1, 2, 3), "a"),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE b=? AND d CONTAINS KEY ?", list(1, 2, 3), 1);
+        assertRows(execute("SELECT * FROM %s WHERE b=? AND d CONTAINS KEY ? ALLOW FILTERING", list(1, 2, 3), 1),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        // index lookup on c
+        assertRows(execute("SELECT * FROM %s WHERE c=?", set(1, 2, 3)),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a")),
+            row(0, list(4, 5, 6), set(1, 2, 3), map(1, "a"))
+        );
+
+        // ordering of c should not matter
+        assertRows(execute("SELECT * FROM %s WHERE c=?", set(2, 1, 3)),
+                row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a")),
+                row(0, list(4, 5, 6), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertEmpty(execute("SELECT * FROM %s WHERE c=?", set(-1)));
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE c=? AND b=?", set(1, 2, 3), list(1, 2, 3));
+        assertRows(execute("SELECT * FROM %s WHERE c=? AND b=? ALLOW FILTERING", set(1, 2, 3), list(1, 2, 3)),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE c=? AND b CONTAINS ?", set(1, 2, 3), 1);
+        assertRows(execute("SELECT * FROM %s WHERE c=? AND b CONTAINS ? ALLOW FILTERING", set(1, 2, 3), 1),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE c=? AND d = ?", set(1, 2, 3), map(1, "a"));
+        assertRows(execute("SELECT * FROM %s WHERE c=? AND d = ? ALLOW FILTERING", set(1, 2, 3), map(1, "a")),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a")),
+            row(0, list(4, 5, 6), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE c=? AND d CONTAINS ?", set(1, 2, 3), "a");
+        assertRows(execute("SELECT * FROM %s WHERE c=? AND d CONTAINS ? ALLOW FILTERING", set(1, 2, 3), "a"),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a")),
+            row(0, list(4, 5, 6), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE c=? AND d CONTAINS KEY ?", set(1, 2, 3), 1);
+        assertRows(execute("SELECT * FROM %s WHERE c=? AND d CONTAINS KEY ? ALLOW FILTERING", set(1, 2, 3), 1),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a")),
+            row(0, list(4, 5, 6), set(1, 2, 3), map(1, "a"))
+        );
+
+        // index lookup on d
+        assertRows(execute("SELECT * FROM %s WHERE d=?", map(1, "a")),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a")),
+            row(0, list(4, 5, 6), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE d=?", map(2, "b")),
+            row(1, list(1, 2, 3), set(4, 5, 6), map(2, "b")),
+            row(1, list(4, 5, 6), set(4, 5, 6), map(2, "b"))
+        );
+
+        assertEmpty(execute("SELECT * FROM %s WHERE d=?", map(3, "c")));
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE d=? AND c=?", map(1, "a"), set(1, 2, 3));
+        assertRows(execute("SELECT * FROM %s WHERE d=? AND b=? ALLOW FILTERING", map(1, "a"), list(1, 2, 3)),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE d=? AND b CONTAINS ?", map(1, "a"), 3);
+        assertRows(execute("SELECT * FROM %s WHERE d=? AND b CONTAINS ? ALLOW FILTERING", map(1, "a"), 3),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertInvalidMessage("ALLOW FILTERING", "SELECT * FROM %s WHERE d=? AND b=? AND c=?", map(1, "a"), list(1, 2, 3), set(1, 2, 3));
+        assertRows(execute("SELECT * FROM %s WHERE d=? AND b=? AND c=? ALLOW FILTERING", map(1, "a"), list(1, 2, 3), set(1, 2, 3)),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE d=? AND b CONTAINS ? AND c CONTAINS ? ALLOW FILTERING", map(1, "a"), 2, 2),
+            row(0, list(1, 2, 3), set(1, 2, 3), map(1, "a"))
+        );
+
+        execute("DELETE d FROM %s WHERE a=? AND b=?", 0, list(1, 2, 3));
+        assertRows(execute("SELECT * FROM %s WHERE d=?", map(1, "a")),
+            row(0, list(4, 5, 6), set(1, 2, 3), map(1, "a"))
+        );
+    }
+
+    /** Test for CASSANDRA-8302 */
+    @Test
+    public void testClusteringColumnFiltering() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b frozen<map<int, int>>, c int, d int, PRIMARY KEY (a, b, c))");
+        createIndex("CREATE INDEX c_index ON %s (c)");
+        createIndex("CREATE INDEX d_index ON %s (d)");
+
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, map(0, 0, 1, 1), 0, 0);
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, map(1, 1, 2, 2), 0, 0);
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, map(0, 0, 1, 1), 0, 0);
+        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, map(1, 1, 2, 2), 0, 0);
+
+        assertRows(execute("SELECT * FROM %s WHERE d=? AND b CONTAINS ? ALLOW FILTERING", 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0),
+                row(1, map(0, 0, 1, 1), 0, 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE d=? AND b CONTAINS KEY ? ALLOW FILTERING", 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0),
+                row(1, map(0, 0, 1, 1), 0, 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE a=? AND d=? AND b CONTAINS ? ALLOW FILTERING", 0, 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0)
+        );
+        assertRows(execute("SELECT * FROM %s WHERE a=? AND d=? AND b CONTAINS KEY ? ALLOW FILTERING", 0, 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0)
+        );
+
+        dropIndex("DROP INDEX %s.d_index");
+
+        assertRows(execute("SELECT * FROM %s WHERE c=? AND b CONTAINS ? ALLOW FILTERING", 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0),
+                row(1, map(0, 0, 1, 1), 0, 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE c=? AND b CONTAINS KEY ? ALLOW FILTERING", 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0),
+                row(1, map(0, 0, 1, 1), 0, 0)
+        );
+
+        assertRows(execute("SELECT * FROM %s WHERE a=? AND c=? AND b CONTAINS ? ALLOW FILTERING", 0, 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0)
+        );
+        assertRows(execute("SELECT * FROM %s WHERE a=? AND c=? AND b CONTAINS KEY ? ALLOW FILTERING", 0, 0, 0),
+                row(0, map(0, 0, 1, 1), 0, 0)
+        );
+    }
+
+    @Test
+    public void testFrozenListInMap() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, m map<frozen<list<int>>, int>)");
+
+        execute("INSERT INTO %s (k, m) VALUES (1, {[1, 2, 3] : 1})");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(list(1, 2, 3), 1)));
+
+        execute("UPDATE %s SET m[[1, 2, 3]]=2 WHERE k=1");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(list(1, 2, 3), 2)));
+
+        execute("UPDATE %s SET m = m + ? WHERE k=1", map(list(4, 5, 6), 3));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1,
+                    map(list(1, 2, 3), 2,
+                        list(4, 5, 6), 3)));
+
+        execute("DELETE m[[1, 2, 3]] FROM %s WHERE k = 1");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(list(4, 5, 6), 3)));
+    }
+
+    @Test
+    public void testFrozenListInSet() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, s set<frozen<list<int>>>)");
+
+        execute("INSERT INTO %s (k, s) VALUES (1, {[1, 2, 3]})");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(list(1, 2, 3)))
+        );
+
+        execute("UPDATE %s SET s = s + ? WHERE k=1", set(list(4, 5, 6)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(list(1, 2, 3), list(4, 5, 6)))
+        );
+
+        execute("UPDATE %s SET s = s - ? WHERE k=1", set(list(4, 5, 6)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(list(1, 2, 3)))
+        );
+
+        execute("DELETE s[[1, 2, 3]] FROM %s WHERE k = 1");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, null)
+        );
+    }
+
+    @Test
+    public void testFrozenListInList() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, l list<frozen<list<int>>>)");
+
+        execute("INSERT INTO %s (k, l) VALUES (1, [[1, 2, 3]])");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(list(1, 2, 3)))
+        );
+
+        execute("UPDATE %s SET l[?]=? WHERE k=1", 0, list(4, 5, 6));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(list(4, 5, 6)))
+        );
+
+        execute("UPDATE %s SET l = ? + l WHERE k=1", list(list(1, 2, 3)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(list(1, 2, 3), list(4, 5, 6)))
+        );
+
+        execute("UPDATE %s SET l = l + ? WHERE k=1", list(list(7, 8, 9)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(list(1, 2, 3), list(4, 5, 6), list(7, 8, 9)))
+        );
+
+        execute("UPDATE %s SET l = l - ? WHERE k=1", list(list(4, 5, 6)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(list(1, 2, 3), list(7, 8, 9)))
+        );
+
+        execute("DELETE l[0] FROM %s WHERE k = 1");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(list(7, 8, 9)))
+        );
+    }
+
+    @Test
+    public void testFrozenMapInMap() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, m map<frozen<map<int, int>>, int>)");
+
+        execute("INSERT INTO %s (k, m) VALUES (1, {{1 : 1, 2 : 2} : 1})");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(map(1, 1, 2, 2), 1)));
+
+        execute("UPDATE %s SET m[?]=2 WHERE k=1", map(1, 1, 2, 2));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(map(1, 1, 2, 2), 2)));
+
+        execute("UPDATE %s SET m = m + ? WHERE k=1", map(map(3, 3, 4, 4), 3));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1,
+                    map(map(1, 1, 2, 2), 2,
+                        map(3, 3, 4, 4), 3)));
+
+        execute("DELETE m[?] FROM %s WHERE k = 1", map(1, 1, 2, 2));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(map(3, 3, 4, 4), 3)));
+    }
+
+    @Test
+    public void testFrozenMapInSet() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, s set<frozen<map<int, int>>>)");
+
+        execute("INSERT INTO %s (k, s) VALUES (1, {{1 : 1, 2 : 2}})");
+
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(map(1, 1, 2, 2)))
+        );
+
+        execute("UPDATE %s SET s = s + ? WHERE k=1", set(map(3, 3, 4, 4)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(map(1, 1, 2, 2), map(3, 3, 4, 4)))
+        );
+
+        execute("UPDATE %s SET s = s - ? WHERE k=1", set(map(3, 3, 4, 4)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(map(1, 1, 2, 2)))
+        );
+
+        execute("DELETE s[?] FROM %s WHERE k = 1", map(1, 1, 2, 2));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, null)
+        );
+    }
+
+    @Test
+    public void testFrozenMapInList() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, l list<frozen<map<int, int>>>)");
+
+        execute("INSERT INTO %s (k, l) VALUES (1, [{1 : 1, 2 : 2}])");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(map(1, 1, 2, 2)))
+        );
+
+        execute("UPDATE %s SET l[?]=? WHERE k=1", 0, map(3, 3, 4, 4));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(map(3, 3, 4, 4)))
+        );
+
+        execute("UPDATE %s SET l = ? + l WHERE k=1", list(map(1, 1, 2, 2)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(map(1, 1, 2, 2), map(3, 3, 4, 4)))
+        );
+
+        execute("UPDATE %s SET l = l + ? WHERE k=1", list(map(5, 5, 6, 6)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(map(1, 1, 2, 2), map(3, 3, 4, 4), map(5, 5, 6, 6)))
+        );
+
+        execute("UPDATE %s SET l = l - ? WHERE k=1", list(map(3, 3, 4, 4)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(map(1, 1, 2, 2), map(5, 5, 6, 6)))
+        );
+
+        execute("DELETE l[0] FROM %s WHERE k = 1");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(map(5, 5, 6, 6)))
+        );
+    }
+
+    @Test
+    public void testFrozenSetInMap() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, m map<frozen<set<int>>, int>)");
+
+        execute("INSERT INTO %s (k, m) VALUES (1, {{1, 2, 3} : 1})");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(set(1, 2, 3), 1)));
+
+        execute("UPDATE %s SET m[?]=2 WHERE k=1", set(1, 2, 3));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(set(1, 2, 3), 2)));
+
+        execute("UPDATE %s SET m = m + ? WHERE k=1", map(set(4, 5, 6), 3));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1,
+                    map(set(1, 2, 3), 2,
+                        set(4, 5, 6), 3)));
+
+        execute("DELETE m[?] FROM %s WHERE k = 1", set(1, 2, 3));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, map(set(4, 5, 6), 3)));
+    }
+
+    @Test
+    public void testFrozenSetInSet() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, s set<frozen<set<int>>>)");
+
+        execute("INSERT INTO %s (k, s) VALUES (1, {{1, 2, 3}})");
+
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(set(1, 2, 3)))
+        );
+
+        execute("UPDATE %s SET s = s + ? WHERE k=1", set(set(4, 5, 6)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(set(1, 2, 3), set(4, 5, 6)))
+        );
+
+        execute("UPDATE %s SET s = s - ? WHERE k=1", set(set(4, 5, 6)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, set(set(1, 2, 3)))
+        );
+
+        execute("DELETE s[?] FROM %s WHERE k = 1", set(1, 2, 3));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, null)
+        );
+    }
+
+    @Test
+    public void testFrozenSetInList() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int primary key, l list<frozen<set<int>>>)");
+
+        execute("INSERT INTO %s (k, l) VALUES (1, [{1, 2, 3}])");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(set(1, 2, 3)))
+        );
+
+        execute("UPDATE %s SET l[?]=? WHERE k=1", 0, set(4, 5, 6));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(set(4, 5, 6)))
+        );
+
+        execute("UPDATE %s SET l = ? + l WHERE k=1", list(set(1, 2, 3)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(set(1, 2, 3), set(4, 5, 6)))
+        );
+
+        execute("UPDATE %s SET l = l + ? WHERE k=1", list(set(7, 8, 9)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(set(1, 2, 3), set(4, 5, 6), set(7, 8, 9)))
+        );
+
+        execute("UPDATE %s SET l = l - ? WHERE k=1", list(set(4, 5, 6)));
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(set(1, 2, 3), set(7, 8, 9)))
+        );
+
+        execute("DELETE l[0] FROM %s WHERE k = 1");
+        assertRows(execute("SELECT * FROM %s WHERE k = 1"),
+                row(1, list(set(7, 8, 9)))
+        );
+    }
+
+    @Test
+    public void testUserDefinedTypes() throws Throwable
+    {
+        String myType = createType("CREATE TYPE %s (a set<int>, b tuple<list<int>>)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v frozen<" + myType + ">)");
+        execute("INSERT INTO %s (k, v) VALUES (?, {a: ?, b: ?})", 0, set(1, 2, 3), tuple(list(1, 2, 3)));
+        assertRows(execute("SELECT v.a, v.b FROM %s WHERE k=?", 0),
+            row(set(1, 2, 3), tuple(list(1, 2, 3)))
+        );
+    }
+
+    private static String clean(String classname)
+    {
+        return StringUtils.remove(classname, "org.apache.cassandra.db.marshal.");
+    }
+
+    @Test
+    public void testToString()
+    {
+        // set<frozen<list<int>>>
+        SetType t = SetType.getInstance(ListType.getInstance(Int32Type.instance, false), true);
+        assertEquals("SetType(FrozenType(ListType(Int32Type)))", clean(t.toString()));
+        assertEquals("SetType(ListType(Int32Type))", clean(t.toString(true)));
+
+        // frozen<set<list<int>>>
+        t = SetType.getInstance(ListType.getInstance(Int32Type.instance, false), false);
+        assertEquals("FrozenType(SetType(ListType(Int32Type)))", clean(t.toString()));
+        assertEquals("SetType(ListType(Int32Type))", clean(t.toString(true)));
+
+        // map<frozen<list<int>>, int>
+        MapType m = MapType.getInstance(ListType.getInstance(Int32Type.instance, false), Int32Type.instance, true);
+        assertEquals("MapType(FrozenType(ListType(Int32Type)),Int32Type)", clean(m.toString()));
+        assertEquals("MapType(ListType(Int32Type),Int32Type)", clean(m.toString(true)));
+
+        // frozen<map<list<int>, int>>
+        m = MapType.getInstance(ListType.getInstance(Int32Type.instance, false), Int32Type.instance, false);
+        assertEquals("FrozenType(MapType(ListType(Int32Type),Int32Type))", clean(m.toString()));
+        assertEquals("MapType(ListType(Int32Type),Int32Type)", clean(m.toString(true)));
+
+        // tuple<set<int>>
+        List<AbstractType<?>> types = new ArrayList<>();
+        types.add(SetType.getInstance(Int32Type.instance, true));
+        TupleType tuple = new TupleType(types);
+        assertEquals("TupleType(SetType(Int32Type))", clean(tuple.toString()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f797bfa4/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
new file mode 100644
index 0000000..a433d06
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
@@ -0,0 +1,644 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.cql3.validation.entities;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+
+import org.junit.Test;
+
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.cassandra.utils.FBUtilities;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class SecondaryIndexTest extends CQLTester
+{
+    private static final int TOO_BIG = 1024 * 65;
+
+    @Test
+    public void testCreateAndDropIndex() throws Throwable
+    {
+        testCreateAndDropIndex("test", false);
+        testCreateAndDropIndex("test2", true);
+    }
+
+    @Test
+    public void testCreateAndDropIndexWithQuotedIdentifier() throws Throwable
+    {
+        testCreateAndDropIndex("\"quoted_ident\"", false);
+        testCreateAndDropIndex("\"quoted_ident2\"", true);
+    }
+
+    @Test
+    public void testCreateAndDropIndexWithCamelCaseIdentifier() throws Throwable
+    {
+        testCreateAndDropIndex("CamelCase", false);
+        testCreateAndDropIndex("CamelCase2", true);
+    }
+
+    /**
+     * Test creating and dropping an index with the specified name.
+     *
+     * @param indexName the index name
+     * @param addKeyspaceOnDrop add the keyspace name in the drop statement
+     * @throws Throwable if an error occurs
+     */
+    private void testCreateAndDropIndex(String indexName, boolean addKeyspaceOnDrop) throws Throwable
+    {
+        execute("USE system");
+        assertInvalidMessage("Index '" + removeQuotes(indexName.toLowerCase(Locale.US)) + "' could not be found", "DROP INDEX " + indexName + ";");
+
+        createTable("CREATE TABLE %s (a int primary key, b int);");
+        createIndex("CREATE INDEX " + indexName + " ON %s(b);");
+        createIndex("CREATE INDEX IF NOT EXISTS " + indexName + " ON %s(b);");
+
+        assertInvalidMessage("Index already exists", "CREATE INDEX " + indexName + " ON %s(b)");
+
+        execute("INSERT INTO %s (a, b) values (?, ?);", 0, 0);
+        execute("INSERT INTO %s (a, b) values (?, ?);", 1, 1);
+        execute("INSERT INTO %s (a, b) values (?, ?);", 2, 2);
+        execute("INSERT INTO %s (a, b) values (?, ?);", 3, 1);
+
+        assertRows(execute("SELECT * FROM %s where b = ?", 1), row(1, 1), row(3, 1));
+        assertInvalidMessage("Index '" + removeQuotes(indexName.toLowerCase(Locale.US)) + "' could not be found in any of the tables of keyspace 'system'", "DROP INDEX " + indexName);
+
+        if (addKeyspaceOnDrop)
+        {
+            dropIndex("DROP INDEX " + KEYSPACE + "." + indexName);
+        }
+        else
+        {
+            execute("USE " + KEYSPACE);
+            dropIndex("DROP INDEX " + indexName);
+        }
+
+        assertInvalidMessage("No secondary indexes on the restricted columns support the provided operators",
+                             "SELECT * FROM %s where b = ?", 1);
+        dropIndex("DROP INDEX IF EXISTS " + indexName);
+        assertInvalidMessage("Index '" + removeQuotes(indexName.toLowerCase(Locale.US)) + "' could not be found", "DROP INDEX " + indexName);
+    }
+
+    /**
+     * Removes the quotes from the specified index name.
+     *
+     * @param indexName the index name from which the quotes must be removed.
+     * @return the unquoted index name.
+     */
+    private static String removeQuotes(String indexName)
+    {
+        return StringUtils.remove(indexName, '\"');
+    }
+
+    /**
+     * Check that you can query for an indexed column even with a key EQ clause,
+     * migrated from cql_tests.py:TestCQL.static_cf_test()
+     */
+    @Test
+    public void testSelectWithEQ() throws Throwable
+    {
+        createTable("CREATE TABLE %s (userid uuid PRIMARY KEY, firstname text, lastname text, age int)");
+        createIndex("CREATE INDEX byAge ON %s(age)");
+
+        UUID id1 = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");
+        UUID id2 = UUID.fromString("f47ac10b-58cc-4372-a567-0e02b2c3d479");
+
+        execute("INSERT INTO %s (userid, firstname, lastname, age) VALUES (?, 'Frodo', 'Baggins', 32)", id1);
+        execute("UPDATE %s SET firstname = 'Samwise', lastname = 'Gamgee', age = 33 WHERE userid = ?", id2);
+
+        assertEmpty(execute("SELECT firstname FROM %s WHERE userid = ? AND age = 33", id1));
+
+        assertRows(execute("SELECT firstname FROM %s WHERE userid = ? AND age = 33", id2),
+                   row("Samwise"));
+    }
+
+    /**
+     * Check CREATE INDEX without name and validate the index can be dropped,
+     * migrated from cql_tests.py:TestCQL.nameless_index_test()
+     */
+    @Test
+    public void testNamelessIndex() throws Throwable
+    {
+        createTable(" CREATE TABLE %s (id text PRIMARY KEY, birth_year int)");
+
+        createIndex("CREATE INDEX on %s (birth_year)");
+
+        execute("INSERT INTO %s (id, birth_year) VALUES ('Tom', 42)");
+        execute("INSERT INTO %s (id, birth_year) VALUES ('Paul', 24)");
+        execute("INSERT INTO %s (id, birth_year) VALUES ('Bob', 42)");
+
+        assertRows(execute("SELECT id FROM %s WHERE birth_year = 42"),
+                   row("Tom"),
+                   row("Bob"));
+
+        execute("DROP INDEX %s_birth_year_idx");
+
+        assertInvalid("SELECT id FROM users WHERE birth_year = 42");
+    }
+
+    /**
+     * Test range queries with 2ndary indexes (#4257),
+     * migrated from cql_tests.py:TestCQL.range_query_2ndary_test()
+     */
+    @Test
+    public void testRangeQuery() throws Throwable
+    {
+        createTable("CREATE TABLE %s (id int primary key, row int, setid int)");
+        createIndex("CREATE INDEX indextest_setid_idx ON %s (setid)");
+
+        execute("INSERT INTO %s (id, row, setid) VALUES (?, ?, ?)", 0, 0, 0);
+        execute("INSERT INTO %s (id, row, setid) VALUES (?, ?, ?)", 1, 1, 0);
+        execute("INSERT INTO %s (id, row, setid) VALUES (?, ?, ?)", 2, 2, 0);
+        execute("INSERT INTO %s (id, row, setid) VALUES (?, ?, ?)", 3, 3, 0);
+
+        assertInvalid("SELECT * FROM %s WHERE setid = 0 AND row < 1");
+
+        assertRows(execute("SELECT * FROM %s WHERE setid = 0 AND row < 1 ALLOW FILTERING"),
+                   row(0, 0, 0));
+    }
+
+    /**
+     * Check for unknown compression parameters options (#4266),
+     * migrated from cql_tests.py:TestCQL.compression_option_validation_test()
+     */
+    @Test
+    public void testUnknownCompressionOptions() throws Throwable
+    {
+        String tableName = createTableName();
+        assertInvalidThrow(SyntaxException.class, String.format(
+                                                               "CREATE TABLE %s (key varchar PRIMARY KEY, password varchar, gender varchar) WITH compression_parameters:sstable_compressor = 'DeflateCompressor'", tableName));
+
+
+        assertInvalidThrow(ConfigurationException.class, String.format(
+                                                                      "CREATE TABLE %s (key varchar PRIMARY KEY, password varchar, gender varchar) WITH compression = { 'sstable_compressor': 'DeflateCompressor' }", tableName));
+    }
+
+    /**
+     * Check one can use arbitrary name for datacenter when creating keyspace (#4278),
+     * migrated from cql_tests.py:TestCQL.keyspace_creation_options_test()
+     */
+    @Test
+    public void testDataCenterName() throws Throwable
+    {
+       execute("CREATE KEYSPACE Foo WITH replication = { 'class' : 'NetworkTopologyStrategy', 'us-east' : 1, 'us-west' : 1 };");
+    }
+
+    /**
+     * Migrated from cql_tests.py:TestCQL.indexes_composite_test()
+     */
+    @Test
+    public void testIndexOnComposite() throws Throwable
+    {
+        String tableName = createTable("CREATE TABLE %s (blog_id int, timestamp int, author text, content text, PRIMARY KEY (blog_id, timestamp))");
+
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 0, 0, "bob", "1st post");
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 0, 1, "tom", "2nd post");
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 0, 2, "bob", "3rd post");
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 0, 3, "tom", "4th post");
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 1, 0, "bob", "5th post");
+
+        createIndex("CREATE INDEX authoridx ON %s (author)");
+
+        assertTrue(waitForIndex(keyspace(), tableName, "authoridx"));
+
+        assertRows(execute("SELECT blog_id, timestamp FROM %s WHERE author = 'bob'"),
+                   row(1, 0),
+                   row(0, 0),
+                   row(0, 2));
+
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 1, 1, "tom", "6th post");
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 1, 2, "tom", "7th post");
+        execute("INSERT INTO %s (blog_id, timestamp, author, content) VALUES (?, ?, ?, ?)", 1, 3, "bob", "8th post");
+
+        assertRows(execute("SELECT blog_id, timestamp FROM %s WHERE author = 'bob'"),
+                   row(1, 0),
+                   row(1, 3),
+                   row(0, 0),
+                   row(0, 2));
+
+        execute("DELETE FROM %s WHERE blog_id = 0 AND timestamp = 2");
+
+        assertRows(execute("SELECT blog_id, timestamp FROM %s WHERE author = 'bob'"),
+                   row(1, 0),
+                   row(1, 3),
+                   row(0, 0));
+    }
+
+    /**
+     * Test for the validation bug of #4709,
+     * migrated from cql_tests.py:TestCQL.refuse_in_with_indexes_test()
+     */
+    @Test
+    public void testInvalidIndexSelect() throws Throwable
+    {
+        createTable("create table %s (pk varchar primary key, col1 varchar, col2 varchar)");
+        createIndex("create index on %s (col1)");
+        createIndex("create index on %s (col2)");
+
+        execute("insert into %s (pk, col1, col2) values ('pk1','foo1','bar1')");
+        execute("insert into %s (pk, col1, col2) values ('pk1a','foo1','bar1')");
+        execute("insert into %s (pk, col1, col2) values ('pk1b','foo1','bar1')");
+        execute("insert into %s (pk, col1, col2) values ('pk1c','foo1','bar1')");
+        execute("insert into %s (pk, col1, col2) values ('pk2','foo2','bar2')");
+        execute("insert into %s (pk, col1, col2) values ('pk3','foo3','bar3')");
+        assertInvalid("select * from %s where col2 in ('bar1', 'bar2')");
+
+        //Migrated from cql_tests.py:TestCQL.bug_6050_test()
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)");
+
+        createIndex("CREATE INDEX ON %s (a)");
+        assertInvalid("SELECT * FROM %s WHERE a = 3 AND b IN (1, 3)");
+
+    }
+
+    /**
+     * Migrated from cql_tests.py:TestCQL.edge_2i_on_complex_pk_test()
+     */
+    @Test
+    public void testIndexesOnComplexPrimaryKey() throws Throwable
+    {
+        createTable("CREATE TABLE %s (pk0 int, pk1 int, ck0 int, ck1 int, ck2 int, value int, PRIMARY KEY ((pk0, pk1), ck0, ck1, ck2))");
+
+        execute("CREATE INDEX ON %s (pk0)");
+        execute("CREATE INDEX ON %s (ck0)");
+        execute("CREATE INDEX ON %s (ck1)");
+        execute("CREATE INDEX ON %s (ck2)");
+
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (0, 1, 2, 3, 4, 5)");
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (1, 2, 3, 4, 5, 0)");
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (2, 3, 4, 5, 0, 1)");
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (3, 4, 5, 0, 1, 2)");
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (4, 5, 0, 1, 2, 3)");
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (5, 0, 1, 2, 3, 4)");
+
+        assertRows(execute("SELECT value FROM %s WHERE pk0 = 2"),
+                   row(1));
+
+        assertRows(execute("SELECT value FROM %s WHERE ck0 = 0"),
+                   row(3));
+
+        assertRows(execute("SELECT value FROM %s WHERE pk0 = 3 AND pk1 = 4 AND ck1 = 0"),
+                   row(2));
+
+        assertRows(execute("SELECT value FROM %s WHERE pk0 = 5 AND pk1 = 0 AND ck0 = 1 AND ck2 = 3 ALLOW FILTERING"),
+                   row(4));
+    }
+
+    /**
+     * Test for CASSANDRA-5240,
+     * migrated from cql_tests.py:TestCQL.bug_5240_test()
+     */
+    @Test
+    public void testIndexOnCompoundRowKey() throws Throwable
+    {
+        createTable("CREATE TABLE %s (interval text, seq int, id int, severity int, PRIMARY KEY ((interval, seq), id) ) WITH CLUSTERING ORDER BY (id DESC)");
+
+        execute("CREATE INDEX ON %s (severity)");
+
+        execute("insert into %s (interval, seq, id , severity) values('t',1, 1, 1)");
+        execute("insert into %s (interval, seq, id , severity) values('t',1, 2, 1)");
+        execute("insert into %s (interval, seq, id , severity) values('t',1, 3, 2)");
+        execute("insert into %s (interval, seq, id , severity) values('t',1, 4, 3)");
+        execute("insert into %s (interval, seq, id , severity) values('t',2, 1, 3)");
+        execute("insert into %s (interval, seq, id , severity) values('t',2, 2, 3)");
+        execute("insert into %s (interval, seq, id , severity) values('t',2, 3, 1)");
+        execute("insert into %s (interval, seq, id , severity) values('t',2, 4, 2)");
+
+        assertRows(execute("select * from %s where severity = 3 and interval = 't' and seq =1"),
+                   row("t", 1, 4, 3));
+    }
+
+    /**
+     * Migrated from cql_tests.py:TestCQL.secondary_index_counters()
+     */
+    @Test
+    public void testIndexOnCountersInvalid() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, c counter)");
+        assertInvalid("CREATE INDEX ON test(c)");
+    }
+
+    /**
+     * Migrated from cql_tests.py:TestCQL.collection_indexing_test()
+     */
+    @Test
+    public void testIndexOnCollections() throws Throwable
+    {
+        createTable(" CREATE TABLE %s ( k int, v int, l list<int>, s set<text>, m map<text, int>, PRIMARY KEY (k, v))");
+
+        createIndex("CREATE INDEX ON %s (l)");
+        createIndex("CREATE INDEX ON %s (s)");
+        createIndex("CREATE INDEX ON %s (m)");
+
+        execute("INSERT INTO %s (k, v, l, s, m) VALUES (0, 0, [1, 2],    {'a'},      {'a' : 1})");
+        execute("INSERT INTO %s (k, v, l, s, m) VALUES (0, 1, [3, 4],    {'b', 'c'}, {'a' : 1, 'b' : 2})");
+        execute("INSERT INTO %s (k, v, l, s, m) VALUES (0, 2, [1],       {'a', 'c'}, {'c' : 3})");
+        execute("INSERT INTO %s (k, v, l, s, m) VALUES (1, 0, [1, 2, 4], {},         {'b' : 1})");
+        execute("INSERT INTO %s (k, v, l, s, m) VALUES (1, 1, [4, 5],    {'d'},      {'a' : 1, 'b' : 3})");
+
+        // lists
+        assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 1"), row(1, 0), row(0, 0), row(0, 2));
+        assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND l CONTAINS 1"), row(0, 0), row(0, 2));
+        assertRows(execute("SELECT k, v FROM %s WHERE l CONTAINS 2"), row(1, 0), row(0, 0));
+        assertEmpty(execute("SELECT k, v FROM %s WHERE l CONTAINS 6"));
+
+        // sets
+        assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'a'"), row(0, 0), row(0, 2));
+        assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND s CONTAINS 'a'"), row(0, 0), row(0, 2));
+        assertRows(execute("SELECT k, v FROM %s WHERE s CONTAINS 'd'"), row(1, 1));
+        assertEmpty(execute("SELECT k, v FROM %s  WHERE s CONTAINS 'e'"));
+
+        // maps
+        assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 1"), row(1, 0), row(1, 1), row(0, 0), row(0, 1));
+        assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS 1"), row(0, 0), row(0, 1));
+        assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS 2"), row(0, 1));
+        assertEmpty(execute("SELECT k, v FROM %s  WHERE m CONTAINS 4"));
+    }
+
+    /**
+     * Migrated from cql_tests.py:TestCQL.map_keys_indexing()
+     */
+    @Test
+    public void testIndexOnMapKeys() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int, v int, m map<text, int>, PRIMARY KEY (k, v))");
+
+        createIndex("CREATE INDEX ON %s(keys(m))");
+
+        execute("INSERT INTO %s (k, v, m) VALUES (0, 0, {'a' : 1})");
+        execute("INSERT INTO %s (k, v, m) VALUES (0, 1, {'a' : 1, 'b' : 2})");
+        execute("INSERT INTO %s (k, v, m) VALUES (0, 2, {'c' : 3})");
+        execute("INSERT INTO %s (k, v, m) VALUES (1, 0, {'b' : 1})");
+        execute("INSERT INTO %s (k, v, m) VALUES (1, 1, {'a' : 1, 'b' : 3})");
+
+        // maps
+        assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS KEY 'a'"), row(1, 1), row(0, 0), row(0, 1));
+        assertRows(execute("SELECT k, v FROM %s WHERE k = 0 AND m CONTAINS KEY 'a'"), row(0, 0), row(0, 1));
+        assertRows(execute("SELECT k, v FROM %s WHERE m CONTAINS KEY 'c'"), row(0, 2));
+        assertEmpty(execute("SELECT k, v FROM %s  WHERE m CONTAINS KEY 'd'"));
+
+        // we're not allowed to create a value index if we already have a key one
+        assertInvalid("CREATE INDEX ON %s(m)");
+    }
+
+    /**
+     * Test for #6950 bug,
+     * migrated from cql_tests.py:TestCQL.key_index_with_reverse_clustering()
+     */
+    @Test
+    public void testIndexOnKeyWithReverseClustering() throws Throwable
+    {
+        createTable(" CREATE TABLE %s (k1 int, k2 int, v int, PRIMARY KEY ((k1, k2), v) ) WITH CLUSTERING ORDER BY (v DESC)");
+
+        createIndex("CREATE INDEX ON %s (k2)");
+
+        execute("INSERT INTO %s (k1, k2, v) VALUES (0, 0, 1)");
+        execute("INSERT INTO %s (k1, k2, v) VALUES (0, 1, 2)");
+        execute("INSERT INTO %s (k1, k2, v) VALUES (0, 0, 3)");
+        execute("INSERT INTO %s (k1, k2, v) VALUES (1, 0, 4)");
+        execute("INSERT INTO %s (k1, k2, v) VALUES (1, 1, 5)");
+        execute("INSERT INTO %s (k1, k2, v) VALUES (2, 0, 7)");
+        execute("INSERT INTO %s (k1, k2, v) VALUES (2, 1, 8)");
+        execute("INSERT INTO %s (k1, k2, v) VALUES (3, 0, 1)");
+
+        assertRows(execute("SELECT * FROM %s WHERE k2 = 0 AND v >= 2 ALLOW FILTERING"),
+                   row(2, 0, 7),
+                   row(0, 0, 3),
+                   row(1, 0, 4));
+    }
+
+    /**
+     * Test for CASSANDRA-6612,
+     * migrated from cql_tests.py:TestCQL.bug_6612_test()
+     */
+    @Test
+    public void testSelectCountOnIndexedColumn() throws Throwable
+    {
+        createTable("CREATE TABLE %s (username text, session_id text, app_name text, account text, last_access timestamp, created_on timestamp, PRIMARY KEY (username, session_id, app_name, account))");
+
+        createIndex("create index ON %s (app_name)");
+        createIndex("create index ON %s (last_access)");
+
+        assertRows(execute("select count(*) from %s where app_name='foo' and account='bar' and last_access > 4 allow filtering"), row(0L));
+
+        execute("insert into %s (username, session_id, app_name, account, last_access, created_on) values ('toto', 'foo', 'foo', 'bar', 12, 13)");
+
+        assertRows(execute("select count(*) from %s where app_name='foo' and account='bar' and last_access > 4 allow filtering"), row(1L));
+    }
+
+    /**
+     * Test for CASSANDRA-5732, Can not query secondary index
+     * migrated from cql_tests.py:TestCQL.bug_5732_test(),
+     * which was executing with a row cache size of 100 MB
+     * and restarting the node, here we just cleanup the cache.
+     */
+    @Test
+    public void testCanQuerySecondaryIndex() throws Throwable
+    {
+        String tableName = createTable("CREATE TABLE %s (k int PRIMARY KEY, v int,)");
+
+        execute("ALTER TABLE %s WITH CACHING='ALL'");
+        execute("INSERT INTO %s (k,v) VALUES (0,0)");
+        execute("INSERT INTO %s (k,v) VALUES (1,1)");
+
+        createIndex("CREATE INDEX testindex on %s (v)");
+        assertTrue(waitForIndex(keyspace(), tableName, "testindex"));
+
+        assertRows(execute("SELECT k FROM %s WHERE v = 0"), row(0));
+        cleanupCache();
+        assertRows(execute("SELECT k FROM %s WHERE v = 0"), row(0));
+    }
+
+    // CASSANDRA-8280/8081
+    // reject updates with indexed values where value > 64k
+    @Test
+    public void testIndexOnCompositeValueOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a int, b int, c blob, PRIMARY KEY (a))");
+        createIndex("CREATE INDEX ON %s(c)");
+        failInsert("INSERT INTO %s (a, b, c) VALUES (0, 0, ?)", ByteBuffer.allocate(TOO_BIG));
+    }
+
+    @Test
+    public void testIndexOnClusteringColumnInsertPartitionKeyAndClusteringsOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a blob, b blob, c blob, d int, PRIMARY KEY (a, b, c))");
+        createIndex("CREATE INDEX ON %s(b)");
+
+        // CompositeIndexOnClusteringKey creates index entries composed of the
+        // PK plus all of the non-indexed clustering columns from the primary row
+        // so we should reject where len(a) + len(c) > 65560 as this will form the
+        // total clustering in the index table
+        ByteBuffer a = ByteBuffer.allocate(100);
+        ByteBuffer b = ByteBuffer.allocate(10);
+        ByteBuffer c = ByteBuffer.allocate(FBUtilities.MAX_UNSIGNED_SHORT - 99);
+
+        failInsert("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, 0)", a, b, c);
+    }
+
+    @Test
+    public void testCompactTableWithValueOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a int, b blob, PRIMARY KEY (a)) WITH COMPACT STORAGE");
+        createIndex("CREATE INDEX ON %s(b)");
+        failInsert("INSERT INTO %s (a, b) VALUES (0, ?)", ByteBuffer.allocate(TOO_BIG));
+    }
+
+    @Test
+    public void testIndexOnCollectionValueInsertPartitionKeyAndCollectionKeyOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a blob , b map<blob, int>, PRIMARY KEY (a))");
+        createIndex("CREATE INDEX ON %s(b)");
+
+        // A collection key > 64k by itself will be rejected from
+        // the primary table.
+        // To test index validation we need to ensure that
+        // len(b) < 64k, but len(a) + len(b) > 64k as that will
+        // form the clustering in the index table
+        ByteBuffer a = ByteBuffer.allocate(100);
+        ByteBuffer b = ByteBuffer.allocate(FBUtilities.MAX_UNSIGNED_SHORT - 100);
+
+        failInsert("UPDATE %s SET b[?] = 0 WHERE a = ?", b, a);
+    }
+
+    @Test
+    public void testIndexOnCollectionKeyInsertPartitionKeyAndClusteringOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a blob, b blob, c map<blob, int>, PRIMARY KEY (a, b))");
+        createIndex("CREATE INDEX ON %s(KEYS(c))");
+
+        // Basically the same as the case with non-collection clustering
+        // CompositeIndexOnCollectionKeyy creates index entries composed of the
+        // PK plus all of the clustering columns from the primary row, except the
+        // collection element - which becomes the partition key in the index table
+        ByteBuffer a = ByteBuffer.allocate(100);
+        ByteBuffer b = ByteBuffer.allocate(FBUtilities.MAX_UNSIGNED_SHORT - 100);
+        ByteBuffer c = ByteBuffer.allocate(10);
+
+        failInsert("UPDATE %s SET c[?] = 0 WHERE a = ? and b = ?", c, a, b);
+    }
+
+    @Test
+    public void testIndexOnPartitionKeyInsertValueOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a int, b int, c blob, PRIMARY KEY ((a, b)))");
+        createIndex("CREATE INDEX ON %s(a)");
+        succeedInsert("INSERT INTO %s (a, b, c) VALUES (0, 0, ?)", ByteBuffer.allocate(TOO_BIG));
+    }
+
+    @Test
+    public void testIndexOnClusteringColumnInsertValueOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a int, b int, c blob, PRIMARY KEY (a, b))");
+        createIndex("CREATE INDEX ON %s(b)");
+        succeedInsert("INSERT INTO %s (a, b, c) VALUES (0, 0, ?)", ByteBuffer.allocate(TOO_BIG));
+    }
+
+    @Test
+    public void testIndexOnFullCollectionEntryInsertCollectionValueOver64k() throws Throwable
+    {
+        createTable("CREATE TABLE %s(a int, b frozen<map<int, blob>>, PRIMARY KEY (a))");
+        createIndex("CREATE INDEX ON %s(full(b))");
+        Map<Integer, ByteBuffer> map = new HashMap();
+        map.put(0, ByteBuffer.allocate(1024 * 65));
+        failInsert("INSERT INTO %s (a, b) VALUES (0, ?)", map);
+    }
+
+    public void failInsert(String insertCQL, Object...args) throws Throwable
+    {
+        try
+        {
+            execute(insertCQL, args);
+            fail("Expected statement to fail validation");
+        }
+        catch (Exception e)
+        {
+            // as expected
+        }
+    }
+
+    public void succeedInsert(String insertCQL, Object...args) throws Throwable
+    {
+        execute(insertCQL, args);
+        flush();
+    }
+
+    /**
+     * Migrated from cql_tests.py:TestCQL.clustering_indexing_test()
+     */
+    @Test
+    public void testIndexesOnClustering() throws Throwable
+    {
+        createTable("CREATE TABLE %s ( id1 int, id2 int, author text, time bigint, v1 text, v2 text, PRIMARY KEY ((id1, id2), author, time))");
+
+        createIndex("CREATE INDEX ON %s (time)");
+        execute("CREATE INDEX ON %s (id2)");
+
+        execute("INSERT INTO %s (id1, id2, author, time, v1, v2) VALUES(0, 0, 'bob', 0, 'A', 'A')");
+        execute("INSERT INTO %s (id1, id2, author, time, v1, v2) VALUES(0, 0, 'bob', 1, 'B', 'B')");
+        execute("INSERT INTO %s (id1, id2, author, time, v1, v2) VALUES(0, 1, 'bob', 2, 'C', 'C')");
+        execute("INSERT INTO %s (id1, id2, author, time, v1, v2) VALUES(0, 0, 'tom', 0, 'D', 'D')");
+        execute("INSERT INTO %s (id1, id2, author, time, v1, v2) VALUES(0, 1, 'tom', 1, 'E', 'E')");
+
+        assertRows(execute("SELECT v1 FROM %s WHERE time = 1"),
+                   row("B"), row("E"));
+
+        assertRows(execute("SELECT v1 FROM %s WHERE id2 = 1"),
+                   row("C"), row("E"));
+
+        assertRows(execute("SELECT v1 FROM %s WHERE id1 = 0 AND id2 = 0 AND author = 'bob' AND time = 0"),
+                   row("A"));
+
+        // Test for CASSANDRA-8206
+        execute("UPDATE %s SET v2 = null WHERE id1 = 0 AND id2 = 0 AND author = 'bob' AND time = 1");
+
+        assertRows(execute("SELECT v1 FROM %s WHERE id2 = 0"),
+                   row("A"), row("B"), row("D"));
+
+        assertRows(execute("SELECT v1 FROM %s WHERE time = 1"),
+                   row("B"), row("E"));
+    }
+
+    /**
+     * Migrated from cql_tests.py:TestCQL.invalid_clustering_indexing_test()
+     */
+    @Test
+    public void testIndexesOnClusteringInvalid() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY KEY ((a, b))) WITH COMPACT STORAGE");
+        assertInvalid("CREATE INDEX ON %s (a)");
+        assertInvalid("CREATE INDEX ON %s (b)");
+
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b)) WITH COMPACT STORAGE");
+        assertInvalid("CREATE INDEX ON %s (a)");
+        assertInvalid("CREATE INDEX ON %s (b)");
+        assertInvalid("CREATE INDEX ON %s (c)");
+
+        createTable("CREATE TABLE %s (a int, b int, c int static , PRIMARY KEY (a, b))");
+        assertInvalid("CREATE INDEX ON %s (c)");
+    }
+
+}