cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tylerho...@apache.org
Subject [1/3] cassandra git commit: Support for non-frozen UDTS
Date Fri, 08 Apr 2016 20:28:36 GMT
Repository: cassandra
Updated Branches:
  refs/heads/trunk 66fb8f51e -> 677230df6


http://git-wip-us.apache.org/repos/asf/cassandra/blob/677230df/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
index d9df206..5501561 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
@@ -73,32 +73,86 @@ public class UserTypesTest extends CQLTester
         execute("INSERT INTO %s(k, v) VALUES (?, {x:?})", 1, -104.99251);
         execute("UPDATE %s SET b = ? WHERE k = ?", true, 1);
 
-        assertRows(execute("SELECT v.x FROM %s WHERE k = ? AND v = {x:?}", 1, -104.99251),
-            row(-104.99251)
-        );
-
-        flush();
-
-        assertRows(execute("SELECT v.x FROM %s WHERE k = ? AND v = {x:?}", 1, -104.99251),
-                   row(-104.99251)
+        beforeAndAfterFlush(() ->
+            assertRows(execute("SELECT v.x FROM %s WHERE k = ? AND v = {x:?}", 1, -104.99251),
+                row(-104.99251)
+            )
         );
     }
 
     @Test
-    public void testCreateInvalidTablesWithUDT() throws Throwable
+    public void testInvalidUDTStatements() throws Throwable
     {
-        String myType = createType("CREATE TYPE %s (f int)");
-
-        // Using a UDT without frozen shouldn't work
-        assertInvalidMessage("Non-frozen User-Defined types are not supported, please use frozen<>",
-                             "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v " + KEYSPACE + '.' + myType + ")");
-
+        String typename = createType("CREATE TYPE %s (a int)");
+        String myType = KEYSPACE + '.' + typename;
+
+        // non-frozen UDTs in a table PK
+        assertInvalidMessage("Invalid non-frozen user-defined type for PRIMARY KEY component k",
+                "CREATE TABLE " + KEYSPACE + ".wrong (k " + myType + " PRIMARY KEY , v int)");
+        assertInvalidMessage("Invalid non-frozen user-defined type for PRIMARY KEY component k2",
+                "CREATE TABLE " + KEYSPACE + ".wrong (k1 int, k2 " + myType + ", v int, PRIMARY KEY (k1, k2))");
+
+        // non-frozen UDTs in a collection
+        assertInvalidMessage("Non-frozen UDTs are not allowed inside collections: list<" + myType + ">",
+                "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v list<" + myType + ">)");
+        assertInvalidMessage("Non-frozen UDTs are not allowed inside collections: set<" + myType + ">",
+                "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v set<" + myType + ">)");
+        assertInvalidMessage("Non-frozen UDTs are not allowed inside collections: map<" + myType + ", int>",
+                "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v map<" + myType + ", int>)");
+        assertInvalidMessage("Non-frozen UDTs are not allowed inside collections: map<int, " + myType + ">",
+                "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v map<int, " + myType + ">)");
+
+        // non-frozen UDT in a collection (as part of a UDT definition)
+        assertInvalidMessage("Non-frozen UDTs are not allowed inside collections: list<" + myType + ">",
+                "CREATE TYPE " + KEYSPACE + ".wrong (a int, b list<" + myType + ">)");
+
+        // non-frozen UDT in a UDT
+        assertInvalidMessage("A user type cannot contain non-frozen UDTs",
+                "CREATE TYPE " + KEYSPACE + ".wrong (a int, b " + myType + ")");
+
+        // referencing a UDT in another keyspace
         assertInvalidMessage("Statement on keyspace " + KEYSPACE + " cannot refer to a user type in keyspace otherkeyspace;" +
                              " user types can only be used in the keyspace they are defined in",
                              "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v frozen<otherKeyspace.myType>)");
 
+        // referencing an unknown UDT
         assertInvalidMessage("Unknown type " + KEYSPACE + ".unknowntype",
                              "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v frozen<" + KEYSPACE + '.' + "unknownType>)");
+
+        // bad deletions on frozen UDTs
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">, c int)");
+        assertInvalidMessage("Frozen UDT column b does not support field deletion", "DELETE b.a FROM %s WHERE a = 0");
+        assertInvalidMessage("Invalid field deletion operation for non-UDT column c", "DELETE c.a FROM %s WHERE a = 0");
+
+        // bad updates on frozen UDTs
+        assertInvalidMessage("Invalid operation (b.a = 0) for frozen UDT column b", "UPDATE %s SET b.a = 0 WHERE a = 0");
+        assertInvalidMessage("Invalid operation (c.a = 0) for non-UDT column c", "UPDATE %s SET c.a = 0 WHERE a = 0");
+
+        // bad deletions on non-frozen UDTs
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b " + myType + ", c int)");
+        assertInvalidMessage("UDT column b does not have a field named foo", "DELETE b.foo FROM %s WHERE a = 0");
+
+        // bad updates on non-frozen UDTs
+        assertInvalidMessage("UDT column b does not have a field named foo", "UPDATE %s SET b.foo = 0 WHERE a = 0");
+
+        // bad insert on non-frozen UDTs
+        assertInvalidMessage("Unknown field 'foo' in value of user defined type", "INSERT INTO %s (a, b, c) VALUES (0, {a: 0, foo: 0}, 0)");
+        if (usePrepared())
+        {
+            assertInvalidMessage("Expected 1 value for " + typename + " column, but got more",
+                    "INSERT INTO %s (a, b, c) VALUES (0, ?, 0)", userType("a", 0, "foo", 0));
+        }
+        else
+        {
+            assertInvalidMessage("Unknown field 'foo' in value of user defined type " + typename,
+                    "INSERT INTO %s (a, b, c) VALUES (0, ?, 0)", userType("a", 0, "foo", 0));
+        }
+
+        // non-frozen UDT with non-frozen nested collection
+        String typename2 = createType("CREATE TYPE %s (bar int, foo list<int>)");
+        String myType2 = KEYSPACE + '.' + typename2;
+        assertInvalidMessage("Non-frozen UDTs with nested non-frozen collections are not supported",
+                "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v " + myType2 + ")");
     }
 
     @Test
@@ -106,24 +160,61 @@ public class UserTypesTest extends CQLTester
     {
         String myType = KEYSPACE + '.' + createType("CREATE TYPE %s (a int)");
         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-        execute("INSERT INTO %s (a, b) VALUES (1, {a: 1})");
+        execute("INSERT INTO %s (a, b) VALUES (1, ?)", userType("a", 1));
 
         assertRows(execute("SELECT b.a FROM %s"), row(1));
 
         flush();
 
-        execute("ALTER TYPE " + myType + " ADD b int");
-        execute("INSERT INTO %s (a, b) VALUES (2, {a: 2, b :2})");
+        schemaChange("ALTER TYPE " + myType + " ADD b int");
+        execute("INSERT INTO %s (a, b) VALUES (2, ?)", userType("a", 2, "b", 2));
 
-        assertRows(execute("SELECT b.a, b.b FROM %s"),
-                   row(1, null),
-                   row(2, 2));
-
-        flush();
+        beforeAndAfterFlush(() ->
+            assertRows(execute("SELECT b.a, b.b FROM %s"),
+                       row(1, null),
+                       row(2, 2))
+        );
+    }
 
-        assertRows(execute("SELECT b.a, b.b FROM %s"),
-                   row(1, null),
-                   row(2, 2));
+    @Test
+    public void testAlterNonFrozenUDT() throws Throwable
+    {
+        String myType = KEYSPACE + '.' + createType("CREATE TYPE %s (a int, b text)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + myType + ")");
+        execute("INSERT INTO %s (k, v) VALUES (0, ?)", userType("a", 1, "b", "abc"));
+
+        beforeAndAfterFlush(() -> {
+            assertRows(execute("SELECT v FROM %s"), row(userType("a", 1, "b", "abc")));
+            assertRows(execute("SELECT v.a FROM %s"), row(1));
+            assertRows(execute("SELECT v.b FROM %s"), row("abc"));
+        });
+
+        schemaChange("ALTER TYPE " + myType + " RENAME b TO foo");
+        assertRows(execute("SELECT v FROM %s"), row(userType("a", 1, "b", "abc")));
+        assertRows(execute("SELECT v.a FROM %s"), row(1));
+        assertRows(execute("SELECT v.foo FROM %s"), row("abc"));
+
+        execute("UPDATE %s SET v.foo = 'def' WHERE k = 0");
+        assertRows(execute("SELECT v FROM %s"), row(userType("a", 1, "foo", "def")));
+        assertRows(execute("SELECT v.a FROM %s"), row(1));
+        assertRows(execute("SELECT v.foo FROM %s"), row("def"));
+
+        execute("INSERT INTO %s (k, v) VALUES (0, ?)", userType("a", 2, "foo", "def"));
+        assertRows(execute("SELECT v FROM %s"), row(userType("a", 2, "foo", "def")));
+        assertRows(execute("SELECT v.a FROM %s"), row(2));
+        assertRows(execute("SELECT v.foo FROM %s"), row("def"));
+
+        schemaChange("ALTER TYPE " + myType + " ADD c int");
+        assertRows(execute("SELECT v FROM %s"), row(userType("a", 2, "foo", "def", "c", null)));
+        assertRows(execute("SELECT v.a FROM %s"), row(2));
+        assertRows(execute("SELECT v.foo FROM %s"), row("def"));
+        assertRows(execute("SELECT v.c FROM %s"), row(new Object[] {null}));
+
+        execute("INSERT INTO %s (k, v) VALUES (0, ?)", userType("a", 3, "foo", "abc", "c", 0));
+        beforeAndAfterFlush(() -> {
+            assertRows(execute("SELECT v FROM %s"), row(userType("a", 3, "foo", "abc", "c", 0)));
+            assertRows(execute("SELECT v.c FROM %s"), row(0));
+        });
     }
 
     @Test
@@ -134,11 +225,14 @@ public class UserTypesTest extends CQLTester
         String myOtherType = createType("CREATE TYPE %s (a frozen<" + myType + ">)");
         createTable("CREATE TABLE %s (k int PRIMARY KEY, v frozen<" + myType + ">, z frozen<" + myOtherType + ">)");
 
-        assertInvalidMessage("Invalid unset value for field 'y' of user defined type " + myType,
-                             "INSERT INTO %s (k, v) VALUES (10, {x:?, y:?})", 1, unset());
+        if (usePrepared())
+        {
+            assertInvalidMessage("Invalid unset value for field 'y' of user defined type " + myType,
+                    "INSERT INTO %s (k, v) VALUES (10, {x:?, y:?})", 1, unset());
 
-        assertInvalidMessage("Invalid unset value for field 'y' of user defined type " + myType,
-                             "INSERT INTO %s (k, v, z) VALUES (10, {x:?, y:?}, {a:{x: ?, y: ?}})", 1, 1, 1, unset());
+            assertInvalidMessage("Invalid unset value for field 'y' of user defined type " + myType,
+                    "INSERT INTO %s (k, v, z) VALUES (10, {x:?, y:?}, {a:{x: ?, y: ?}})", 1, 1, 1, unset());
+        }
     }
 
     @Test
@@ -153,28 +247,22 @@ public class UserTypesTest extends CQLTester
 
             createTable("CREATE TABLE %s (x int PRIMARY KEY, y " + columnType + ")");
 
-            execute("INSERT INTO %s (x, y) VALUES(1, {'firstValue':{a:1}})");
-            assertRows(execute("SELECT * FROM %s"), row(1, map("firstValue", userType(1))));
+            execute("INSERT INTO %s (x, y) VALUES(1, ?)", map("firstValue", userType("a", 1)));
+            assertRows(execute("SELECT * FROM %s"), row(1, map("firstValue", userType("a", 1))));
             flush();
 
             execute("ALTER TYPE " + KEYSPACE + "." + ut1 + " ADD b int");
-            execute("INSERT INTO %s (x, y) VALUES(2, {'secondValue':{a:2, b:2}})");
-            execute("INSERT INTO %s (x, y) VALUES(3, {'thirdValue':{a:3}})");
-            execute("INSERT INTO %s (x, y) VALUES(4, {'fourthValue':{b:4}})");
-
-            assertRows(execute("SELECT * FROM %s"),
-                    row(1, map("firstValue", userType(1))),
-                    row(2, map("secondValue", userType(2, 2))),
-                    row(3, map("thirdValue", userType(3, null))),
-                    row(4, map("fourthValue", userType(null, 4))));
-
-            flush();
-
-            assertRows(execute("SELECT * FROM %s"),
-                    row(1, map("firstValue", userType(1))),
-                    row(2, map("secondValue", userType(2, 2))),
-                    row(3, map("thirdValue", userType(3, null))),
-                    row(4, map("fourthValue", userType(null, 4))));
+            execute("INSERT INTO %s (x, y) VALUES(2, ?)", map("secondValue", userType("a", 2, "b", 2)));
+            execute("INSERT INTO %s (x, y) VALUES(3, ?)", map("thirdValue", userType("a", 3, "b", null)));
+            execute("INSERT INTO %s (x, y) VALUES(4, ?)", map("fourthValue", userType("a", null, "b", 4)));
+
+            beforeAndAfterFlush(() ->
+                assertRows(execute("SELECT * FROM %s"),
+                        row(1, map("firstValue", userType("a", 1))),
+                        row(2, map("secondValue", userType("a", 2, "b", 2))),
+                        row(3, map("thirdValue", userType("a", 3, "b", null))),
+                        row(4, map("fourthValue", userType("a", null, "b", 4))))
+            );
         }
     }
 
@@ -190,28 +278,22 @@ public class UserTypesTest extends CQLTester
 
             createTable("CREATE TABLE %s (x int PRIMARY KEY, y " + columnType + ")");
 
-            execute("INSERT INTO %s (x, y) VALUES(1, {1} )");
-            assertRows(execute("SELECT * FROM %s"), row(1, set(userType(1))));
+            execute("INSERT INTO %s (x, y) VALUES(1, ?)", set(userType("a", 1)));
+            assertRows(execute("SELECT * FROM %s"), row(1, set(userType("a", 1))));
             flush();
 
             execute("ALTER TYPE " + KEYSPACE + "." + ut1 + " ADD b int");
-            execute("INSERT INTO %s (x, y) VALUES(2, {{a:2, b:2}})");
-            execute("INSERT INTO %s (x, y) VALUES(3, {{a:3}})");
-            execute("INSERT INTO %s (x, y) VALUES(4, {{b:4}})");
-
-            assertRows(execute("SELECT * FROM %s"),
-                    row(1, set(userType(1))),
-                    row(2, set(userType(2, 2))),
-                    row(3, set(userType(3, null))),
-                    row(4, set(userType(null, 4))));
-
-            flush();
-
-            assertRows(execute("SELECT * FROM %s"),
-                    row(1, set(userType(1))),
-                    row(2, set(userType(2, 2))),
-                    row(3, set(userType(3, null))),
-                    row(4, set(userType(null, 4))));
+            execute("INSERT INTO %s (x, y) VALUES(2, ?)", set(userType("a", 2, "b", 2)));
+            execute("INSERT INTO %s (x, y) VALUES(3, ?)", set(userType("a", 3, "b", null)));
+            execute("INSERT INTO %s (x, y) VALUES(4, ?)", set(userType("a", null, "b", 4)));
+
+            beforeAndAfterFlush(() ->
+                assertRows(execute("SELECT * FROM %s"),
+                        row(1, set(userType("a", 1))),
+                        row(2, set(userType("a", 2, "b", 2))),
+                        row(3, set(userType("a", 3, "b", null))),
+                        row(4, set(userType("a", null, "b", 4))))
+            );
         }
     }
 
@@ -227,28 +309,22 @@ public class UserTypesTest extends CQLTester
 
             createTable("CREATE TABLE %s (x int PRIMARY KEY, y " + columnType + ")");
 
-            execute("INSERT INTO %s (x, y) VALUES(1, [1] )");
-            assertRows(execute("SELECT * FROM %s"), row(1, list(userType(1))));
+            execute("INSERT INTO %s (x, y) VALUES(1, ?)", list(userType("a", 1)));
+            assertRows(execute("SELECT * FROM %s"), row(1, list(userType("a", 1))));
             flush();
 
             execute("ALTER TYPE " + KEYSPACE + "." + ut1 + " ADD b int");
-            execute("INSERT INTO %s (x, y) VALUES(2, [{a:2, b:2}])");
-            execute("INSERT INTO %s (x, y) VALUES(3, [{a:3}])");
-            execute("INSERT INTO %s (x, y) VALUES(4, [{b:4}])");
-
-            assertRows(execute("SELECT * FROM %s"),
-                    row(1, list(userType(1))),
-                    row(2, list(userType(2, 2))),
-                    row(3, list(userType(3, null))),
-                    row(4, list(userType(null, 4))));
-
-            flush();
-
-            assertRows(execute("SELECT * FROM %s"),
-                    row(1, list(userType(1))),
-                    row(2, list(userType(2, 2))),
-                    row(3, list(userType(3, null))),
-                    row(4, list(userType(null, 4))));
+            execute("INSERT INTO %s (x, y) VALUES (2, ?)", list(userType("a", 2, "b", 2)));
+            execute("INSERT INTO %s (x, y) VALUES (3, ?)", list(userType("a", 3, "b", null)));
+            execute("INSERT INTO %s (x, y) VALUES (4, ?)", list(userType("a", null, "b", 4)));
+
+            beforeAndAfterFlush(() ->
+                assertRows(execute("SELECT * FROM %s"),
+                        row(1, list(userType("a", 1))),
+                        row(2, list(userType("a", 2, "b", 2))),
+                        row(3, list(userType("a", 3, "b", null))),
+                        row(4, list(userType("a", null, "b", 4))))
+            );
         }
     }
 
@@ -259,28 +335,22 @@ public class UserTypesTest extends CQLTester
 
         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, " + KEYSPACE + "." + type + ">>)");
 
-        execute("INSERT INTO %s (a, b) VALUES(1, (1, {a:1, b:1}))");
-        assertRows(execute("SELECT * FROM %s"), row(1, tuple(1, userType(1, 1))));
+        execute("INSERT INTO %s (a, b) VALUES(1, (1, ?))", userType("a", 1, "b", 1));
+        assertRows(execute("SELECT * FROM %s"), row(1, tuple(1, userType("a", 1, "b", 1))));
         flush();
 
         execute("ALTER TYPE " + KEYSPACE + "." + type + " ADD c int");
-        execute("INSERT INTO %s (a, b) VALUES(2, (2, {a: 2, b: 2, c: 2}))");
-        execute("INSERT INTO %s (a, b) VALUES(3, (3, {a: 3, b: 3}))");
-        execute("INSERT INTO %s (a, b) VALUES(4, (4, {b:4}))");
-
-        assertRows(execute("SELECT * FROM %s"),
-                   row(1, tuple(1, userType(1, 1))),
-                   row(2, tuple(2, userType(2, 2, 2))),
-                   row(3, tuple(3, userType(3, 3, null))),
-                   row(4, tuple(4, userType(null, 4, null))));
+        execute("INSERT INTO %s (a, b) VALUES (2, (2, ?))", userType("a", 2, "b", 2, "c", 2));
+        execute("INSERT INTO %s (a, b) VALUES (3, (3, ?))", userType("a", 3, "b", 3, "c", null));
+        execute("INSERT INTO %s (a, b) VALUES (4, (4, ?))", userType("a", null, "b", 4, "c", null));
 
-        flush();
-
-        assertRows(execute("SELECT * FROM %s"),
-                   row(1, tuple(1, userType(1, 1))),
-                   row(2, tuple(2, userType(2, 2, 2))),
-                   row(3, tuple(3, userType(3, 3, null))),
-                   row(4, tuple(4, userType(null, 4, null))));
+        beforeAndAfterFlush(() ->
+            assertRows(execute("SELECT * FROM %s"),
+                    row(1, tuple(1, userType("a", 1, "b", 1))),
+                    row(2, tuple(2, userType("a", 2, "b", 2, "c", 2))),
+                    row(3, tuple(3, userType("a", 3, "b", 3, "c", null))),
+                    row(4, tuple(4, userType("a", null, "b", 4, "c", null))))
+        );
     }
 
     @Test
@@ -290,28 +360,22 @@ public class UserTypesTest extends CQLTester
 
         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, tuple<int, " + KEYSPACE + "." + type + ">>>)");
 
-        execute("INSERT INTO %s (a, b) VALUES(1, (1, (1, {a:1, b:1})))");
-        assertRows(execute("SELECT * FROM %s"), row(1, tuple(1, tuple(1, userType(1, 1)))));
+        execute("INSERT INTO %s (a, b) VALUES(1, (1, (1, ?)))", userType("a", 1, "b", 1));
+        assertRows(execute("SELECT * FROM %s"), row(1, tuple(1, tuple(1, userType("a", 1, "b", 1)))));
         flush();
 
         execute("ALTER TYPE " + KEYSPACE + "." + type + " ADD c int");
-        execute("INSERT INTO %s (a, b) VALUES(2, (2, (1, {a: 2, b: 2, c: 2})))");
-        execute("INSERT INTO %s (a, b) VALUES(3, (3, (1, {a: 3, b: 3})))");
-        execute("INSERT INTO %s (a, b) VALUES(4, (4, (1, {b:4})))");
+        execute("INSERT INTO %s (a, b) VALUES(2, (2, (1, ?)))", userType("a", 2, "b", 2, "c", 2));
+        execute("INSERT INTO %s (a, b) VALUES(3, (3, ?))", tuple(1, userType("a", 3, "b", 3, "c", null)));
+        execute("INSERT INTO %s (a, b) VALUES(4, ?)", tuple(4, tuple(1, userType("a", null, "b", 4, "c", null))));
 
-        assertRows(execute("SELECT * FROM %s"),
-                   row(1, tuple(1, tuple(1, userType(1, 1)))),
-                   row(2, tuple(2, tuple(1, userType(2, 2, 2)))),
-                   row(3, tuple(3, tuple(1, userType(3, 3, null)))),
-                   row(4, tuple(4, tuple(1, userType(null, 4, null)))));
-
-        flush();
-
-        assertRows(execute("SELECT * FROM %s"),
-                   row(1, tuple(1, tuple(1, userType(1, 1)))),
-                   row(2, tuple(2, tuple(1, userType(2, 2, 2)))),
-                   row(3, tuple(3, tuple(1, userType(3, 3, null)))),
-                   row(4, tuple(4, tuple(1, userType(null, 4, null)))));
+        beforeAndAfterFlush(() ->
+            assertRows(execute("SELECT * FROM %s"),
+                    row(1, tuple(1, tuple(1, userType("a", 1, "b", 1)))),
+                    row(2, tuple(2, tuple(1, userType("a", 2, "b", 2, "c", 2)))),
+                    row(3, tuple(3, tuple(1, userType("a", 3, "b", 3, "c", null)))),
+                    row(4, tuple(4, tuple(1, userType("a", null, "b", 4, "c", null)))))
+        );
     }
 
     @Test
@@ -322,28 +386,24 @@ public class UserTypesTest extends CQLTester
 
         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + KEYSPACE + "." + otherType + ">)");
 
-        execute("INSERT INTO %s (a, b) VALUES(1, {x: {a:1, b:1}})");
+        execute("INSERT INTO %s (a, b) VALUES(1, {x: ?})", userType("a", 1, "b", 1));
+        assertRows(execute("SELECT b.x.a, b.x.b FROM %s"), row(1, 1));
+        execute("INSERT INTO %s (a, b) VALUES(1, ?)", userType("x", userType("a", 1, "b", 1)));
         assertRows(execute("SELECT b.x.a, b.x.b FROM %s"), row(1, 1));
         flush();
 
         execute("ALTER TYPE " + KEYSPACE + "." + type + " ADD c int");
-        execute("INSERT INTO %s (a, b) VALUES(2, {x: {a: 2, b: 2, c: 2}})");
-        execute("INSERT INTO %s (a, b) VALUES(3, {x: {a: 3, b: 3}})");
-        execute("INSERT INTO %s (a, b) VALUES(4, {x: {b:4}})");
-
-        assertRows(execute("SELECT b.x.a, b.x.b, b.x.c FROM %s"),
-                   row(1, 1, null),
-                   row(2, 2, 2),
-                   row(3, 3, null),
-                   row(null, 4, null));
-
-        flush();
-
-        assertRows(execute("SELECT b.x.a, b.x.b, b.x.c FROM %s"),
-                   row(1, 1, null),
-                   row(2, 2, 2),
-                   row(3, 3, null),
-                   row(null, 4, null));
+        execute("INSERT INTO %s (a, b) VALUES(2, {x: ?})", userType("a", 2, "b", 2, "c", 2));
+        execute("INSERT INTO %s (a, b) VALUES(3, {x: ?})", userType("a", 3, "b", 3));
+        execute("INSERT INTO %s (a, b) VALUES(4, {x: ?})", userType("a", null, "b", 4));
+
+        beforeAndAfterFlush(() ->
+            assertRows(execute("SELECT b.x.a, b.x.b, b.x.c FROM %s"),
+                       row(1, 1, null),
+                       row(2, 2, 2),
+                       row(3, 3, null),
+                       row(null, 4, null))
+        );
     }
 
     /**
@@ -383,10 +443,11 @@ public class UserTypesTest extends CQLTester
 
         createTable("CREATE TABLE %s (id int PRIMARY KEY, val frozen<" + type2 + ">)");
 
-        execute("INSERT INTO %s (id, val) VALUES (0, { s : {{ s : {'foo', 'bar'}, m : { 'foo' : 'bar' }, l : ['foo', 'bar']} }})");
+        execute("INSERT INTO %s (id, val) VALUES (0, ?)",
+                userType("s", set(userType("s", set("foo", "bar"), "m", map("foo", "bar"), "l", list("foo", "bar")))));
 
-        // TODO: check result once we have an easy way to do it. For now we just check it doesn't crash
-        execute("SELECT * FROM %s");
+        assertRows(execute("SELECT * FROM %s"),
+                row(0, userType("s", set(userType("s", set("foo", "bar"), "m", map("foo", "bar"), "l", list("foo", "bar"))))));
     }
 
     /**
@@ -398,9 +459,11 @@ public class UserTypesTest extends CQLTester
         String typeName = createType("CREATE TYPE %s (fooint int, fooset set <text>)");
         createTable("CREATE TABLE %s (key int PRIMARY KEY, data frozen <" + typeName + ">)");
 
-        execute("INSERT INTO %s (key, data) VALUES (1, {fooint: 1, fooset: {'2'}})");
+        execute("INSERT INTO %s (key, data) VALUES (1, ?)", userType("fooint", 1, "fooset", set("2")));
         execute("ALTER TYPE " + keyspace() + "." + typeName + " ADD foomap map <int,text>");
-        execute("INSERT INTO %s (key, data) VALUES (1, {fooint: 1, fooset: {'2'}, foomap: {3 : 'bar'}})");
+        execute("INSERT INTO %s (key, data) VALUES (1, ?)", userType("fooint", 1, "fooset", set("2"), "foomap", map(3, "bar")));
+        assertRows(execute("SELECT * FROM %s"),
+                row(1, userType("fooint", 1, "fooset", set("2"), "foomap", map(3, "bar"))));
     }
 
     @Test
@@ -464,13 +527,13 @@ public class UserTypesTest extends CQLTester
 
         type1 = createType("CREATE TYPE %s (foo ascii)");
         String type2 = createType("CREATE TYPE %s (foo frozen<" + type1 + ">)");
-        assertComplexInvalidAlterDropStatements(type1, type2, "{foo: 'abc'}");
+        assertComplexInvalidAlterDropStatements(type1, type2, "{foo: {foo: 'abc'}}");
 
         type1 = createType("CREATE TYPE %s (foo ascii)");
         type2 = createType("CREATE TYPE %s (foo frozen<" + type1 + ">)");
         assertComplexInvalidAlterDropStatements(type1,
                                                 "list<frozen<" + type2 + ">>",
-                                                "[{foo: 'abc'}]");
+                                                "[{foo: {foo: 'abc'}}]");
 
         type1 = createType("CREATE TYPE %s (foo ascii)");
         type2 = createType("CREATE TYPE %s (foo frozen<set<" + type1 + ">>)");
@@ -515,6 +578,110 @@ public class UserTypesTest extends CQLTester
         assertInvalidMessage("Cannot drop user type " + typeWithKs(t), "DROP TYPE " + typeWithKs(t) + ';');
     }
 
+    @Test
+    public void testInsertNonFrozenUDT() throws Throwable
+    {
+        String typeName = createType("CREATE TYPE %s (a int, b text)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + typeName + ")");
+
+        execute("INSERT INTO %s (k, v) VALUES (?, {a: ?, b: ?})", 0, 0, "abc");
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc")));
+
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc"));
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc")));
+
+        execute("INSERT INTO %s (k, v) VALUES (?, {a: ?, b: ?})", 0, 0, null);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null)));
+
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", null, "b", "abc"));
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc")));
+    }
+
+    @Test
+    public void testUpdateNonFrozenUDT() throws Throwable
+    {
+        String typeName = createType("CREATE TYPE %s (a int, b text)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + typeName + ")");
+
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc"));
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc")));
+
+        // overwrite the whole UDT
+        execute("UPDATE %s SET v = ? WHERE k = ?", userType("a", 1, "b", "def"), 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 1, "b", "def")));
+
+        execute("UPDATE %s SET v = ? WHERE k = ?", userType("a", 0, "b", null), 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null)));
+
+        execute("UPDATE %s SET v = ? WHERE k = ?", userType("a", null, "b", "abc"), 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc")));
+
+        // individually set fields to non-null values
+        execute("UPDATE %s SET v.a = ? WHERE k = ?", 1, 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 1, "b", "abc")));
+
+        execute("UPDATE %s SET v.b = ? WHERE k = ?", "def", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 1, "b", "def")));
+
+        execute("UPDATE %s SET v.a = ?, v.b = ? WHERE k = ?", 0, "abc", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc")));
+
+        execute("UPDATE %s SET v.b = ?, v.a = ? WHERE k = ?", "abc", 0, 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc")));
+
+        // individually set fields to null values
+        execute("UPDATE %s SET v.a = ? WHERE k = ?", null, 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc")));
+
+        execute("UPDATE %s SET v.a = ? WHERE k = ?", 0, 0);
+        execute("UPDATE %s SET v.b = ? WHERE k = ?", null, 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null)));
+
+        execute("UPDATE %s SET v.a = ? WHERE k = ?", null, 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null));
+
+        assertInvalid("UPDATE %s SET v.bad = ? FROM %s WHERE k = ?", 0, 0);
+        assertInvalid("UPDATE %s SET v = ? FROM %s WHERE k = ?", 0, 0);
+        assertInvalid("UPDATE %s SET v = ? FROM %s WHERE k = ?", userType("a", 1, "b", "abc", "bad", 123), 0);
+    }
+
+    @Test
+    public void testDeleteNonFrozenUDT() throws Throwable
+    {
+        String typeName = createType("CREATE TYPE %s (a int, b text)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + typeName + ")");
+
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc"));
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", "abc")));
+
+        execute("DELETE v.b FROM %s WHERE k = ?", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", 0, "b", null)));
+
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc"));
+        execute("DELETE v.a FROM %s WHERE k = ?", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, userType("a", null, "b", "abc")));
+
+        execute("DELETE v.b FROM %s WHERE k = ?", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null));
+
+        // delete both fields at once
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc"));
+        execute("DELETE v.a, v.b FROM %s WHERE k = ?", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null));
+
+        // same, but reverse field order
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc"));
+        execute("DELETE v.b, v.a FROM %s WHERE k = ?", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null));
+
+        // delete the whole thing at once
+        execute("INSERT INTO %s (k, v) VALUES (?, ?)", 0, userType("a", 0, "b", "abc"));
+        execute("DELETE v FROM %s WHERE k = ?", 0);
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 0), row(0, null));
+
+        assertInvalid("DELETE v.bad FROM %s WHERE k = ?", 0);
+    }
+
     private String typeWithKs(String type1)
     {
         return keyspace() + '.' + type1;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/677230df/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index ade80bb..9094d4f 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@ -384,6 +384,377 @@ public class InsertUpdateIfConditionTest extends CQLTester
         assertRows(execute("INSERT INTO %s (partition, key, owner) VALUES ('a', 'c', 'x') IF NOT EXISTS"), row(true));
     }
 
+    @Test
+    public void testWholeUDT() throws Throwable
+    {
+        String typename = createType("CREATE TYPE %s (a int, b text)");
+        String myType = KEYSPACE + '.' + typename;
+
+        for (boolean frozen : new boolean[] {false, true})
+        {
+            createTable(String.format("CREATE TABLE %%s (k int PRIMARY KEY, v %s)",
+                                      frozen
+                                      ? "frozen<" + myType + ">"
+                                      : myType));
+
+            Object v = userType("a", 0, "b", "abc");
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v = {a: 0, b: 'abc'}", v);
+            checkAppliesUDT("v != null", v);
+            checkAppliesUDT("v != {a: 1, b: 'abc'}", v);
+            checkAppliesUDT("v != {a: 0, b: 'def'}", v);
+            checkAppliesUDT("v > {a: -1, b: 'abc'}", v);
+            checkAppliesUDT("v > {a: 0, b: 'aaa'}", v);
+            checkAppliesUDT("v > {a: 0}", v);
+            checkAppliesUDT("v >= {a: 0, b: 'aaa'}", v);
+            checkAppliesUDT("v >= {a: 0, b: 'abc'}", v);
+            checkAppliesUDT("v < {a: 0, b: 'zzz'}", v);
+            checkAppliesUDT("v < {a: 1, b: 'abc'}", v);
+            checkAppliesUDT("v < {a: 1}", v);
+            checkAppliesUDT("v <= {a: 0, b: 'zzz'}", v);
+            checkAppliesUDT("v <= {a: 0, b: 'abc'}", v);
+            checkAppliesUDT("v IN (null, {a: 0, b: 'abc'}, {a: 1})", v);
+
+            // multiple conditions
+            checkAppliesUDT("v > {a: -1, b: 'abc'} AND v > {a: 0}", v);
+            checkAppliesUDT("v != null AND v IN ({a: 0, b: 'abc'})", v);
+
+            // should not apply
+            checkDoesNotApplyUDT("v = {a: 0, b: 'def'}", v);
+            checkDoesNotApplyUDT("v = {a: 1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v = null", v);
+            checkDoesNotApplyUDT("v != {a: 0, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v > {a: 1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v > {a: 0, b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v >= {a: 1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v >= {a: 0, b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v < {a: -1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v < {a: 0, b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v <= {a: -1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v <= {a: 0, b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v IN ({a: 0}, {b: 'abc'}, {a: 0, b: 'def'}, null)", v);
+            checkDoesNotApplyUDT("v IN ()", v);
+
+            // multiple conditions
+            checkDoesNotApplyUDT("v IN () AND v IN ({a: 0, b: 'abc'})", v);
+            checkDoesNotApplyUDT("v > {a: 0, b: 'aaa'} AND v < {a: 0, b: 'aaa'}", v);
+
+            // invalid conditions
+            checkInvalidUDT("v = {a: 1, b: 'abc', c: 'foo'}", v, InvalidRequestException.class);
+            checkInvalidUDT("v = {foo: 'foo'}", v, InvalidRequestException.class);
+            checkInvalidUDT("v < {a: 1, b: 'abc', c: 'foo'}", v, InvalidRequestException.class);
+            checkInvalidUDT("v < null", v, InvalidRequestException.class);
+            checkInvalidUDT("v <= {a: 1, b: 'abc', c: 'foo'}", v, InvalidRequestException.class);
+            checkInvalidUDT("v <= null", v, InvalidRequestException.class);
+            checkInvalidUDT("v > {a: 1, b: 'abc', c: 'foo'}", v, InvalidRequestException.class);
+            checkInvalidUDT("v > null", v, InvalidRequestException.class);
+            checkInvalidUDT("v >= {a: 1, b: 'abc', c: 'foo'}", v, InvalidRequestException.class);
+            checkInvalidUDT("v >= null", v, InvalidRequestException.class);
+            checkInvalidUDT("v IN null", v, SyntaxException.class);
+            checkInvalidUDT("v IN 367", v, SyntaxException.class);
+            checkInvalidUDT("v CONTAINS KEY 123", v, SyntaxException.class);
+            checkInvalidUDT("v CONTAINS 'bar'", v, SyntaxException.class);
+
+
+            /////////////////// null suffix on stored udt ////////////////////
+            v = userType("a", 0, "b", null);
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v = {a: 0}", v);
+            checkAppliesUDT("v = {a: 0, b: null}", v);
+            checkAppliesUDT("v != null", v);
+            checkAppliesUDT("v != {a: 1, b: null}", v);
+            checkAppliesUDT("v != {a: 1}", v);
+            checkAppliesUDT("v != {a: 0, b: 'def'}", v);
+            checkAppliesUDT("v > {a: -1, b: 'abc'}", v);
+            checkAppliesUDT("v > {a: -1}", v);
+            checkAppliesUDT("v >= {a: 0}", v);
+            checkAppliesUDT("v >= {a: -1, b: 'abc'}", v);
+            checkAppliesUDT("v < {a: 0, b: 'zzz'}", v);
+            checkAppliesUDT("v < {a: 1, b: 'abc'}", v);
+            checkAppliesUDT("v < {a: 1}", v);
+            checkAppliesUDT("v <= {a: 0, b: 'zzz'}", v);
+            checkAppliesUDT("v <= {a: 0}", v);
+            checkAppliesUDT("v IN (null, {a: 0, b: 'abc'}, {a: 0})", v);
+
+            // multiple conditions
+            checkAppliesUDT("v > {a: -1, b: 'abc'} AND v >= {a: 0}", v);
+            checkAppliesUDT("v != null AND v IN ({a: 0}, {a: 0, b: null})", v);
+
+            // should not apply
+            checkDoesNotApplyUDT("v = {a: 0, b: 'def'}", v);
+            checkDoesNotApplyUDT("v = {a: 1}", v);
+            checkDoesNotApplyUDT("v = {b: 'abc'}", v);
+            checkDoesNotApplyUDT("v = null", v);
+            checkDoesNotApplyUDT("v != {a: 0}", v);
+            checkDoesNotApplyUDT("v != {a: 0, b: null}", v);
+            checkDoesNotApplyUDT("v > {a: 1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v > {a: 0}", v);
+            checkDoesNotApplyUDT("v >= {a: 1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v >= {a: 1}", v);
+            checkDoesNotApplyUDT("v < {a: -1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v < {a: -1}", v);
+            checkDoesNotApplyUDT("v < {a: 0}", v);
+            checkDoesNotApplyUDT("v <= {a: -1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v <= {a: -1}", v);
+            checkDoesNotApplyUDT("v IN ({a: 1}, {b: 'abc'}, {a: 0, b: 'def'}, null)", v);
+            checkDoesNotApplyUDT("v IN ()", v);
+
+            // multiple conditions
+            checkDoesNotApplyUDT("v IN () AND v IN ({a: 0})", v);
+            checkDoesNotApplyUDT("v > {a: -1} AND v < {a: 0}", v);
+
+
+            /////////////////// null prefix on stored udt ////////////////////
+            v = userType("a", null, "b", "abc");
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v = {a: null, b: 'abc'}", v);
+            checkAppliesUDT("v = {b: 'abc'}", v);
+            checkAppliesUDT("v != null", v);
+            checkAppliesUDT("v != {a: 0, b: 'abc'}", v);
+            checkAppliesUDT("v != {a: 0}", v);
+            checkAppliesUDT("v != {b: 'def'}", v);
+            checkAppliesUDT("v > {a: null, b: 'aaa'}", v);
+            checkAppliesUDT("v > {b: 'aaa'}", v);
+            checkAppliesUDT("v >= {a: null, b: 'aaa'}", v);
+            checkAppliesUDT("v >= {b: 'abc'}", v);
+            checkAppliesUDT("v < {a: null, b: 'zzz'}", v);
+            checkAppliesUDT("v < {a: 0, b: 'abc'}", v);
+            checkAppliesUDT("v < {a: 0}", v);
+            checkAppliesUDT("v < {b: 'zzz'}", v);
+            checkAppliesUDT("v <= {a: null, b: 'zzz'}", v);
+            checkAppliesUDT("v <= {a: 0}", v);
+            checkAppliesUDT("v <= {b: 'abc'}", v);
+            checkAppliesUDT("v IN (null, {a: null, b: 'abc'}, {a: 0})", v);
+            checkAppliesUDT("v IN (null, {a: 0, b: 'abc'}, {b: 'abc'})", v);
+
+            // multiple conditions
+            checkAppliesUDT("v > {b: 'aaa'} AND v >= {b: 'abc'}", v);
+            checkAppliesUDT("v != null AND v IN ({a: 0}, {a: null, b: 'abc'})", v);
+
+            // should not apply
+            checkDoesNotApplyUDT("v = {a: 0, b: 'def'}", v);
+            checkDoesNotApplyUDT("v = {a: 1}", v);
+            checkDoesNotApplyUDT("v = {b: 'def'}", v);
+            checkDoesNotApplyUDT("v = null", v);
+            checkDoesNotApplyUDT("v != {b: 'abc'}", v);
+            checkDoesNotApplyUDT("v != {a: null, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v > {a: 1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v > {a: null, b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v > {b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v >= {a: null, b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v >= {a: 1}", v);
+            checkDoesNotApplyUDT("v >= {b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v < {a: null, b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v < {b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v <= {a: null, b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v <= {b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v IN ({a: 1}, {a: 1, b: 'abc'}, {a: null, b: 'def'}, null)", v);
+            checkDoesNotApplyUDT("v IN ()", v);
+
+            // multiple conditions
+            checkDoesNotApplyUDT("v IN () AND v IN ({b: 'abc'})", v);
+            checkDoesNotApplyUDT("v IN () AND v IN ({a: null, b: 'abc'})", v);
+            checkDoesNotApplyUDT("v > {a: -1} AND v < {a: 0}", v);
+
+
+            /////////////////// null udt ////////////////////
+            v = null;
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v = null", v);
+            checkAppliesUDT("v IN (null, {a: null, b: 'abc'}, {a: 0})", v);
+            checkAppliesUDT("v IN (null, {a: 0, b: 'abc'}, {b: 'abc'})", v);
+
+            // multiple conditions
+            checkAppliesUDT("v = null AND v IN (null, {a: 0}, {a: null, b: 'abc'})", v);
+
+            // should not apply
+            checkDoesNotApplyUDT("v = {a: 0, b: 'def'}", v);
+            checkDoesNotApplyUDT("v = {a: 1}", v);
+            checkDoesNotApplyUDT("v = {b: 'def'}", v);
+            checkDoesNotApplyUDT("v != null", v);
+            checkDoesNotApplyUDT("v > {a: 1, b: 'abc'}", v);
+            checkDoesNotApplyUDT("v > {a: null, b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v > {b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v >= {a: null, b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v >= {a: 1}", v);
+            checkDoesNotApplyUDT("v >= {b: 'zzz'}", v);
+            checkDoesNotApplyUDT("v < {a: null, b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v < {b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v <= {a: null, b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v <= {b: 'aaa'}", v);
+            checkDoesNotApplyUDT("v IN ({a: 1}, {a: 1, b: 'abc'}, {a: null, b: 'def'})", v);
+            checkDoesNotApplyUDT("v IN ()", v);
+
+            // multiple conditions
+            checkDoesNotApplyUDT("v IN () AND v IN ({b: 'abc'})", v);
+            checkDoesNotApplyUDT("v > {a: -1} AND v < {a: 0}", v);
+
+        }
+    }
+
+    @Test
+    public void testUDTField() throws Throwable
+    {
+        String typename = createType("CREATE TYPE %s (a int, b text)");
+        String myType = KEYSPACE + '.' + typename;
+
+        for (boolean frozen : new boolean[] {false, true})
+        {
+            createTable(String.format("CREATE TABLE %%s (k int PRIMARY KEY, v %s)",
+                                      frozen
+                                      ? "frozen<" + myType + ">"
+                                      : myType));
+
+            Object v = userType("a", 0, "b", "abc");
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v.a = 0", v);
+            checkAppliesUDT("v.b = 'abc'", v);
+            checkAppliesUDT("v.a < 1", v);
+            checkAppliesUDT("v.b < 'zzz'", v);
+            checkAppliesUDT("v.b <= 'bar'", v);
+            checkAppliesUDT("v.b > 'aaa'", v);
+            checkAppliesUDT("v.b >= 'abc'", v);
+            checkAppliesUDT("v.a != -1", v);
+            checkAppliesUDT("v.b != 'xxx'", v);
+            checkAppliesUDT("v.a != null", v);
+            checkAppliesUDT("v.b != null", v);
+            checkAppliesUDT("v.a IN (null, 0, 1)", v);
+            checkAppliesUDT("v.b IN (null, 'xxx', 'abc')", v);
+            checkAppliesUDT("v.b > 'aaa' AND v.b < 'zzz'", v);
+            checkAppliesUDT("v.a = 0 AND v.b > 'aaa'", v);
+
+            // do not apply
+            checkDoesNotApplyUDT("v.a = -1", v);
+            checkDoesNotApplyUDT("v.b = 'xxx'", v);
+            checkDoesNotApplyUDT("v.a < -1", v);
+            checkDoesNotApplyUDT("v.b < 'aaa'", v);
+            checkDoesNotApplyUDT("v.b <= 'aaa'", v);
+            checkDoesNotApplyUDT("v.b > 'zzz'", v);
+            checkDoesNotApplyUDT("v.b >= 'zzz'", v);
+            checkDoesNotApplyUDT("v.a != 0", v);
+            checkDoesNotApplyUDT("v.b != 'abc'", v);
+            checkDoesNotApplyUDT("v.a IN (null, -1)", v);
+            checkDoesNotApplyUDT("v.b IN (null, 'xxx')", v);
+            checkDoesNotApplyUDT("v.a IN ()", v);
+            checkDoesNotApplyUDT("v.b IN ()", v);
+            checkDoesNotApplyUDT("v.b != null AND v.b IN ()", v);
+
+            // invalid
+            checkInvalidUDT("v.c = null", v, InvalidRequestException.class);
+            checkInvalidUDT("v.a < null", v, InvalidRequestException.class);
+            checkInvalidUDT("v.a <= null", v, InvalidRequestException.class);
+            checkInvalidUDT("v.a > null", v, InvalidRequestException.class);
+            checkInvalidUDT("v.a >= null", v, InvalidRequestException.class);
+            checkInvalidUDT("v.a IN null", v, SyntaxException.class);
+            checkInvalidUDT("v.a IN 367", v, SyntaxException.class);
+            checkInvalidUDT("v.b IN (1, 2, 3)", v, InvalidRequestException.class);
+            checkInvalidUDT("v.a CONTAINS 367", v, SyntaxException.class);
+            checkInvalidUDT("v.a CONTAINS KEY 367", v, SyntaxException.class);
+
+
+            /////////////// null suffix on udt ////////////////
+            v = userType("a", 0, "b", null);
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v.a = 0", v);
+            checkAppliesUDT("v.b = null", v);
+            checkAppliesUDT("v.b != 'xxx'", v);
+            checkAppliesUDT("v.a != null", v);
+            checkAppliesUDT("v.a IN (null, 0, 1)", v);
+            checkAppliesUDT("v.b IN (null, 'xxx', 'abc')", v);
+            checkAppliesUDT("v.a = 0 AND v.b = null", v);
+
+            // do not apply
+            checkDoesNotApplyUDT("v.b = 'abc'", v);
+            checkDoesNotApplyUDT("v.a < -1", v);
+            checkDoesNotApplyUDT("v.b < 'aaa'", v);
+            checkDoesNotApplyUDT("v.b <= 'aaa'", v);
+            checkDoesNotApplyUDT("v.b > 'zzz'", v);
+            checkDoesNotApplyUDT("v.b >= 'zzz'", v);
+            checkDoesNotApplyUDT("v.a != 0", v);
+            checkDoesNotApplyUDT("v.b != null", v);
+            checkDoesNotApplyUDT("v.a IN (null, -1)", v);
+            checkDoesNotApplyUDT("v.b IN ('xxx', 'abc')", v);
+            checkDoesNotApplyUDT("v.a IN ()", v);
+            checkDoesNotApplyUDT("v.b IN ()", v);
+            checkDoesNotApplyUDT("v.b != null AND v.b IN ()", v);
+
+
+            /////////////// null prefix on udt ////////////////
+            v = userType("a", null, "b", "abc");
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v.a = null", v);
+            checkAppliesUDT("v.b = 'abc'", v);
+            checkAppliesUDT("v.a != 0", v);
+            checkAppliesUDT("v.b != null", v);
+            checkAppliesUDT("v.a IN (null, 0, 1)", v);
+            checkAppliesUDT("v.b IN (null, 'xxx', 'abc')", v);
+            checkAppliesUDT("v.a = null AND v.b = 'abc'", v);
+
+            // do not apply
+            checkDoesNotApplyUDT("v.a = 0", v);
+            checkDoesNotApplyUDT("v.a < -1", v);
+            checkDoesNotApplyUDT("v.b >= 'zzz'", v);
+            checkDoesNotApplyUDT("v.a != null", v);
+            checkDoesNotApplyUDT("v.b != 'abc'", v);
+            checkDoesNotApplyUDT("v.a IN (-1, 0)", v);
+            checkDoesNotApplyUDT("v.b IN (null, 'xxx')", v);
+            checkDoesNotApplyUDT("v.a IN ()", v);
+            checkDoesNotApplyUDT("v.b IN ()", v);
+            checkDoesNotApplyUDT("v.b != null AND v.b IN ()", v);
+
+
+            /////////////// null udt ////////////////
+            v = null;
+            execute("INSERT INTO %s (k, v) VALUES (0, ?)", v);
+
+            checkAppliesUDT("v.a = null", v);
+            checkAppliesUDT("v.b = null", v);
+            checkAppliesUDT("v.a != 0", v);
+            checkAppliesUDT("v.b != 'abc'", v);
+            checkAppliesUDT("v.a IN (null, 0, 1)", v);
+            checkAppliesUDT("v.b IN (null, 'xxx', 'abc')", v);
+            checkAppliesUDT("v.a = null AND v.b = null", v);
+
+            // do not apply
+            checkDoesNotApplyUDT("v.a = 0", v);
+            checkDoesNotApplyUDT("v.a < -1", v);
+            checkDoesNotApplyUDT("v.b >= 'zzz'", v);
+            checkDoesNotApplyUDT("v.a != null", v);
+            checkDoesNotApplyUDT("v.b != null", v);
+            checkDoesNotApplyUDT("v.a IN (-1, 0)", v);
+            checkDoesNotApplyUDT("v.b IN ('xxx', 'abc')", v);
+            checkDoesNotApplyUDT("v.a IN ()", v);
+            checkDoesNotApplyUDT("v.b IN ()", v);
+            checkDoesNotApplyUDT("v.b != null AND v.b IN ()", v);
+        }
+    }
+
+    void checkAppliesUDT(String condition, Object value) throws Throwable
+    {
+        assertRows(execute("UPDATE %s SET v = ? WHERE k = 0 IF " + condition, value), row(true));
+        assertRows(execute("SELECT * FROM %s"), row(0, value));
+    }
+
+    void checkDoesNotApplyUDT(String condition, Object value) throws Throwable
+    {
+        assertRows(execute("UPDATE %s SET v = ? WHERE k = 0 IF " + condition, value),
+                   row(false, value));
+        assertRows(execute("SELECT * FROM %s"), row(0, value));
+    }
+
+    void checkInvalidUDT(String condition, Object value, Class<? extends Throwable> expected) throws Throwable
+    {
+        assertInvalidThrow(expected, "UPDATE %s SET v = ?  WHERE k = 0 IF " + condition, value);
+        assertRows(execute("SELECT * FROM %s"), row(0, value));
+    }
+
     /**
      * Migrated from cql_tests.py:TestCQL.whole_list_conditional_test()
      */

http://git-wip-us.apache.org/repos/asf/cassandra/blob/677230df/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
index 0340fd3..9432c90 100644
--- a/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
+++ b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
@@ -87,7 +87,7 @@ public class LegacySchemaMigratorTest
         }
 
         // make sure that we've read *exactly* the same set of keyspaces/tables/types/functions
-        assertEquals(expected, actual);
+        assertEquals(expected.diff(actual).toString(), expected, actual);
 
         // check that the build status of all indexes has been updated to use the new
         // format of index name: the index_name column of system.IndexInfo used to
@@ -311,17 +311,20 @@ public class LegacySchemaMigratorTest
         UserType udt1 = new UserType(keyspace,
                                      bytes("udt1"),
                                      new ArrayList<ByteBuffer>() {{ add(bytes("col1")); add(bytes("col2")); }},
-                                     new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }});
+                                     new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }},
+                                     true);
 
         UserType udt2 = new UserType(keyspace,
                                      bytes("udt2"),
                                      new ArrayList<ByteBuffer>() {{ add(bytes("col3")); add(bytes("col4")); }},
-                                     new ArrayList<AbstractType<?>>() {{ add(BytesType.instance); add(BooleanType.instance); }});
+                                     new ArrayList<AbstractType<?>>() {{ add(BytesType.instance); add(BooleanType.instance); }},
+                                     true);
 
         UserType udt3 = new UserType(keyspace,
                                      bytes("udt3"),
                                      new ArrayList<ByteBuffer>() {{ add(bytes("col5")); }},
-                                     new ArrayList<AbstractType<?>>() {{ add(AsciiType.instance); }});
+                                     new ArrayList<AbstractType<?>>() {{ add(AsciiType.instance); }},
+                                     true);
 
         return KeyspaceMetadata.create(keyspace,
                                        KeyspaceParams.simple(1),
@@ -431,12 +434,14 @@ public class LegacySchemaMigratorTest
         UserType udt1 = new UserType(keyspace,
                                      bytes("udt1"),
                                      new ArrayList<ByteBuffer>() {{ add(bytes("col1")); add(bytes("col2")); }},
-                                     new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }});
+                                     new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }},
+                                     true);
 
         UserType udt2 = new UserType(keyspace,
                                      bytes("udt2"),
                                      new ArrayList<ByteBuffer>() {{ add(bytes("col1")); add(bytes("col2")); }},
-                                     new ArrayList<AbstractType<?>>() {{ add(ListType.getInstance(udt1, false)); add(Int32Type.instance); }});
+                                     new ArrayList<AbstractType<?>>() {{ add(ListType.getInstance(udt1, false)); add(Int32Type.instance); }},
+                                     true);
 
         UDFunction udf1 = UDFunction.create(new FunctionName(keyspace, "udf"),
                                             ImmutableList.of(new ColumnIdentifier("col1", false), new ColumnIdentifier("col2", false)),
@@ -478,12 +483,14 @@ public class LegacySchemaMigratorTest
         UserType udt1 = new UserType(keyspace,
                                      bytes("udt1"),
                                      new ArrayList<ByteBuffer>() {{ add(bytes("col1")); add(bytes("col2")); }},
-                                     new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }});
+                                     new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }},
+                                     true);
 
         UserType udt2 = new UserType(keyspace,
                                      bytes("udt2"),
                                      new ArrayList<ByteBuffer>() {{ add(bytes("col1")); add(bytes("col2")); }},
-                                     new ArrayList<AbstractType<?>>() {{ add(ListType.getInstance(udt1, false)); add(Int32Type.instance); }});
+                                     new ArrayList<AbstractType<?>>() {{ add(ListType.getInstance(udt1, false)); add(Int32Type.instance); }},
+                                     true);
 
         UDFunction udf1 = UDFunction.create(new FunctionName(keyspace, "udf1"),
                                             ImmutableList.of(new ColumnIdentifier("col1", false), new ColumnIdentifier("col2", false)),

http://git-wip-us.apache.org/repos/asf/cassandra/blob/677230df/test/unit/org/apache/cassandra/transport/SerDeserTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/transport/SerDeserTest.java b/test/unit/org/apache/cassandra/transport/SerDeserTest.java
index fdb346e..0b19151 100644
--- a/test/unit/org/apache/cassandra/transport/SerDeserTest.java
+++ b/test/unit/org/apache/cassandra/transport/SerDeserTest.java
@@ -184,7 +184,8 @@ public class SerDeserTest
         UserType udt = new UserType("ks",
                                     bb("myType"),
                                     Arrays.asList(bb("f1"), bb("f2"), bb("f3"), bb("f4")),
-                                    Arrays.asList(LongType.instance, lt, st, mt));
+                                    Arrays.asList(LongType.instance, lt, st, mt),
+                                    true);
 
         Map<ColumnIdentifier, Term.Raw> value = new HashMap<>();
         value.put(ci("f1"), lit(42));


Mime
View raw message