You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sn...@apache.org on 2016/12/07 12:38:36 UTC

[01/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-2.2 2e93398ce -> 0b97c5d1f
  refs/heads/cassandra-3.0 95d0b671d -> 3aefe3565
  refs/heads/cassandra-3.X 57c2003de -> d7b6b7a34
  refs/heads/trunk 8253912a6 -> d2a92e4b1


http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index bcfe871..d4d2a10 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@ -17,9 +17,6 @@
  */
 package org.apache.cassandra.cql3.validation.entities;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -34,14 +31,9 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.Row;
-import com.datastax.driver.core.TupleType;
-import com.datastax.driver.core.TupleValue;
-import com.datastax.driver.core.UDTValue;
 import com.datastax.driver.core.exceptions.InvalidQueryException;
 import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.cql3.CQL3Type;
 import org.apache.cassandra.cql3.CQLTester;
 import org.apache.cassandra.cql3.QueryProcessor;
 import org.apache.cassandra.cql3.UntypedResultSet;
@@ -50,13 +42,11 @@ import org.apache.cassandra.cql3.functions.Functions;
 import org.apache.cassandra.cql3.functions.UDFunction;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.dht.ByteOrderedPartitioner;
-import org.apache.cassandra.exceptions.FunctionExecutionException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.transport.Event;
 import org.apache.cassandra.transport.Server;
 import org.apache.cassandra.transport.messages.ResultMessage;
-import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.UUIDGen;
 
 public class UFTest extends CQLTester
@@ -295,7 +285,7 @@ public class UFTest extends CQLTester
         return prepared;
     }
 
-    public void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
+    private void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
     {
         // prepare a statement which doesn't use any function for a control
         createTable("CREATE TABLE %s (" +
@@ -584,164 +574,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaFunctionNoParameters() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = "\n  return 1L;\n";
-
-        String fName = createFunction(KEYSPACE, "",
-                                      "CREATE OR REPLACE FUNCTION %s() " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" +functionBody + "';");
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           KEYSPACE, parseFunctionName(fName).name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
-                   row(1, 1d, 1L),
-                   row(2, 2d, 1L),
-                   row(3, 3d, 1L)
-        );
-    }
-
-    @Test
-    public void testJavaFunctionInvalidBodies() throws Throwable
-    {
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
-        }
-
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz;" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
-        }
-    }
-
-    @Test
-    public void testJavaFunctionInvalidReturn() throws Throwable
-    {
-        assertInvalidMessage("system keyspace is not user-modifiable",
-                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE JAVA\n" +
-                             "AS 'return 1L;';");
-    }
-
-    @Test
-    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val bigint)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return Double.valueOf(val);';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
-        assertInvalidMessage("val cannot be passed as argument 0 of function",
-                             "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaFunctionCounter() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val counter)");
-
-        String fName = createFunction(KEYSPACE, "counter",
-                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return val + 1;';");
-
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1L, 2L));
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 4L, 5L));
-        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-    }
-
-    @Test
     public void testFunctionInTargetKeyspace() throws Throwable
     {
         createTable("CREATE TABLE %s (key int primary key, val double)");
@@ -869,140 +701,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaKeyspaceFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin( val );\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                     "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                     "CALLED ON NULL INPUT " +
-                                     "RETURNS double " +
-                                     "LANGUAGE JAVA " +
-                                     "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaRuntimeException() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  throw new RuntimeException(\"oh no!\");\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-
-        // function throws a RuntimeException which is wrapped by FunctionExecutionException
-        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaDollarQuotedFunction() throws Throwable
-    {
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (input == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE FUNCTION %s( input double ) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$" + functionBody + "$$;");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-    }
-
-    @Test
-    public void testJavaSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                                     "CREATE FUNCTION %s( lst list<double> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS list<double> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return lst;$$;");
-        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                                     "CREATE FUNCTION %s( st set<text> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS set<text> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return st;$$;");
-        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS map<int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return mp;$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
     public void testWrongKeyspace() throws Throwable
     {
         String typeName = createType("CREATE TYPE %s (txt text, i int)");
@@ -1135,206 +833,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
-                                     "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS tuple<double, text, int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavaTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS " + tupleTypeDef + ' ' +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup;$$;");
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       Double.valueOf(tup.getDouble(0));$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS list<double> " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return " +
-                                      "       tup.getList(1, Double.class);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getSet(2, String.class);$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getMap(3, Integer.class, Boolean.class);$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavaUserTypeWithUse() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            executeNet(version, "USE " + KEYSPACE);
-
-            executeNet(version,
-                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS " + type + " " +
-                       "LANGUAGE java " +
-                       "AS $$return " +
-                       "     udt;$$;");
-            try
-            {
-                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
-                Assert.assertEquals(1, rowsNet.size());
-                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-                Assert.assertEquals("one", udtVal.getString("txt"));
-                Assert.assertEquals(1, udtVal.getInt("i"));
-            }
-            finally
-            {
-                executeNet(version, "DROP FUNCTION f_use1");
-            }
-        }
-    }
-
-    @Test
-    public void testJavaUserType() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt0 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS " + type + " " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt;$$;");
-        String fUdt1 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt.getString(\"txt\");$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
-            Assert.assertEquals(1, rowsNet.size());
-            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-            Assert.assertEquals("one", udtVal.getString("txt"));
-            Assert.assertEquals(1, udtVal.getInt("i"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                          row("one"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                          row(1));
-        }
-    }
-
-    @Test
     public void testUserTypeDrop() throws Throwable
     {
         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
@@ -1372,686 +870,22 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaUserTypeRenameField() throws Throwable
+    public void testDuplicateArgNames() throws Throwable
     {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+        assertInvalidMessage("duplicate argument names for given function",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE javascript\n" +
+                             "AS '\"foo bar\";';");
+    }
 
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return udt.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-
-        execute("ALTER TYPE " + type + " RENAME txt TO str");
-
-        assertInvalidMessage("txt is not a field defined in this UDT",
-                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
-
-        execute("ALTER TYPE " + type + " RENAME str TO txt");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-    }
-
-    @Test
-    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName1replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + ") " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS double " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS " + type + " " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt;$$;");
-
-        String fName1noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "CALLED ON NULL INPUT " +
-                                                "RETURNS double " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "RETURNS NULL ON NULL INPUT " +
-                                                "RETURNS " + type + " " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return udt;$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        // add field
-
-        execute("ALTER TYPE " + type + " ADD added double");
-
-        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
-
-        // note: type references of functions remain at the state _before_ the type mutation
-        // means we need to recreate the functions
-
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt.getString(\"txt\");$$;",
-                              fName1replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
-                              fName2replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
-                              fName3replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS %s " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt;$$;",
-                              fName4replace, type, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        // un-replaced functions will work since the user type has changed
-        // and the UDF has exchanged the user type reference
-
-        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        execute("DROP FUNCTION " + fName1replace);
-        execute("DROP FUNCTION " + fName2replace);
-        execute("DROP FUNCTION " + fName3replace);
-        execute("DROP FUNCTION " + fName4replace);
-        execute("DROP FUNCTION " + fName1noReplace);
-        execute("DROP FUNCTION " + fName2noReplace);
-        execute("DROP FUNCTION " + fName3noReplace);
-        execute("DROP FUNCTION " + fName4noReplace);
-    }
-
-    @Test
-    public void testJavaUTCollections() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
-                              "     return udtVal.getString(\"txt\");$$;");
-        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
-                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS text " +
-                                       "LANGUAGE java\n" +
-                                       "AS $$" +
-                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
-                                       "     return udtVal.getString(\"txt\");$$;");
-        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
-                              "     return udtVal.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row("three", "one", "two"));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                "CREATE FUNCTION %s( lst list<double> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS 'lst;';");
-        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                "CREATE FUNCTION %s( st set<text> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS 'st;';");
-        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS 'mp;';");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
-    public void testJavascriptTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
-                "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, text, int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavascriptTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup;$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getDouble(0);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
-        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        // same test - but via native protocol
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavascriptUserType() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt1 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS " + type + " " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt;$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt.getString(\"txt\");$$;");
-        String fUdt3 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "     udt.getInt(\"i\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-    }
-
-    @Test
-    public void testJavascriptUTCollections() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "        lst.get(1).getString(\"txt\");$$;");
-        createFunctionOverload(fName, "set<frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        st.iterator().next().getString(\"txt\");$$;");
-        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                // list<frozen<UDT>>
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                // set<frozen<UDT>>
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                // map<int, frozen<UDT>>
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
-                   row("three"));
-        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
-                   row("two"));
-
-        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
-        assertRows(execute(cqlSelect),
-                   row("three", "one", "two"));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, cqlSelect),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("javascript", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavascriptBadReturnType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '\"string\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ClassCastException
-        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavascriptThrow() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                       "CREATE OR REPLACE FUNCTION %s(val double) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS double " +
-                       "LANGUAGE javascript\n" +
-                       "AS 'throw \"fool\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ScriptException
-        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testDuplicateArgNames() throws Throwable
-    {
-        assertInvalidMessage("duplicate argument names for given function",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE javascript\n" +
-                             "AS '\"foo bar\";';");
-    }
-
-    @Test
-    public void testJavascriptCompileFailure() throws Throwable
-    {
-        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE javascript\n" +
-                             "AS 'foo bar';");
-    }
-
-    @Test
-    public void testScriptInvalidLanguage() throws Throwable
-    {
-        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE artificial_intelligence\n" +
-                             "AS 'question for 42?';");
-    }
-
-    @Test
-    public void testScriptReturnTypeCasting() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-
-        Object[][] variations = {
-                                new Object[]    {   "true",     "boolean",  true    },
-                                new Object[]    {   "false",    "boolean",  false   },
-                                new Object[]    {   "100",      "tinyint",  (byte)100 },
-                                new Object[]    {   "100.",     "tinyint",  (byte)100 },
-                                new Object[]    {   "100",      "smallint", (short)100 },
-                                new Object[]    {   "100.",     "smallint", (short)100 },
-                                new Object[]    {   "100",      "int",      100     },
-                                new Object[]    {   "100.",     "int",      100     },
-                                new Object[]    {   "100",      "double",   100d    },
-                                new Object[]    {   "100.",     "double",   100d    },
-                                new Object[]    {   "100",      "bigint",   100L    },
-                                new Object[]    {   "100.",     "bigint",   100L    },
-                                new Object[]    {   "100",      "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "parseInt(\"100\");", "decimal",  BigDecimal.valueOf(100d)    },
-                                new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object functionBody = variation[0];
-            Object returnType = variation[1];
-            Object expectedResult = variation[2];
-
-            String fName = createFunction(KEYSPACE, "double",
-                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " +returnType + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS '" + functionBody + ";';");
-            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                       row(1, 1d, expectedResult));
-        }
-    }
-
-    @Test
-    public void testScriptParamReturnTypes() throws Throwable
-    {
-        UUID ruuid = UUID.randomUUID();
-        UUID tuuid = UUIDGen.getTimeUUID();
-
-        createTable("CREATE TABLE %s (key int primary key, " +
-                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
-                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
-        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
-                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
-                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
-
-        Object[][] variations = {
-                                new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
-                                new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
-                                new Object[] {  "int",      "ival",     1,                      2  },
-                                new Object[] {  "bigint",   "lval",     1L,                     2L  },
-                                new Object[] {  "float",    "fval",     1f,                     2f  },
-                                new Object[] {  "double",   "dval",     1d,                     2d  },
-                                new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
-                                new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
-                                new Object[] {  "time",     "timval",   1L,                     2L  },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS " + type + ' ' +
-                           "LANGUAGE javascript " +
-                           "AS 'val+1;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-
-        variations = new Object[][] {
-                     new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
-                     new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
-                     new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
-                     new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
-        };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " + type + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS 'val;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-    }
-
-    static class TypesTestDef
-    {
-        final String udfType;
-        final String tableType;
-        final String columnName;
-        final Object referenceValue;
+    private static class TypesTestDef
+    {
+        final String udfType;
+        final String tableType;
+        final String columnName;
+        final Object referenceValue;
 
         String fCheckArgAndReturn;
 
@@ -2274,416 +1108,4 @@ public class UFTest extends CQLTester
             }
         }
     }
-
-    @Test
-    public void testFunctionWithFrozenSetType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<set<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS set<int> " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenListType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<list<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "list<int>",
-                                             "CREATE FUNCTION %s (values list<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "list<int>",
-                                      "CREATE FUNCTION %s (values list<int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS list<int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenMapType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<map<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "map<int, int>",
-                                             "CREATE FUNCTION %s (values map<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "map<int, int>",
-                                      "CREATE FUNCTION %s (values map<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS map<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<tuple<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "tuple<int, int>",
-                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "(null, null)"),
-                   row(1, "(1, 2)"),
-                   row(2, "(4, 5)"),
-                   row(3, "(7, 8)"));
-
-        functionName = createFunction(KEYSPACE,
-                                      "tuple<int, int>",
-                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS tuple<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenUDType() throws Throwable
-    {
-        String myType = createType("CREATE TYPE %s (f int)");
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<" + myType + "> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             myType,
-                                             "CREATE FUNCTION %s (values " + myType + ") " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "{f:0}"),
-                   row(1, "{f:1}"),
-                   row(2, "{f:4}"),
-                   row(3, "{f:7}"));
-
-        functionName = createFunction(KEYSPACE,
-                                      myType,
-                                      "CREATE FUNCTION %s (values " + myType + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS " + myType + " " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
-    }
-
-    @Test
-    public void testEmptyString() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
-        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
-
-        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
-        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
-    }
-
-    @Test
-    public void testAllNativeTypes() throws Throwable
-    {
-        StringBuilder sig = new StringBuilder();
-        StringBuilder args = new StringBuilder();
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            if (sig.length() > 0)
-                sig.append(',');
-            sig.append(type.toString());
-
-            if (args.length() > 0)
-                args.append(',');
-            args.append("arg").append(type.toString()).append(' ').append(type.toString());
-        }
-        createFunction(KEYSPACE, sig.toString(),
-                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS int " +
-                       "LANGUAGE JAVA\n" +
-                       "AS 'return 0;'");
-
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            createFunction(KEYSPACE_PER_TEST, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS int " +
-                           "LANGUAGE JAVA\n" +
-                           "AS 'return 0;'");
-        }
-    }
 }


[05/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index bcfe871..d4d2a10 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@ -17,9 +17,6 @@
  */
 package org.apache.cassandra.cql3.validation.entities;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -34,14 +31,9 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.Row;
-import com.datastax.driver.core.TupleType;
-import com.datastax.driver.core.TupleValue;
-import com.datastax.driver.core.UDTValue;
 import com.datastax.driver.core.exceptions.InvalidQueryException;
 import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.cql3.CQL3Type;
 import org.apache.cassandra.cql3.CQLTester;
 import org.apache.cassandra.cql3.QueryProcessor;
 import org.apache.cassandra.cql3.UntypedResultSet;
@@ -50,13 +42,11 @@ import org.apache.cassandra.cql3.functions.Functions;
 import org.apache.cassandra.cql3.functions.UDFunction;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.dht.ByteOrderedPartitioner;
-import org.apache.cassandra.exceptions.FunctionExecutionException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.transport.Event;
 import org.apache.cassandra.transport.Server;
 import org.apache.cassandra.transport.messages.ResultMessage;
-import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.UUIDGen;
 
 public class UFTest extends CQLTester
@@ -295,7 +285,7 @@ public class UFTest extends CQLTester
         return prepared;
     }
 
-    public void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
+    private void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
     {
         // prepare a statement which doesn't use any function for a control
         createTable("CREATE TABLE %s (" +
@@ -584,164 +574,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaFunctionNoParameters() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = "\n  return 1L;\n";
-
-        String fName = createFunction(KEYSPACE, "",
-                                      "CREATE OR REPLACE FUNCTION %s() " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" +functionBody + "';");
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           KEYSPACE, parseFunctionName(fName).name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
-                   row(1, 1d, 1L),
-                   row(2, 2d, 1L),
-                   row(3, 3d, 1L)
-        );
-    }
-
-    @Test
-    public void testJavaFunctionInvalidBodies() throws Throwable
-    {
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
-        }
-
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz;" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
-        }
-    }
-
-    @Test
-    public void testJavaFunctionInvalidReturn() throws Throwable
-    {
-        assertInvalidMessage("system keyspace is not user-modifiable",
-                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE JAVA\n" +
-                             "AS 'return 1L;';");
-    }
-
-    @Test
-    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val bigint)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return Double.valueOf(val);';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
-        assertInvalidMessage("val cannot be passed as argument 0 of function",
-                             "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaFunctionCounter() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val counter)");
-
-        String fName = createFunction(KEYSPACE, "counter",
-                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return val + 1;';");
-
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1L, 2L));
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 4L, 5L));
-        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-    }
-
-    @Test
     public void testFunctionInTargetKeyspace() throws Throwable
     {
         createTable("CREATE TABLE %s (key int primary key, val double)");
@@ -869,140 +701,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaKeyspaceFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin( val );\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                     "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                     "CALLED ON NULL INPUT " +
-                                     "RETURNS double " +
-                                     "LANGUAGE JAVA " +
-                                     "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaRuntimeException() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  throw new RuntimeException(\"oh no!\");\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-
-        // function throws a RuntimeException which is wrapped by FunctionExecutionException
-        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaDollarQuotedFunction() throws Throwable
-    {
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (input == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE FUNCTION %s( input double ) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$" + functionBody + "$$;");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-    }
-
-    @Test
-    public void testJavaSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                                     "CREATE FUNCTION %s( lst list<double> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS list<double> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return lst;$$;");
-        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                                     "CREATE FUNCTION %s( st set<text> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS set<text> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return st;$$;");
-        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS map<int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return mp;$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
     public void testWrongKeyspace() throws Throwable
     {
         String typeName = createType("CREATE TYPE %s (txt text, i int)");
@@ -1135,206 +833,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
-                                     "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS tuple<double, text, int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavaTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS " + tupleTypeDef + ' ' +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup;$$;");
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       Double.valueOf(tup.getDouble(0));$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS list<double> " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return " +
-                                      "       tup.getList(1, Double.class);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getSet(2, String.class);$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getMap(3, Integer.class, Boolean.class);$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavaUserTypeWithUse() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            executeNet(version, "USE " + KEYSPACE);
-
-            executeNet(version,
-                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS " + type + " " +
-                       "LANGUAGE java " +
-                       "AS $$return " +
-                       "     udt;$$;");
-            try
-            {
-                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
-                Assert.assertEquals(1, rowsNet.size());
-                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-                Assert.assertEquals("one", udtVal.getString("txt"));
-                Assert.assertEquals(1, udtVal.getInt("i"));
-            }
-            finally
-            {
-                executeNet(version, "DROP FUNCTION f_use1");
-            }
-        }
-    }
-
-    @Test
-    public void testJavaUserType() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt0 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS " + type + " " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt;$$;");
-        String fUdt1 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt.getString(\"txt\");$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
-            Assert.assertEquals(1, rowsNet.size());
-            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-            Assert.assertEquals("one", udtVal.getString("txt"));
-            Assert.assertEquals(1, udtVal.getInt("i"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                          row("one"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                          row(1));
-        }
-    }
-
-    @Test
     public void testUserTypeDrop() throws Throwable
     {
         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
@@ -1372,686 +870,22 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaUserTypeRenameField() throws Throwable
+    public void testDuplicateArgNames() throws Throwable
     {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+        assertInvalidMessage("duplicate argument names for given function",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE javascript\n" +
+                             "AS '\"foo bar\";';");
+    }
 
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return udt.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-
-        execute("ALTER TYPE " + type + " RENAME txt TO str");
-
-        assertInvalidMessage("txt is not a field defined in this UDT",
-                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
-
-        execute("ALTER TYPE " + type + " RENAME str TO txt");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-    }
-
-    @Test
-    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName1replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + ") " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS double " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS " + type + " " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt;$$;");
-
-        String fName1noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "CALLED ON NULL INPUT " +
-                                                "RETURNS double " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "RETURNS NULL ON NULL INPUT " +
-                                                "RETURNS " + type + " " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return udt;$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        // add field
-
-        execute("ALTER TYPE " + type + " ADD added double");
-
-        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
-
-        // note: type references of functions remain at the state _before_ the type mutation
-        // means we need to recreate the functions
-
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt.getString(\"txt\");$$;",
-                              fName1replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
-                              fName2replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
-                              fName3replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS %s " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt;$$;",
-                              fName4replace, type, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        // un-replaced functions will work since the user type has changed
-        // and the UDF has exchanged the user type reference
-
-        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        execute("DROP FUNCTION " + fName1replace);
-        execute("DROP FUNCTION " + fName2replace);
-        execute("DROP FUNCTION " + fName3replace);
-        execute("DROP FUNCTION " + fName4replace);
-        execute("DROP FUNCTION " + fName1noReplace);
-        execute("DROP FUNCTION " + fName2noReplace);
-        execute("DROP FUNCTION " + fName3noReplace);
-        execute("DROP FUNCTION " + fName4noReplace);
-    }
-
-    @Test
-    public void testJavaUTCollections() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
-                              "     return udtVal.getString(\"txt\");$$;");
-        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
-                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS text " +
-                                       "LANGUAGE java\n" +
-                                       "AS $$" +
-                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
-                                       "     return udtVal.getString(\"txt\");$$;");
-        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
-                              "     return udtVal.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row("three", "one", "two"));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                "CREATE FUNCTION %s( lst list<double> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS 'lst;';");
-        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                "CREATE FUNCTION %s( st set<text> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS 'st;';");
-        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS 'mp;';");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
-    public void testJavascriptTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
-                "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, text, int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavascriptTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup;$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getDouble(0);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
-        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        // same test - but via native protocol
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavascriptUserType() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt1 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS " + type + " " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt;$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt.getString(\"txt\");$$;");
-        String fUdt3 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "     udt.getInt(\"i\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-    }
-
-    @Test
-    public void testJavascriptUTCollections() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "        lst.get(1).getString(\"txt\");$$;");
-        createFunctionOverload(fName, "set<frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        st.iterator().next().getString(\"txt\");$$;");
-        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                // list<frozen<UDT>>
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                // set<frozen<UDT>>
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                // map<int, frozen<UDT>>
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
-                   row("three"));
-        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
-                   row("two"));
-
-        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
-        assertRows(execute(cqlSelect),
-                   row("three", "one", "two"));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, cqlSelect),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("javascript", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavascriptBadReturnType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '\"string\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ClassCastException
-        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavascriptThrow() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                       "CREATE OR REPLACE FUNCTION %s(val double) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS double " +
-                       "LANGUAGE javascript\n" +
-                       "AS 'throw \"fool\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ScriptException
-        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testDuplicateArgNames() throws Throwable
-    {
-        assertInvalidMessage("duplicate argument names for given function",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE javascript\n" +
-                             "AS '\"foo bar\";';");
-    }
-
-    @Test
-    public void testJavascriptCompileFailure() throws Throwable
-    {
-        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE javascript\n" +
-                             "AS 'foo bar';");
-    }
-
-    @Test
-    public void testScriptInvalidLanguage() throws Throwable
-    {
-        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE artificial_intelligence\n" +
-                             "AS 'question for 42?';");
-    }
-
-    @Test
-    public void testScriptReturnTypeCasting() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-
-        Object[][] variations = {
-                                new Object[]    {   "true",     "boolean",  true    },
-                                new Object[]    {   "false",    "boolean",  false   },
-                                new Object[]    {   "100",      "tinyint",  (byte)100 },
-                                new Object[]    {   "100.",     "tinyint",  (byte)100 },
-                                new Object[]    {   "100",      "smallint", (short)100 },
-                                new Object[]    {   "100.",     "smallint", (short)100 },
-                                new Object[]    {   "100",      "int",      100     },
-                                new Object[]    {   "100.",     "int",      100     },
-                                new Object[]    {   "100",      "double",   100d    },
-                                new Object[]    {   "100.",     "double",   100d    },
-                                new Object[]    {   "100",      "bigint",   100L    },
-                                new Object[]    {   "100.",     "bigint",   100L    },
-                                new Object[]    {   "100",      "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "parseInt(\"100\");", "decimal",  BigDecimal.valueOf(100d)    },
-                                new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object functionBody = variation[0];
-            Object returnType = variation[1];
-            Object expectedResult = variation[2];
-
-            String fName = createFunction(KEYSPACE, "double",
-                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " +returnType + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS '" + functionBody + ";';");
-            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                       row(1, 1d, expectedResult));
-        }
-    }
-
-    @Test
-    public void testScriptParamReturnTypes() throws Throwable
-    {
-        UUID ruuid = UUID.randomUUID();
-        UUID tuuid = UUIDGen.getTimeUUID();
-
-        createTable("CREATE TABLE %s (key int primary key, " +
-                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
-                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
-        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
-                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
-                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
-
-        Object[][] variations = {
-                                new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
-                                new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
-                                new Object[] {  "int",      "ival",     1,                      2  },
-                                new Object[] {  "bigint",   "lval",     1L,                     2L  },
-                                new Object[] {  "float",    "fval",     1f,                     2f  },
-                                new Object[] {  "double",   "dval",     1d,                     2d  },
-                                new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
-                                new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
-                                new Object[] {  "time",     "timval",   1L,                     2L  },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS " + type + ' ' +
-                           "LANGUAGE javascript " +
-                           "AS 'val+1;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-
-        variations = new Object[][] {
-                     new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
-                     new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
-                     new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
-                     new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
-        };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " + type + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS 'val;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-    }
-
-    static class TypesTestDef
-    {
-        final String udfType;
-        final String tableType;
-        final String columnName;
-        final Object referenceValue;
+    private static class TypesTestDef
+    {
+        final String udfType;
+        final String tableType;
+        final String columnName;
+        final Object referenceValue;
 
         String fCheckArgAndReturn;
 
@@ -2274,416 +1108,4 @@ public class UFTest extends CQLTester
             }
         }
     }
-
-    @Test
-    public void testFunctionWithFrozenSetType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<set<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS set<int> " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenListType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<list<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "list<int>",
-                                             "CREATE FUNCTION %s (values list<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "list<int>",
-                                      "CREATE FUNCTION %s (values list<int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS list<int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenMapType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<map<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "map<int, int>",
-                                             "CREATE FUNCTION %s (values map<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "map<int, int>",
-                                      "CREATE FUNCTION %s (values map<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS map<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<tuple<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "tuple<int, int>",
-                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "(null, null)"),
-                   row(1, "(1, 2)"),
-                   row(2, "(4, 5)"),
-                   row(3, "(7, 8)"));
-
-        functionName = createFunction(KEYSPACE,
-                                      "tuple<int, int>",
-                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS tuple<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenUDType() throws Throwable
-    {
-        String myType = createType("CREATE TYPE %s (f int)");
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<" + myType + "> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             myType,
-                                             "CREATE FUNCTION %s (values " + myType + ") " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "{f:0}"),
-                   row(1, "{f:1}"),
-                   row(2, "{f:4}"),
-                   row(3, "{f:7}"));
-
-        functionName = createFunction(KEYSPACE,
-                                      myType,
-                                      "CREATE FUNCTION %s (values " + myType + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS " + myType + " " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
-    }
-
-    @Test
-    public void testEmptyString() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
-        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
-
-        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
-        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
-    }
-
-    @Test
-    public void testAllNativeTypes() throws Throwable
-    {
-        StringBuilder sig = new StringBuilder();
-        StringBuilder args = new StringBuilder();
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            if (sig.length() > 0)
-                sig.append(',');
-            sig.append(type.toString());
-
-            if (args.length() > 0)
-                args.append(',');
-            args.append("arg").append(type.toString()).append(' ').append(type.toString());
-        }
-        createFunction(KEYSPACE, sig.toString(),
-                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS int " +
-                       "LANGUAGE JAVA\n" +
-                       "AS 'return 0;'");
-
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            createFunction(KEYSPACE_PER_TEST, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS int " +
-                           "LANGUAGE JAVA\n" +
-                           "AS 'return 0;'");
-        }
-    }
 }


[23/25] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.X

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
index 0000000,de98748..3f1bcb1
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
@@@ -1,0 -1,549 +1,550 @@@
+ /*
+  * 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.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ import java.util.UUID;
+ 
+ import org.junit.Assert;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.Row;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
++import org.apache.cassandra.transport.ProtocolVersion;
+ import org.apache.cassandra.utils.UUIDGen;
+ 
+ public class UFTypesTest extends CQLTester
+ {
+ 
+     @Test
+     public void testComplexNullValues() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
+                     "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
+ 
+         String fList = createFunction(KEYSPACE, "list<double>",
+                                       "CREATE FUNCTION %s( coll list<double> ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return coll;$$;");
+         String fSet = createFunction(KEYSPACE, "set<text>",
+                                      "CREATE FUNCTION %s( coll set<text> ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return coll;$$;");
+         String fMap = createFunction(KEYSPACE, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( coll map<int, boolean> ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return coll;$$;");
+         String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return val;$$;");
+         String fUdt = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( val " + type + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return val;$$;");
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+         Object t = tuple(1d, "one", 42, false);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
+         execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
+ 
+         execute("SELECT " +
+                 fList + "(lst), " +
+                 fSet + "(st), " +
+                 fMap + "(mp), " +
+                 fTup + "(tup), " +
+                 fUdt + "(udt) FROM %s WHERE key = 1");
+         UntypedResultSet.Row row = execute("SELECT " +
+                                            fList + "(lst) as l, " +
+                                            fSet + "(st) as s, " +
+                                            fMap + "(mp) as m, " +
+                                            fTup + "(tup) as t, " +
+                                            fUdt + "(udt) as u " +
+                                            "FROM %s WHERE key = 1").one();
+         Assert.assertNotNull(row.getBytes("l"));
+         Assert.assertNotNull(row.getBytes("s"));
+         Assert.assertNotNull(row.getBytes("m"));
+         Assert.assertNotNull(row.getBytes("t"));
+         Assert.assertNotNull(row.getBytes("u"));
+         row = execute("SELECT " +
+                       fList + "(lst) as l, " +
+                       fSet + "(st) as s, " +
+                       fMap + "(mp) as m, " +
+                       fTup + "(tup) as t, " +
+                       fUdt + "(udt) as u " +
+                       "FROM %s WHERE key = 2").one();
+         Assert.assertNull(row.getBytes("l"));
+         Assert.assertNull(row.getBytes("s"));
+         Assert.assertNull(row.getBytes("m"));
+         Assert.assertNull(row.getBytes("t"));
+         Assert.assertNull(row.getBytes("u"));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             Row r = executeNet(version, "SELECT " +
+                                         fList + "(lst) as l, " +
+                                         fSet + "(st) as s, " +
+                                         fMap + "(mp) as m, " +
+                                         fTup + "(tup) as t, " +
+                                         fUdt + "(udt) as u " +
+                                         "FROM %s WHERE key = 1").one();
+             Assert.assertNotNull(r.getBytesUnsafe("l"));
+             Assert.assertNotNull(r.getBytesUnsafe("s"));
+             Assert.assertNotNull(r.getBytesUnsafe("m"));
+             Assert.assertNotNull(r.getBytesUnsafe("t"));
+             Assert.assertNotNull(r.getBytesUnsafe("u"));
+             r = executeNet(version, "SELECT " +
+                                     fList + "(lst) as l, " +
+                                     fSet + "(st) as s, " +
+                                     fMap + "(mp) as m, " +
+                                     fTup + "(tup) as t, " +
+                                     fUdt + "(udt) as u " +
+                                     "FROM %s WHERE key = 2").one();
+             Assert.assertNull(r.getBytesUnsafe("l"));
+             Assert.assertNull(r.getBytesUnsafe("s"));
+             Assert.assertNull(r.getBytesUnsafe("m"));
+             Assert.assertNull(r.getBytesUnsafe("t"));
+             Assert.assertNull(r.getBytesUnsafe("u"));
+         }
+     }
+ 
+     private static class TypesTestDef
+     {
+         final String udfType;
+         final String tableType;
+         final String columnName;
+         final Object referenceValue;
+ 
+         String fCheckArgAndReturn;
+ 
+         String fCalledOnNull;
+         String fReturnsNullOnNull;
+ 
+         TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
+         {
+             this.udfType = udfType;
+             this.tableType = tableType;
+             this.columnName = columnName;
+             this.referenceValue = referenceValue;
+         }
+     }
+ 
+     @Test
+     public void testTypesWithAndWithoutNulls() throws Throwable
+     {
+         // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
+ 
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         TypesTestDef[] typeDefs =
+         {
+         //                udf type,            table type,                 column, reference value
+         new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
+         new TypesTestDef("date", "date", "dt", 12345),
+         new TypesTestDef("time", "time", "tim", 12345L),
+         new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
+         new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
+         new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
+         new TypesTestDef("smallint", "smallint", "si", (short) 43),
+         new TypesTestDef("int", "int", "i", 44),
+         new TypesTestDef("bigint", "bigint", "b", 45L),
+         new TypesTestDef("float", "float", "f", 46f),
+         new TypesTestDef("double", "double", "d", 47d),
+         new TypesTestDef("boolean", "boolean", "x", true),
+         new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
+         new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
+         //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
+         new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
+         };
+ 
+         String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
+         String insertDML = "INSERT INTO %s (key";
+         List<Object> values = new ArrayList<>();
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
+             insertDML += ", " + typeDef.columnName;
+             String typeName = typeDef.udfType;
+             typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
+                                                         typeName,
+                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
+                                                         "CALLED ON NULL INPUT " +
+                                                         "RETURNS " + typeName + ' ' +
+                                                         "LANGUAGE java\n" +
+                                                         "AS 'return val;';");
+             typeDef.fCalledOnNull = createFunction(KEYSPACE,
+                                                    typeName,
+                                                    "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
+                                                    "CALLED ON NULL INPUT " +
+                                                    "RETURNS text " +
+                                                    "LANGUAGE java\n" +
+                                                    "AS 'return \"called\";';");
+             typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
+                                                         typeName,
+                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
+                                                         "RETURNS NULL ON NULL INPUT " +
+                                                         "RETURNS text " +
+                                                         "LANGUAGE java\n" +
+                                                         "AS 'return \"called\";';");
+             values.add(typeDef.referenceValue);
+         }
+ 
+         createTableDDL += ')';
+         createTable(createTableDDL);
+ 
+         insertDML += ") VALUES (1";
+         for (TypesTestDef ignored : typeDefs)
+             insertDML += ", ?";
+         insertDML += ')';
+ 
+         execute(insertDML, values.toArray());
+ 
+         // second row with null values
+         for (int i = 0; i < values.size(); i++)
+             values.set(i, null);
+         execute(insertDML.replace('1', '2'), values.toArray());
+ 
+         // check argument input + return
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
+                        row(new Object[]{ typeDef.referenceValue }));
+         }
+ 
+         // check for CALLED ON NULL INPUT with non-null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
+                        row(new Object[]{ "called" }));
+         }
+ 
+         // check for CALLED ON NULL INPUT with null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
+                        row(new Object[]{ "called" }));
+         }
+ 
+         // check for RETURNS NULL ON NULL INPUT with non-null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
+                        row(new Object[]{ "called" }));
+         }
+ 
+         // check for RETURNS NULL ON NULL INPUT with null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
+                        row(new Object[]{ null }));
+         }
+ 
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenSetType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+         createIndex("CREATE INDEX ON %s (FULL(b))");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<set<int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "set<int>",
+                                              "CREATE FUNCTION %s (values set<int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "set<int>",
+                                       "CREATE FUNCTION %s (values set<int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS set<int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenListType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+         createIndex("CREATE INDEX ON %s (FULL(b))");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<list<int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "list<int>",
+                                              "CREATE FUNCTION %s (values list<int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "list<int>",
+                                       "CREATE FUNCTION %s (values list<int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS list<int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenMapType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+         createIndex("CREATE INDEX ON %s (FULL(b))");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<map<int, int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "map<int, int>",
+                                              "CREATE FUNCTION %s (values map<int, int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "map<int, int>",
+                                       "CREATE FUNCTION %s (values map<int, int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS map<int, int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+         createIndex("CREATE INDEX ON %s (b)");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values.toString();';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<tuple<int, int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "tuple<int, int>",
+                                              "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'return values.toString();';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "tuple<int, int>",
+                                       "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS tuple<int, int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenUDType() throws Throwable
+     {
+         String myType = createType("CREATE TYPE %s (f int)");
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+         createIndex("CREATE INDEX ON %s (b)");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values.toString();';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<" + myType + "> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              myType,
+                                              "CREATE FUNCTION %s (values " + myType + ") " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'return values.toString();';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       myType,
+                                       "CREATE FUNCTION %s (values " + myType + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + myType + " " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
+     }
+ }


[18/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index c52e178,d4d2a10..8a743ea
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@@ -17,44 -17,37 +17,29 @@@
   */
  package org.apache.cassandra.cql3.validation.entities;
  
 +import java.nio.ByteBuffer;
  import java.util.ArrayList;
--import java.util.Arrays;
  import java.util.Date;
  import java.util.List;
--import java.util.Map;
--import java.util.Set;
--import java.util.TreeMap;
--import java.util.TreeSet;
--import java.util.UUID;
- import java.security.AccessControlException;
  
  import org.junit.Assert;
 -import org.junit.BeforeClass;
  import org.junit.Test;
  
- import com.datastax.driver.core.*;
 -import com.datastax.driver.core.Row;
  import com.datastax.driver.core.exceptions.InvalidQueryException;
--import org.apache.cassandra.config.DatabaseDescriptor;
 +import org.apache.cassandra.config.Schema;
- import org.apache.cassandra.cql3.CQL3Type;
  import org.apache.cassandra.cql3.CQLTester;
  import org.apache.cassandra.cql3.QueryProcessor;
  import org.apache.cassandra.cql3.UntypedResultSet;
- import org.apache.cassandra.config.Config;
  import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.cql3.functions.Functions;
  import org.apache.cassandra.cql3.functions.UDFunction;
- import org.apache.cassandra.cql3.functions.UDHelper;
  import org.apache.cassandra.db.marshal.CollectionType;
- import org.apache.cassandra.exceptions.FunctionExecutionException;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
  import org.apache.cassandra.exceptions.InvalidRequestException;
 +import org.apache.cassandra.schema.KeyspaceMetadata;
  import org.apache.cassandra.service.ClientState;
- import org.apache.cassandra.service.ClientWarn;
  import org.apache.cassandra.transport.Event;
  import org.apache.cassandra.transport.Server;
  import org.apache.cassandra.transport.messages.ResultMessage;
 -import org.apache.cassandra.utils.UUIDGen;
 +import org.apache.cassandra.utils.ByteBufferUtil;
- import org.apache.cassandra.utils.UUIDGen;
  
  public class UFTest extends CQLTester
  {
@@@ -1017,320 -724,115 +710,6 @@@
      }
  
      @Test
--    public void testComplexNullValues() throws Throwable
--    {
--        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
--
--        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
--                    "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
--
--        String fList = createFunction(KEYSPACE, "list<double>",
--                                      "CREATE FUNCTION %s( coll list<double> ) " +
--                                      "CALLED ON NULL INPUT " +
--                                      "RETURNS list<double> " +
--                                      "LANGUAGE java\n" +
--                                      "AS $$return coll;$$;");
--        String fSet = createFunction(KEYSPACE, "set<text>",
--                                     "CREATE FUNCTION %s( coll set<text> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS set<text> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return coll;$$;");
--        String fMap = createFunction(KEYSPACE, "map<int, boolean>",
--                                     "CREATE FUNCTION %s( coll map<int, boolean> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS map<int, boolean> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return coll;$$;");
--        String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
--                                     "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS tuple<double, text, int, boolean> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return val;$$;");
--        String fUdt = createFunction(KEYSPACE, type,
--                                     "CREATE FUNCTION %s( val " + type + " ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS " + type + " " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return val;$$;");
--        List<Double> list = Arrays.asList(1d, 2d, 3d);
--        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
--        Map<Integer, Boolean> map = new TreeMap<>();
--        map.put(1, true);
--        map.put(2, false);
--        map.put(3, true);
--        Object t = tuple(1d, "one", 42, false);
--
--        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
--        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
--
--        execute("SELECT " +
--                fList + "(lst), " +
--                fSet + "(st), " +
--                fMap + "(mp), " +
--                fTup + "(tup), " +
--                fUdt + "(udt) FROM %s WHERE key = 1");
--        UntypedResultSet.Row row = execute("SELECT " +
--                                           fList + "(lst) as l, " +
--                                           fSet + "(st) as s, " +
--                                           fMap + "(mp) as m, " +
--                                           fTup + "(tup) as t, " +
--                                           fUdt + "(udt) as u " +
--                                           "FROM %s WHERE key = 1").one();
--        Assert.assertNotNull(row.getBytes("l"));
--        Assert.assertNotNull(row.getBytes("s"));
--        Assert.assertNotNull(row.getBytes("m"));
--        Assert.assertNotNull(row.getBytes("t"));
--        Assert.assertNotNull(row.getBytes("u"));
--        row = execute("SELECT " +
--                      fList + "(lst) as l, " +
--                      fSet + "(st) as s, " +
--                      fMap + "(mp) as m, " +
--                      fTup + "(tup) as t, " +
--                      fUdt + "(udt) as u " +
--                      "FROM %s WHERE key = 2").one();
--        Assert.assertNull(row.getBytes("l"));
--        Assert.assertNull(row.getBytes("s"));
--        Assert.assertNull(row.getBytes("m"));
--        Assert.assertNull(row.getBytes("t"));
--        Assert.assertNull(row.getBytes("u"));
--
-         for (int version : PROTOCOL_VERSIONS)
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
--        {
--            Row r = executeNet(version, "SELECT " +
--                                        fList + "(lst) as l, " +
--                                        fSet + "(st) as s, " +
--                                        fMap + "(mp) as m, " +
--                                        fTup + "(tup) as t, " +
--                                        fUdt + "(udt) as u " +
--                                        "FROM %s WHERE key = 1").one();
--            Assert.assertNotNull(r.getBytesUnsafe("l"));
--            Assert.assertNotNull(r.getBytesUnsafe("s"));
--            Assert.assertNotNull(r.getBytesUnsafe("m"));
--            Assert.assertNotNull(r.getBytesUnsafe("t"));
--            Assert.assertNotNull(r.getBytesUnsafe("u"));
--            r = executeNet(version, "SELECT " +
--                                    fList + "(lst) as l, " +
--                                    fSet + "(st) as s, " +
--                                    fMap + "(mp) as m, " +
--                                    fTup + "(tup) as t, " +
--                                    fUdt + "(udt) as u " +
--                                    "FROM %s WHERE key = 2").one();
--            Assert.assertNull(r.getBytesUnsafe("l"));
--            Assert.assertNull(r.getBytesUnsafe("s"));
--            Assert.assertNull(r.getBytesUnsafe("m"));
--            Assert.assertNull(r.getBytesUnsafe("t"));
--            Assert.assertNull(r.getBytesUnsafe("u"));
-         }
-     }
- 
-     @Test
-     public void testJavaTupleType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
- 
-         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
-                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS tuple<double, text, int, boolean> " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return tup;$$;");
- 
-         Object t = tuple(1d, "foo", 2, true);
- 
-         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
- 
-         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                    row(t));
- 
-         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                    row(t));
-     }
- 
-     @Test
-     public void testJavaTupleTypeCollection() throws Throwable
-     {
-         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
- 
-         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
- 
-         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "CALLED ON NULL INPUT " +
-                 "RETURNS " + tupleTypeDef + ' ' +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup;$$;");
-         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "CALLED ON NULL INPUT " +
-                 "RETURNS double " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       Double.valueOf(tup.getDouble(0));$$;");
-         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS list<double> " +
-                                       "LANGUAGE java\n" +
-                                       "AS $$return " +
-                                       "       tup.getList(1, Double.class);$$;");
-         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "RETURNS NULL ON NULL INPUT " +
-                 "RETURNS set<text> " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup.getSet(2, String.class);$$;");
-         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "RETURNS NULL ON NULL INPUT " +
-                 "RETURNS map<int, boolean> " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup.getMap(3, Integer.class, Boolean.class);$$;");
- 
-         List<Double> list = Arrays.asList(1d, 2d, 3d);
-         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-         Map<Integer, Boolean> map = new TreeMap<>();
-         map.put(1, true);
-         map.put(2, false);
-         map.put(3, true);
- 
-         Object t = tuple(1d, list, set, map);
- 
-         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
- 
-         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                    row(t));
-         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                    row(1d));
-         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                    row(list));
-         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                    row(set));
-         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                    row(map));
- 
-         // same test - but via native protocol
-         // we use protocol V3 here to encode the expected version because the server
-         // always serializes Collections using V3 - see CollectionSerializer's
-         // serialize and deserialize methods.
-         TupleType tType = tupleTypeOf(Server.VERSION_3,
-                                       DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-         TupleValue tup = tType.newValue(1d, list, set, map);
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                           row(tup));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                           row(1d));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                           row(list));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                           row(set));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                           row(map));
-         }
-     }
- 
-     @Test
-     public void testJavaUserTypeWithUse() throws Throwable
-     {
-         String type = createType("CREATE TYPE %s (txt text, i int)");
-         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
-         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
- 
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             executeNet(version, "USE " + KEYSPACE);
- 
-             executeNet(version,
-                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
-                        "RETURNS NULL ON NULL INPUT " +
-                        "RETURNS " + type + " " +
-                        "LANGUAGE java " +
-                        "AS $$return " +
-                        "     udt;$$;");
-             try
-             {
-                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
-                 Assert.assertEquals(1, rowsNet.size());
-                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-                 Assert.assertEquals("one", udtVal.getString("txt"));
-                 Assert.assertEquals(1, udtVal.getInt("i"));
-             }
-             finally
-             {
-                 executeNet(version, "DROP FUNCTION f_use1");
-             }
-         }
-     }
- 
-     @Test
-     public void testJavaUserType() throws Throwable
-     {
-         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
- 
-         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- 
-         String fUdt0 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + " ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS " + type + " " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     udt;$$;");
-         String fUdt1 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + ") " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS text " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     udt.getString(\"txt\");$$;");
-         String fUdt2 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + ") " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS int " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
- 
-         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
- 
-         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
-         Assert.assertEquals(1, rows.size());
-         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                    row("one"));
-         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                    row(1));
- 
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
-             Assert.assertEquals(1, rowsNet.size());
-             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-             Assert.assertEquals("one", udtVal.getString("txt"));
-             Assert.assertEquals(1, udtVal.getInt("i"));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                           row("one"));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                           row(1));
--        }
--    }
--
--    @Test
      public void testUserTypeDrop() throws Throwable
      {
          String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
@@@ -1593,162 -880,140 +757,7 @@@
                               "AS '\"foo bar\";';");
      }
  
 -    private static class TypesTestDef
 -    {
 -        final String udfType;
 -        final String tableType;
 -        final String columnName;
 -        final Object referenceValue;
 -
 -        String fCheckArgAndReturn;
 -
 -        String fCalledOnNull;
 -        String fReturnsNullOnNull;
 -
 -        TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
 -        {
 -            this.udfType = udfType;
 -            this.tableType = tableType;
 -            this.columnName = columnName;
 -            this.referenceValue = referenceValue;
 -        }
 -    }
 -
 -    @Test
 -    public void testTypesWithAndWithoutNulls() throws Throwable
 -    {
 -        // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
 -
 -        String type = createType("CREATE TYPE %s (txt text, i int)");
 -
 -        TypesTestDef[] typeDefs =
 -        {
 -        //                udf type,            table type,                 column, reference value
 -        new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
 -        new TypesTestDef("date", "date", "dt", 12345),
 -        new TypesTestDef("time", "time", "tim", 12345L),
 -        new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
 -        new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
 -        new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
 -        new TypesTestDef("smallint", "smallint", "si", (short) 43),
 -        new TypesTestDef("int", "int", "i", 44),
 -        new TypesTestDef("bigint", "bigint", "b", 45L),
 -        new TypesTestDef("float", "float", "f", 46f),
 -        new TypesTestDef("double", "double", "d", 47d),
 -        new TypesTestDef("boolean", "boolean", "x", true),
 -        new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
 -        new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
 -        //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
 -        new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
 -        };
 -
 -        String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
 -        String insertDML = "INSERT INTO %s (key";
 -        List<Object> values = new ArrayList<>();
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
 -            insertDML += ", " + typeDef.columnName;
 -            String typeName = typeDef.udfType;
 -            typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
 -                                                        typeName,
 -                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                        "CALLED ON NULL INPUT " +
 -                                                        "RETURNS " + typeName + ' ' +
 -                                                        "LANGUAGE java\n" +
 -                                                        "AS 'return val;';");
 -            typeDef.fCalledOnNull = createFunction(KEYSPACE,
 -                                                   typeName,
 -                                                   "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                   "CALLED ON NULL INPUT " +
 -                                                   "RETURNS text " +
 -                                                   "LANGUAGE java\n" +
 -                                                   "AS 'return \"called\";';");
 -            typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
 -                                                        typeName,
 -                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                        "RETURNS NULL ON NULL INPUT " +
 -                                                        "RETURNS text " +
 -                                                        "LANGUAGE java\n" +
 -                                                        "AS 'return \"called\";';");
 -            values.add(typeDef.referenceValue);
 -        }
 -
 -        createTableDDL += ')';
 -        createTable(createTableDDL);
 -
 -        insertDML += ") VALUES (1";
 -        for (TypesTestDef ignored : typeDefs)
 -            insertDML += ", ?";
 -        insertDML += ')';
 -
 -        execute(insertDML, values.toArray());
 -
 -        // second row with null values
 -        for (int i = 0; i < values.size(); i++)
 -            values.set(i, null);
 -        execute(insertDML.replace('1', '2'), values.toArray());
 -
 -        // check argument input + return
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ typeDef.referenceValue }));
 -        }
 -
 -        // check for CALLED ON NULL INPUT with non-null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for CALLED ON NULL INPUT with null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for RETURNS NULL ON NULL INPUT with non-null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for RETURNS NULL ON NULL INPUT with null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
 -                       row(new Object[]{ null }));
 -        }
 -
 -    }
 -
      @Test
-     public void testJavascriptCompileFailure() throws Throwable
-     {
-         assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE javascript\n" +
-                              "AS 'foo bar';");
-     }
- 
-     @Test
-     public void testScriptInvalidLanguage() throws Throwable
-     {
-         assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE artificial_intelligence\n" +
-                              "AS 'question for 42?';");
-     }
- 
-     static class TypesTestDef
-     {
-         final String udfType;
-         final String tableType;
-         final String columnName;
-         final Object referenceValue;
- 
-         String fCheckArgAndReturn;
- 
-         String fCalledOnNull;
-         String fReturnsNullOnNull;
- 
-         TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
-         {
-             this.udfType = udfType;
-             this.tableType = tableType;
-             this.columnName = columnName;
-             this.referenceValue = referenceValue;
-         }
-     }
- 
-     @Test
-     public void testTypesWithAndWithoutNulls() throws Throwable
-     {
-         // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
- 
-         String type = createType("CREATE TYPE %s (txt text, i int)");
- 
-         TypesTestDef[] typeDefs =
-         {
-         //                udf type,            table type,                 column, reference value
-         new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
-         new TypesTestDef("date", "date", "dt", 12345),
-         new TypesTestDef("time", "time", "tim", 12345L),
-         new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
-         new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
-         new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
-         new TypesTestDef("smallint", "smallint", "si", (short) 43),
-         new TypesTestDef("int", "int", "i", 44),
-         new TypesTestDef("bigint", "bigint", "b", 45L),
-         new TypesTestDef("float", "float", "f", 46f),
-         new TypesTestDef("double", "double", "d", 47d),
-         new TypesTestDef("boolean", "boolean", "x", true),
-         new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
-         new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
-         //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
-         new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
-         };
- 
-         String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
-         String insertDML = "INSERT INTO %s (key";
-         List<Object> values = new ArrayList<>();
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
-             insertDML += ", " + typeDef.columnName;
-             String typeName = typeDef.udfType;
-             typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
-                                                         typeName,
-                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                         "CALLED ON NULL INPUT " +
-                                                         "RETURNS " + typeName + ' ' +
-                                                         "LANGUAGE java\n" +
-                                                         "AS 'return val;';");
-             typeDef.fCalledOnNull = createFunction(KEYSPACE,
-                                                    typeName,
-                                                    "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                    "CALLED ON NULL INPUT " +
-                                                    "RETURNS text " +
-                                                    "LANGUAGE java\n" +
-                                                    "AS 'return \"called\";';");
-             typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
-                                                         typeName,
-                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                         "RETURNS NULL ON NULL INPUT " +
-                                                         "RETURNS text " +
-                                                         "LANGUAGE java\n" +
-                                                         "AS 'return \"called\";';");
-             values.add(typeDef.referenceValue);
-         }
- 
-         createTableDDL += ')';
-         createTable(createTableDDL);
- 
-         insertDML += ") VALUES (1";
-         for (TypesTestDef ignored : typeDefs)
-             insertDML += ", ?";
-         insertDML += ')';
- 
-         execute(insertDML, values.toArray());
- 
-         // second row with null values
-         for (int i = 0; i < values.size(); i++)
-             values.set(i, null);
-         execute(insertDML.replace('1', '2'), values.toArray());
- 
-         // check argument input + return
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ typeDef.referenceValue }));
-         }
- 
-         // check for CALLED ON NULL INPUT with non-null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for CALLED ON NULL INPUT with null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for RETURNS NULL ON NULL INPUT with non-null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for RETURNS NULL ON NULL INPUT with null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
-                        row(new Object[]{ null }));
-         }
- 
-     }
- 
-     @Test
      public void testReplaceAllowNulls() throws Throwable
      {
          String fNulls = createFunction(KEYSPACE,
@@@ -1851,638 -1108,4 +860,112 @@@
              }
          }
      }
-     @Test
-     public void testFunctionWithFrozenSetType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<set<int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "set<int>",
-                                              "CREATE FUNCTION %s (values set<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "set<int>",
-                                              "CREATE FUNCTION %s (values set<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS set<int> " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenListType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<list<int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "list<int>",
-                                              "CREATE FUNCTION %s (values list<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "list<int>",
-                                       "CREATE FUNCTION %s (values list<int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS list<int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenMapType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<map<int, int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "map<int, int>",
-                                              "CREATE FUNCTION %s (values map<int, int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "map<int, int>",
-                                       "CREATE FUNCTION %s (values map<int, int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS map<int, int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenTupleType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
-         createIndex("CREATE INDEX ON %s (b)");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values.toString();';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<tuple<int, int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "tuple<int, int>",
-                                              "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values.toString();';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "tuple<int, int>",
-                                       "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS tuple<int, int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenUDType() throws Throwable
-     {
-         String myType = createType("CREATE TYPE %s (f int)");
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-         createIndex("CREATE INDEX ON %s (b)");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values.toString();';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<" + myType + "> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              myType,
-                                              "CREATE FUNCTION %s (values " + myType + ") " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values.toString();';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
- 
-         functionName = createFunction(KEYSPACE,
-                                       myType,
-                                       "CREATE FUNCTION %s (values " + myType + ") " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS " + myType + " " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
-     }
 +
 +    @Test
 +    public void testEmptyString() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
 +        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
 +
 +        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return \"\";'");
 +
 +        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return \"\";'");
 +
 +        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return ByteBuffer.allocate(0);'");
 +
 +        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return ByteBuffer.allocate(0);'");
 +
 +        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return 0;'");
 +
 +        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return 0;'");
 +
 +        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
 +        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +    }
- 
-     @Test
-     public void testAllNativeTypes() throws Throwable
-     {
-         StringBuilder sig = new StringBuilder();
-         StringBuilder args = new StringBuilder();
-         for (CQL3Type.Native type : CQL3Type.Native.values())
-         {
-             if (type == CQL3Type.Native.EMPTY)
-                 continue;
- 
-             if (sig.length() > 0)
-                 sig.append(',');
-             sig.append(type.toString());
- 
-             if (args.length() > 0)
-                 args.append(',');
-             args.append("arg").append(type.toString()).append(' ').append(type.toString());
-         }
-         createFunction(KEYSPACE, sig.toString(),
-                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
-                        "RETURNS NULL ON NULL INPUT " +
-                        "RETURNS int " +
-                        "LANGUAGE JAVA\n" +
-                        "AS 'return 0;'");
- 
-         for (CQL3Type.Native type : CQL3Type.Native.values())
-         {
-             if (type == CQL3Type.Native.EMPTY)
-                 continue;
- 
-             createFunction(KEYSPACE_PER_TEST, type.toString(),
-                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
-                            "RETURNS NULL ON NULL INPUT " +
-                            "RETURNS int " +
-                            "LANGUAGE JAVA\n" +
-                            "AS 'return 0;'");
-         }
-     }
- 
-     @Test
-     public void testSecurityPermissions() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, dval double)");
-         execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
- 
-         // Java UDFs
- 
-         try
-         {
-             String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                           "RETURNS NULL ON NULL INPUT " +
-                                           "RETURNS double " +
-                                           "LANGUAGE JAVA\n" +
-                                           "AS 'System.getProperty(\"foo.bar.baz\"); return 0d;';");
-             execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-             Assert.fail();
-         }
-         catch (FunctionExecutionException e)
-         {
-             assertAccessControlException("System.getProperty(\"foo.bar.baz\"); return 0d;", e);
-         }
- 
-         String[][] typesAndSources =
-         {
-         {"",                        "try { Class.forName(\"" + UDHelper.class.getName() + "\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
-         {"sun.misc.Unsafe",         "sun.misc.Unsafe.getUnsafe(); return 0d;"},
-         {"",                        "try { Class.forName(\"sun.misc.Unsafe\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
-         {"java.nio.file.FileSystems", "try {" +
-                                     "     java.nio.file.FileSystems.getDefault(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.nio.channels.FileChannel", "try {" +
-                                     "     java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")).close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.nio.channels.SocketChannel", "try {" +
-                                     "     java.nio.channels.SocketChannel.open().close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.io.FileInputStream", "try {" +
-                                     "     new java.io.FileInputStream(\"./foobar\").close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.lang.Runtime",       "try {" +
-                                     "     java.lang.Runtime.getRuntime(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"org.apache.cassandra.service.StorageService",
-                                     "try {" +
-                                     "     org.apache.cassandra.service.StorageService v = org.apache.cassandra.service.StorageService.instance; v.isShutdown(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.net.ServerSocket",   "try {" +
-                                     "     new java.net.ServerSocket().bind(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.io.FileOutputStream","try {" +
-                                     "     new java.io.FileOutputStream(\".foo\"); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.lang.Runtime",       "try {" +
-                                     "     java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'}
-         };
- 
-         for (String[] typeAndSource : typesAndSources)
-         {
-             assertInvalidMessage(typeAndSource[0] + " cannot be resolved",
-                                  "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".invalid_class_access(val double) " +
-                                  "RETURNS NULL ON NULL INPUT " +
-                                  "RETURNS double " +
-                                  "LANGUAGE JAVA\n" +
-                                  "AS '" + typeAndSource[1] + "';");
-         }
- 
-         // JavaScript UDFs
- 
-         try
-         {
-             String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                           "RETURNS NULL ON NULL INPUT " +
-                                           "RETURNS double " +
-                                           "LANGUAGE javascript\n" +
-                                           "AS 'org.apache.cassandra.service.StorageService.instance.isShutdown(); 0;';");
-             execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-             Assert.fail("Javascript security check failed");
-         }
-         catch (FunctionExecutionException e)
-         {
-             assertAccessControlException("", e);
-         }
- 
-         String[] javascript =
-         {
-         "java.lang.management.ManagmentFactory.getThreadMXBean(); 0;",
-         "new java.io.FileInputStream(\"/tmp/foo\"); 0;",
-         "new java.io.FileOutputStream(\"/tmp/foo\"); 0;",
-         "java.nio.file.FileSystems.getDefault().createFileExclusively(\"./foo_bar_baz\"); 0;",
-         "java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")); 0;",
-         "java.nio.channels.SocketChannel.open(); 0;",
-         "new java.net.ServerSocket().bind(null); 0;",
-         "var thread = new java.lang.Thread(); thread.start(); 0;",
-         "java.lang.System.getProperty(\"foo.bar.baz\"); 0;",
-         "java.lang.Class.forName(\"java.lang.System\"); 0;",
-         "java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); 0;",
-         "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
-         "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
-         // TODO these (ugly) calls are still possible - these can consume CPU (as one could do with an evil loop, too)
- //        "java.lang.Runtime.getRuntime().traceMethodCalls(true); 0;",
- //        "java.lang.Runtime.getRuntime().gc(); 0;",
- //        "java.lang.Runtime.getRuntime(); 0;",
-         };
- 
-         for (String script : javascript)
-         {
-             try
-             {
-                 String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                               "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                               "RETURNS NULL ON NULL INPUT " +
-                                               "RETURNS double " +
-                                               "LANGUAGE javascript\n" +
-                                               "AS '" + script + "';");
-                 execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-                 Assert.fail("Javascript security check failed: " + script);
-             }
-             catch (FunctionExecutionException e)
-             {
-                 assertAccessControlException(script, e);
-             }
-         }
-     }
- 
-     private static void assertAccessControlException(String script, FunctionExecutionException e)
-     {
-         for (Throwable t = e; t != null && t != t.getCause(); t = t.getCause())
-             if (t instanceof AccessControlException)
-                 return;
-         Assert.fail("no AccessControlException for " + script + " (got " + e + ')');
-     }
- 
-     @Test
-     public void testAmokUDF() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, dval double)");
-         execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
- 
-         long udfWarnTimeout = DatabaseDescriptor.getUserDefinedFunctionWarnTimeout();
-         long udfFailTimeout = DatabaseDescriptor.getUserDefinedFunctionFailTimeout();
-         int maxTries = 5;
-         for (int i = 1; i <= maxTries; i++)
-         {
-             try
-             {
-                 // short timeout
-                 DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(10);
-                 DatabaseDescriptor.setUserDefinedFunctionFailTimeout(250);
-                 // don't kill the unit test... - default policy is "die"
-                 DatabaseDescriptor.setUserFunctionTimeoutPolicy(Config.UserFunctionTimeoutPolicy.ignore);
- 
-                 ClientWarn.instance.captureWarnings();
-                 String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                               "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                               "RETURNS NULL ON NULL INPUT " +
-                                               "RETURNS double " +
-                                               "LANGUAGE JAVA\n" +
-                                               "AS 'long t=System.currentTimeMillis()+110; while (t>System.currentTimeMillis()) { }; return 0d;'");
-                 execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-                 List<String> warnings = ClientWarn.instance.getWarnings();
-                 Assert.assertNotNull(warnings);
-                 Assert.assertFalse(warnings.isEmpty());
-                 ClientWarn.instance.resetWarnings();
- 
-                 // Java UDF
- 
-                 fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                        "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                        "RETURNS NULL ON NULL INPUT " +
-                                        "RETURNS double " +
-                                        "LANGUAGE JAVA\n" +
-                                        "AS 'long t=System.currentTimeMillis()+500; while (t>System.currentTimeMillis()) { }; return 0d;';");
-                 assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
- 
-                 // Javascript UDF
- 
-                 fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                        "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                        "RETURNS NULL ON NULL INPUT " +
-                                        "RETURNS double " +
-                                        "LANGUAGE JAVASCRIPT\n" +
-                                        "AS 'var t=java.lang.System.currentTimeMillis()+500; while (t>java.lang.System.currentTimeMillis()) { }; 0;';");
-                 assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
- 
-                 return;
-             }
-             catch (Error | RuntimeException e)
-             {
-                 if (i == maxTries)
-                     throw e;
-             }
-             finally
-             {
-                 // reset to defaults
-                 DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(udfWarnTimeout);
-                 DatabaseDescriptor.setUserDefinedFunctionFailTimeout(udfFailTimeout);
-             }
-         }
-     }
  }


[20/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
Merge branch 'cassandra-2.2' into cassandra-3.0


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3aefe356
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3aefe356
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3aefe356

Branch: refs/heads/trunk
Commit: 3aefe356545bcc2f5c4453e0d9d704bef339a008
Parents: 95d0b67 0b97c5d
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:08:35 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:08:35 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    |  797 +++++++++
 .../validation/entities/UFPureScriptTest.java   |  406 -----
 .../cql3/validation/entities/UFScriptTest.java  |  428 +++++
 .../validation/entities/UFSecurityTest.java     |  258 +++
 .../cql3/validation/entities/UFTest.java        | 1519 +-----------------
 .../cql3/validation/entities/UFTypesTest.java   |  549 +++++++
 6 files changed, 2033 insertions(+), 1924 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
index 0000000,caef808..15c8e18
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@@ -1,0 -1,1177 +1,797 @@@
+ /*
+  * 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.Arrays;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ 
+ import org.junit.Assert;
 -import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.DataType;
+ import com.datastax.driver.core.Row;
+ import com.datastax.driver.core.TupleType;
+ import com.datastax.driver.core.TupleValue;
+ import com.datastax.driver.core.UDTValue;
 -import org.apache.cassandra.config.DatabaseDescriptor;
++import org.apache.cassandra.config.Schema;
+ import org.apache.cassandra.cql3.CQL3Type;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.cql3.functions.Functions;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
+ import org.apache.cassandra.transport.Server;
 -import org.apache.cassandra.utils.ByteBufferUtil;
+ 
+ public class UFJavaTest extends CQLTester
+ {
 -    @BeforeClass
 -    public static void setUp()
 -    {
 -        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
 -    }
 -
 -
+     @Test
+     public void testJavaFunctionNoParameters() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = "\n  return 1L;\n";
+ 
+         String fName = createFunction(KEYSPACE, "",
+                                       "CREATE OR REPLACE FUNCTION %s() " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" +functionBody + "';");
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            KEYSPACE, parseFunctionName(fName).name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                    row(1, 1d, 1L),
+                    row(2, 2d, 1L),
+                    row(3, 3d, 1L)
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidBodies() throws Throwable
+     {
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+         }
+ 
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz;" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+         }
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidReturn() throws Throwable
+     {
+         assertInvalidMessage("system keyspace is not user-modifiable",
+                              "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE JAVA\n" +
+                              "AS 'return 1L;';");
+     }
+ 
+     @Test
+     public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val bigint)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return Double.valueOf(val);';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+         assertInvalidMessage("val cannot be passed as argument 0 of function",
+                              "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionCounter() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val counter)");
+ 
+         String fName = createFunction(KEYSPACE, "counter",
+                                       "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return val + 1;';");
+ 
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1L, 2L));
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+         execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 4L, 5L));
+         execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+     }
+ 
+     @Test
+     public void testJavaKeyspaceFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin( val );\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaRuntimeException() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  throw new RuntimeException(\"oh no!\");\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+ 
+         // function throws a RuntimeException which is wrapped by FunctionExecutionException
+         assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaDollarQuotedFunction() throws Throwable
+     {
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (input == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return \"'\"+Math.sin(input)+'\\\'';\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE FUNCTION %s( input double ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" + functionBody + "$$;");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+     }
+ 
+     @Test
+     public void testJavaSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return lst;$$;");
+         String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                      "CREATE FUNCTION %s( st set<text> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return st;$$;");
+         String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return mp;$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         // same test - but via native protocol
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavaTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavaTupleTypeCollection() throws Throwable
+     {
+         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+ 
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+ 
+         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + tupleTypeDef + ' ' +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup;$$;");
+         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       Double.valueOf(tup.getDouble(0));$$;");
+         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getList(1, Double.class);$$;");
+         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getSet(2, String.class);$$;");
+         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         Object t = tuple(1d, list, set, map);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                    row(1d));
+         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                    row(list));
+         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                    row(set));
+         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                    row(map));
+ 
 -        TupleType tType = TupleType.of(DataType.cdouble(),
 -                                       DataType.list(DataType.cdouble()),
 -                                       DataType.set(DataType.text()),
 -                                       DataType.map(DataType.cint(), DataType.cboolean()));
++        // same test - but via native protocol
++        // we use protocol V3 here to encode the expected version because the server
++        // always serializes Collections using V3 - see CollectionSerializer's
++        // serialize and deserialize methods.
++        TupleType tType = tupleTypeOf(Server.VERSION_3,
++                                      DataType.cdouble(),
++                                      DataType.list(DataType.cdouble()),
++                                      DataType.set(DataType.text()),
++                                      DataType.map(DataType.cint(), DataType.cboolean()));
+         TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                           row(tup));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                           row(1d));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                           row(list));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                           row(set));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                           row(map));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeWithUse() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             executeNet(version, "USE " + KEYSPACE);
+ 
+             executeNet(version,
+                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS " + type + " " +
+                        "LANGUAGE java " +
+                        "AS $$return " +
+                        "     udt;$$;");
+             try
+             {
+                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                 Assert.assertEquals(1, rowsNet.size());
+                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                 Assert.assertEquals("one", udtVal.getString("txt"));
+                 Assert.assertEquals(1, udtVal.getInt("i"));
+             }
+             finally
+             {
+                 executeNet(version, "DROP FUNCTION f_use1");
+             }
+         }
+     }
+ 
+     @Test
+     public void testJavaUserType() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt0 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + " " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt;$$;");
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+             Assert.assertEquals(1, rowsNet.size());
+             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+             Assert.assertEquals("one", udtVal.getString("txt"));
+             Assert.assertEquals(1, udtVal.getInt("i"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                           row("one"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                           row(1));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeRenameField() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return udt.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+ 
+         execute("ALTER TYPE " + type + " RENAME txt TO str");
+ 
+         assertInvalidMessage("txt is not a field defined in this UDT",
+                              "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+ 
+         execute("ALTER TYPE " + type + " RENAME str TO txt");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+     }
+ 
+     @Test
+     public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName1replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + ") " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS text " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt.getString(\"txt\");$$;");
+         String fName2replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS int " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS double " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS " + type + " " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt;$$;");
+ 
+         String fName1noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS text " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt.getString(\"txt\");$$;");
+         String fName2noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS int " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS double " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS " + type + " " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt;$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
+         // add field
+ 
+         execute("ALTER TYPE " + type + " ADD added double");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+ 
+         // note: type references of functions remain at the state _before_ the type mutation
+         // means we need to recreate the functions
+ 
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt.getString(\"txt\");$$;",
+                               fName1replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName1replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS int " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                               fName2replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName2replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS double " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                               fName3replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName3replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS %s " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt;$$;",
+                               fName4replace, type, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName4replace)).size());
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         // un-replaced functions will work since the user type has changed
+         // and the UDF has exchanged the user type reference
+ 
+         assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         execute("DROP FUNCTION " + fName1replace);
+         execute("DROP FUNCTION " + fName2replace);
+         execute("DROP FUNCTION " + fName3replace);
+         execute("DROP FUNCTION " + fName4replace);
+         execute("DROP FUNCTION " + fName1noReplace);
+         execute("DROP FUNCTION " + fName2noReplace);
+         execute("DROP FUNCTION " + fName3noReplace);
+         execute("DROP FUNCTION " + fName4noReplace);
+     }
+ 
+     @Test
+     public void testJavaUTCollections() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row("three", "one", "two"));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
 -    public void testFunctionWithFrozenSetType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<set<int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "set<int>",
 -                                             "CREATE FUNCTION %s (values set<int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "set<int>",
 -                                      "CREATE FUNCTION %s (values set<int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS set<int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenListType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<list<int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "list<int>",
 -                                             "CREATE FUNCTION %s (values list<int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "list<int>",
 -                                      "CREATE FUNCTION %s (values list<int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS list<int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenMapType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<map<int, int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "map<int, int>",
 -                                             "CREATE FUNCTION %s (values map<int, int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "map<int, int>",
 -                                      "CREATE FUNCTION %s (values map<int, int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS map<int, int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenTupleType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
 -        createIndex("CREATE INDEX ON %s (b)");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS text " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values.toString();';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<tuple<int, int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "tuple<int, int>",
 -                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS text " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'return values.toString();';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, "(null, null)"),
 -                   row(1, "(1, 2)"),
 -                   row(2, "(4, 5)"),
 -                   row(3, "(7, 8)"));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "tuple<int, int>",
 -                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS tuple<int, int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenUDType() throws Throwable
 -    {
 -        String myType = createType("CREATE TYPE %s (f int)");
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
 -        createIndex("CREATE INDEX ON %s (b)");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS text " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values.toString();';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<" + myType + "> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             myType,
 -                                             "CREATE FUNCTION %s (values " + myType + ") " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS text " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'return values.toString();';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, "{f:0}"),
 -                   row(1, "{f:1}"),
 -                   row(2, "{f:4}"),
 -                   row(3, "{f:7}"));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      myType,
 -                                      "CREATE FUNCTION %s (values " + myType + ") " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS " + myType + " " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
 -    }
 -
 -    @Test
 -    public void testEmptyString() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
 -        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
 -
 -        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return \"\";'");
 -
 -        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return \"\";'");
 -
 -        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return ByteBuffer.allocate(0);'");
 -
 -        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return ByteBuffer.allocate(0);'");
 -
 -        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return 0;'");
 -
 -        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return 0;'");
 -
 -        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
 -        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
 -        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
 -        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
 -    }
 -
 -    @Test
+     public void testAllNativeTypes() throws Throwable
+     {
+         StringBuilder sig = new StringBuilder();
+         StringBuilder args = new StringBuilder();
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
++            if (type == CQL3Type.Native.EMPTY)
++                continue;
++
+             if (sig.length() > 0)
+                 sig.append(',');
+             sig.append(type.toString());
+ 
+             if (args.length() > 0)
+                 args.append(',');
+             args.append("arg").append(type.toString()).append(' ').append(type.toString());
+         }
+         createFunction(KEYSPACE, sig.toString(),
+                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS int " +
+                        "LANGUAGE JAVA\n" +
+                        "AS 'return 0;'");
+ 
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
++            if (type == CQL3Type.Native.EMPTY)
++                continue;
++
+             createFunction(KEYSPACE_PER_TEST, type.toString(),
+                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                            "RETURNS NULL ON NULL INPUT " +
+                            "RETURNS int " +
+                            "LANGUAGE JAVA\n" +
+                            "AS 'return 0;'");
+         }
+     }
+ }


[25/25] cassandra git commit: Merge branch 'cassandra-3.X' into trunk

Posted by sn...@apache.org.
Merge branch 'cassandra-3.X' into trunk


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/d2a92e4b
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/d2a92e4b
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/d2a92e4b

Branch: refs/heads/trunk
Commit: d2a92e4b154cf4d2cb87a8731e6101031fba78c2
Parents: 8253912 d7b6b7a
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:24:08 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:24:08 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    |  798 ++++++++
 .../validation/entities/UFPureScriptTest.java   |  407 ----
 .../cql3/validation/entities/UFScriptTest.java  |  429 +++++
 .../validation/entities/UFSecurityTest.java     |  258 +++
 .../cql3/validation/entities/UFTest.java        | 1739 +-----------------
 .../cql3/validation/entities/UFTypesTest.java   |  550 ++++++
 6 files changed, 2036 insertions(+), 2145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/d2a92e4b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
index 0000000,4d46b8b..a7c09b1
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@@ -1,0 -1,797 +1,798 @@@
+ /*
+  * 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.util.Arrays;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ 
+ import org.junit.Assert;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.DataType;
+ import com.datastax.driver.core.Row;
+ import com.datastax.driver.core.TupleType;
+ import com.datastax.driver.core.TupleValue;
+ import com.datastax.driver.core.UDTValue;
+ import org.apache.cassandra.config.Schema;
+ import org.apache.cassandra.cql3.CQL3Type;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
+ import org.apache.cassandra.transport.ProtocolVersion;
++import org.apache.cassandra.transport.Server;
+ 
+ public class UFJavaTest extends CQLTester
+ {
+     @Test
+     public void testJavaFunctionNoParameters() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = "\n  return 1L;\n";
+ 
+         String fName = createFunction(KEYSPACE, "",
+                                       "CREATE OR REPLACE FUNCTION %s() " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" +functionBody + "';");
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            KEYSPACE, parseFunctionName(fName).name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                    row(1, 1d, 1L),
+                    row(2, 2d, 1L),
+                    row(3, 3d, 1L)
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidBodies() throws Throwable
+     {
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+         }
+ 
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz;" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+         }
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidReturn() throws Throwable
+     {
+         assertInvalidMessage("system keyspace is not user-modifiable",
+                              "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE JAVA\n" +
+                              "AS 'return 1L;';");
+     }
+ 
+     @Test
+     public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val bigint)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return Double.valueOf(val);';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+         assertInvalidMessage("val cannot be passed as argument 0 of function",
+                              "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionCounter() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val counter)");
+ 
+         String fName = createFunction(KEYSPACE, "counter",
+                                       "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return val + 1;';");
+ 
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1L, 2L));
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+         execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 4L, 5L));
+         execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+     }
+ 
+     @Test
+     public void testJavaKeyspaceFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin( val );\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaRuntimeException() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  throw new RuntimeException(\"oh no!\");\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+ 
+         // function throws a RuntimeException which is wrapped by FunctionExecutionException
+         assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaDollarQuotedFunction() throws Throwable
+     {
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (input == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return \"'\"+Math.sin(input)+'\\\'';\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE FUNCTION %s( input double ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" + functionBody + "$$;");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+     }
+ 
+     @Test
+     public void testJavaSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return lst;$$;");
+         String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                      "CREATE FUNCTION %s( st set<text> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return st;$$;");
+         String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return mp;$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         // same test - but via native protocol
+         for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavaTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavaTupleTypeCollection() throws Throwable
+     {
+         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+ 
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+ 
+         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + tupleTypeDef + ' ' +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup;$$;");
+         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       Double.valueOf(tup.getDouble(0));$$;");
+         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getList(1, Double.class);$$;");
+         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getSet(2, String.class);$$;");
+         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         Object t = tuple(1d, list, set, map);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                    row(1d));
+         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                    row(list));
+         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                    row(set));
+         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                    row(map));
+ 
+         // same test - but via native protocol
+         // we use protocol V3 here to encode the expected version because the server
+         // always serializes Collections using V3 - see CollectionSerializer's
+         // serialize and deserialize methods.
+         TupleType tType = tupleTypeOf(ProtocolVersion.V3,
+                                       DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+         TupleValue tup = tType.newValue(1d, list, set, map);
+         for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                           row(tup));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                           row(1d));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                           row(list));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                           row(set));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                           row(map));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeWithUse() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             executeNet(version, "USE " + KEYSPACE);
+ 
+             executeNet(version,
+                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS " + type + " " +
+                        "LANGUAGE java " +
+                        "AS $$return " +
+                        "     udt;$$;");
+             try
+             {
+                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                 Assert.assertEquals(1, rowsNet.size());
+                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                 Assert.assertEquals("one", udtVal.getString("txt"));
+                 Assert.assertEquals(1, udtVal.getInt("i"));
+             }
+             finally
+             {
+                 executeNet(version, "DROP FUNCTION f_use1");
+             }
+         }
+     }
+ 
+     @Test
+     public void testJavaUserType() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt0 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + " " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt;$$;");
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
+         for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+             Assert.assertEquals(1, rowsNet.size());
+             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+             Assert.assertEquals("one", udtVal.getString("txt"));
+             Assert.assertEquals(1, udtVal.getInt("i"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                           row("one"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                           row(1));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeRenameField() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return udt.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+ 
+         execute("ALTER TYPE " + type + " RENAME txt TO str");
+ 
+         assertInvalidMessage("txt is not a field defined in this UDT",
+                              "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+ 
+         execute("ALTER TYPE " + type + " RENAME str TO txt");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+     }
+ 
+     @Test
+     public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName1replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + ") " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS text " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt.getString(\"txt\");$$;");
+         String fName2replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS int " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS double " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS " + type + " " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt;$$;");
+ 
+         String fName1noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS text " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt.getString(\"txt\");$$;");
+         String fName2noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS int " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS double " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS " + type + " " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt;$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
+         // add field
+ 
+         execute("ALTER TYPE " + type + " ADD added double");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+ 
+         // note: type references of functions remain at the state _before_ the type mutation
+         // means we need to recreate the functions
+ 
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt.getString(\"txt\");$$;",
+                               fName1replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName1replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS int " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                               fName2replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName2replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS double " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                               fName3replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName3replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS %s " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt;$$;",
+                               fName4replace, type, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName4replace)).size());
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         // un-replaced functions will work since the user type has changed
+         // and the UDF has exchanged the user type reference
+ 
+         assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         execute("DROP FUNCTION " + fName1replace);
+         execute("DROP FUNCTION " + fName2replace);
+         execute("DROP FUNCTION " + fName3replace);
+         execute("DROP FUNCTION " + fName4replace);
+         execute("DROP FUNCTION " + fName1noReplace);
+         execute("DROP FUNCTION " + fName2noReplace);
+         execute("DROP FUNCTION " + fName3noReplace);
+         execute("DROP FUNCTION " + fName4noReplace);
+     }
+ 
+     @Test
+     public void testJavaUTCollections() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row("three", "one", "two"));
+ 
+         for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testAllNativeTypes() throws Throwable
+     {
+         StringBuilder sig = new StringBuilder();
+         StringBuilder args = new StringBuilder();
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
+             if (type == CQL3Type.Native.EMPTY)
+                 continue;
+ 
+             if (sig.length() > 0)
+                 sig.append(',');
+             sig.append(type.toString());
+ 
+             if (args.length() > 0)
+                 args.append(',');
+             args.append("arg").append(type.toString()).append(' ').append(type.toString());
+         }
+         createFunction(KEYSPACE, sig.toString(),
+                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS int " +
+                        "LANGUAGE JAVA\n" +
+                        "AS 'return 0;'");
+ 
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
+             if (type == CQL3Type.Native.EMPTY)
+                 continue;
+ 
+             createFunction(KEYSPACE_PER_TEST, type.toString(),
+                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                            "RETURNS NULL ON NULL INPUT " +
+                            "RETURNS int " +
+                            "LANGUAGE JAVA\n" +
+                            "AS 'return 0;'");
+         }
+     }
+ }


[14/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index c52e178,d4d2a10..8a743ea
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@@ -17,44 -17,37 +17,29 @@@
   */
  package org.apache.cassandra.cql3.validation.entities;
  
 +import java.nio.ByteBuffer;
  import java.util.ArrayList;
--import java.util.Arrays;
  import java.util.Date;
  import java.util.List;
--import java.util.Map;
--import java.util.Set;
--import java.util.TreeMap;
--import java.util.TreeSet;
--import java.util.UUID;
- import java.security.AccessControlException;
  
  import org.junit.Assert;
 -import org.junit.BeforeClass;
  import org.junit.Test;
  
- import com.datastax.driver.core.*;
 -import com.datastax.driver.core.Row;
  import com.datastax.driver.core.exceptions.InvalidQueryException;
--import org.apache.cassandra.config.DatabaseDescriptor;
 +import org.apache.cassandra.config.Schema;
- import org.apache.cassandra.cql3.CQL3Type;
  import org.apache.cassandra.cql3.CQLTester;
  import org.apache.cassandra.cql3.QueryProcessor;
  import org.apache.cassandra.cql3.UntypedResultSet;
- import org.apache.cassandra.config.Config;
  import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.cql3.functions.Functions;
  import org.apache.cassandra.cql3.functions.UDFunction;
- import org.apache.cassandra.cql3.functions.UDHelper;
  import org.apache.cassandra.db.marshal.CollectionType;
- import org.apache.cassandra.exceptions.FunctionExecutionException;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
  import org.apache.cassandra.exceptions.InvalidRequestException;
 +import org.apache.cassandra.schema.KeyspaceMetadata;
  import org.apache.cassandra.service.ClientState;
- import org.apache.cassandra.service.ClientWarn;
  import org.apache.cassandra.transport.Event;
  import org.apache.cassandra.transport.Server;
  import org.apache.cassandra.transport.messages.ResultMessage;
 -import org.apache.cassandra.utils.UUIDGen;
 +import org.apache.cassandra.utils.ByteBufferUtil;
- import org.apache.cassandra.utils.UUIDGen;
  
  public class UFTest extends CQLTester
  {
@@@ -1017,320 -724,115 +710,6 @@@
      }
  
      @Test
--    public void testComplexNullValues() throws Throwable
--    {
--        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
--
--        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
--                    "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
--
--        String fList = createFunction(KEYSPACE, "list<double>",
--                                      "CREATE FUNCTION %s( coll list<double> ) " +
--                                      "CALLED ON NULL INPUT " +
--                                      "RETURNS list<double> " +
--                                      "LANGUAGE java\n" +
--                                      "AS $$return coll;$$;");
--        String fSet = createFunction(KEYSPACE, "set<text>",
--                                     "CREATE FUNCTION %s( coll set<text> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS set<text> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return coll;$$;");
--        String fMap = createFunction(KEYSPACE, "map<int, boolean>",
--                                     "CREATE FUNCTION %s( coll map<int, boolean> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS map<int, boolean> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return coll;$$;");
--        String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
--                                     "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS tuple<double, text, int, boolean> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return val;$$;");
--        String fUdt = createFunction(KEYSPACE, type,
--                                     "CREATE FUNCTION %s( val " + type + " ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS " + type + " " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return val;$$;");
--        List<Double> list = Arrays.asList(1d, 2d, 3d);
--        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
--        Map<Integer, Boolean> map = new TreeMap<>();
--        map.put(1, true);
--        map.put(2, false);
--        map.put(3, true);
--        Object t = tuple(1d, "one", 42, false);
--
--        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
--        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
--
--        execute("SELECT " +
--                fList + "(lst), " +
--                fSet + "(st), " +
--                fMap + "(mp), " +
--                fTup + "(tup), " +
--                fUdt + "(udt) FROM %s WHERE key = 1");
--        UntypedResultSet.Row row = execute("SELECT " +
--                                           fList + "(lst) as l, " +
--                                           fSet + "(st) as s, " +
--                                           fMap + "(mp) as m, " +
--                                           fTup + "(tup) as t, " +
--                                           fUdt + "(udt) as u " +
--                                           "FROM %s WHERE key = 1").one();
--        Assert.assertNotNull(row.getBytes("l"));
--        Assert.assertNotNull(row.getBytes("s"));
--        Assert.assertNotNull(row.getBytes("m"));
--        Assert.assertNotNull(row.getBytes("t"));
--        Assert.assertNotNull(row.getBytes("u"));
--        row = execute("SELECT " +
--                      fList + "(lst) as l, " +
--                      fSet + "(st) as s, " +
--                      fMap + "(mp) as m, " +
--                      fTup + "(tup) as t, " +
--                      fUdt + "(udt) as u " +
--                      "FROM %s WHERE key = 2").one();
--        Assert.assertNull(row.getBytes("l"));
--        Assert.assertNull(row.getBytes("s"));
--        Assert.assertNull(row.getBytes("m"));
--        Assert.assertNull(row.getBytes("t"));
--        Assert.assertNull(row.getBytes("u"));
--
-         for (int version : PROTOCOL_VERSIONS)
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
--        {
--            Row r = executeNet(version, "SELECT " +
--                                        fList + "(lst) as l, " +
--                                        fSet + "(st) as s, " +
--                                        fMap + "(mp) as m, " +
--                                        fTup + "(tup) as t, " +
--                                        fUdt + "(udt) as u " +
--                                        "FROM %s WHERE key = 1").one();
--            Assert.assertNotNull(r.getBytesUnsafe("l"));
--            Assert.assertNotNull(r.getBytesUnsafe("s"));
--            Assert.assertNotNull(r.getBytesUnsafe("m"));
--            Assert.assertNotNull(r.getBytesUnsafe("t"));
--            Assert.assertNotNull(r.getBytesUnsafe("u"));
--            r = executeNet(version, "SELECT " +
--                                    fList + "(lst) as l, " +
--                                    fSet + "(st) as s, " +
--                                    fMap + "(mp) as m, " +
--                                    fTup + "(tup) as t, " +
--                                    fUdt + "(udt) as u " +
--                                    "FROM %s WHERE key = 2").one();
--            Assert.assertNull(r.getBytesUnsafe("l"));
--            Assert.assertNull(r.getBytesUnsafe("s"));
--            Assert.assertNull(r.getBytesUnsafe("m"));
--            Assert.assertNull(r.getBytesUnsafe("t"));
--            Assert.assertNull(r.getBytesUnsafe("u"));
-         }
-     }
- 
-     @Test
-     public void testJavaTupleType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
- 
-         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
-                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS tuple<double, text, int, boolean> " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return tup;$$;");
- 
-         Object t = tuple(1d, "foo", 2, true);
- 
-         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
- 
-         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                    row(t));
- 
-         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                    row(t));
-     }
- 
-     @Test
-     public void testJavaTupleTypeCollection() throws Throwable
-     {
-         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
- 
-         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
- 
-         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "CALLED ON NULL INPUT " +
-                 "RETURNS " + tupleTypeDef + ' ' +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup;$$;");
-         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "CALLED ON NULL INPUT " +
-                 "RETURNS double " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       Double.valueOf(tup.getDouble(0));$$;");
-         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS list<double> " +
-                                       "LANGUAGE java\n" +
-                                       "AS $$return " +
-                                       "       tup.getList(1, Double.class);$$;");
-         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "RETURNS NULL ON NULL INPUT " +
-                 "RETURNS set<text> " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup.getSet(2, String.class);$$;");
-         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "RETURNS NULL ON NULL INPUT " +
-                 "RETURNS map<int, boolean> " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup.getMap(3, Integer.class, Boolean.class);$$;");
- 
-         List<Double> list = Arrays.asList(1d, 2d, 3d);
-         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-         Map<Integer, Boolean> map = new TreeMap<>();
-         map.put(1, true);
-         map.put(2, false);
-         map.put(3, true);
- 
-         Object t = tuple(1d, list, set, map);
- 
-         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
- 
-         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                    row(t));
-         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                    row(1d));
-         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                    row(list));
-         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                    row(set));
-         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                    row(map));
- 
-         // same test - but via native protocol
-         // we use protocol V3 here to encode the expected version because the server
-         // always serializes Collections using V3 - see CollectionSerializer's
-         // serialize and deserialize methods.
-         TupleType tType = tupleTypeOf(Server.VERSION_3,
-                                       DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-         TupleValue tup = tType.newValue(1d, list, set, map);
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                           row(tup));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                           row(1d));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                           row(list));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                           row(set));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                           row(map));
-         }
-     }
- 
-     @Test
-     public void testJavaUserTypeWithUse() throws Throwable
-     {
-         String type = createType("CREATE TYPE %s (txt text, i int)");
-         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
-         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
- 
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             executeNet(version, "USE " + KEYSPACE);
- 
-             executeNet(version,
-                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
-                        "RETURNS NULL ON NULL INPUT " +
-                        "RETURNS " + type + " " +
-                        "LANGUAGE java " +
-                        "AS $$return " +
-                        "     udt;$$;");
-             try
-             {
-                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
-                 Assert.assertEquals(1, rowsNet.size());
-                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-                 Assert.assertEquals("one", udtVal.getString("txt"));
-                 Assert.assertEquals(1, udtVal.getInt("i"));
-             }
-             finally
-             {
-                 executeNet(version, "DROP FUNCTION f_use1");
-             }
-         }
-     }
- 
-     @Test
-     public void testJavaUserType() throws Throwable
-     {
-         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
- 
-         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- 
-         String fUdt0 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + " ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS " + type + " " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     udt;$$;");
-         String fUdt1 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + ") " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS text " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     udt.getString(\"txt\");$$;");
-         String fUdt2 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + ") " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS int " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
- 
-         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
- 
-         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
-         Assert.assertEquals(1, rows.size());
-         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                    row("one"));
-         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                    row(1));
- 
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
-             Assert.assertEquals(1, rowsNet.size());
-             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-             Assert.assertEquals("one", udtVal.getString("txt"));
-             Assert.assertEquals(1, udtVal.getInt("i"));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                           row("one"));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                           row(1));
--        }
--    }
--
--    @Test
      public void testUserTypeDrop() throws Throwable
      {
          String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
@@@ -1593,162 -880,140 +757,7 @@@
                               "AS '\"foo bar\";';");
      }
  
 -    private static class TypesTestDef
 -    {
 -        final String udfType;
 -        final String tableType;
 -        final String columnName;
 -        final Object referenceValue;
 -
 -        String fCheckArgAndReturn;
 -
 -        String fCalledOnNull;
 -        String fReturnsNullOnNull;
 -
 -        TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
 -        {
 -            this.udfType = udfType;
 -            this.tableType = tableType;
 -            this.columnName = columnName;
 -            this.referenceValue = referenceValue;
 -        }
 -    }
 -
 -    @Test
 -    public void testTypesWithAndWithoutNulls() throws Throwable
 -    {
 -        // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
 -
 -        String type = createType("CREATE TYPE %s (txt text, i int)");
 -
 -        TypesTestDef[] typeDefs =
 -        {
 -        //                udf type,            table type,                 column, reference value
 -        new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
 -        new TypesTestDef("date", "date", "dt", 12345),
 -        new TypesTestDef("time", "time", "tim", 12345L),
 -        new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
 -        new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
 -        new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
 -        new TypesTestDef("smallint", "smallint", "si", (short) 43),
 -        new TypesTestDef("int", "int", "i", 44),
 -        new TypesTestDef("bigint", "bigint", "b", 45L),
 -        new TypesTestDef("float", "float", "f", 46f),
 -        new TypesTestDef("double", "double", "d", 47d),
 -        new TypesTestDef("boolean", "boolean", "x", true),
 -        new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
 -        new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
 -        //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
 -        new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
 -        };
 -
 -        String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
 -        String insertDML = "INSERT INTO %s (key";
 -        List<Object> values = new ArrayList<>();
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
 -            insertDML += ", " + typeDef.columnName;
 -            String typeName = typeDef.udfType;
 -            typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
 -                                                        typeName,
 -                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                        "CALLED ON NULL INPUT " +
 -                                                        "RETURNS " + typeName + ' ' +
 -                                                        "LANGUAGE java\n" +
 -                                                        "AS 'return val;';");
 -            typeDef.fCalledOnNull = createFunction(KEYSPACE,
 -                                                   typeName,
 -                                                   "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                   "CALLED ON NULL INPUT " +
 -                                                   "RETURNS text " +
 -                                                   "LANGUAGE java\n" +
 -                                                   "AS 'return \"called\";';");
 -            typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
 -                                                        typeName,
 -                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                        "RETURNS NULL ON NULL INPUT " +
 -                                                        "RETURNS text " +
 -                                                        "LANGUAGE java\n" +
 -                                                        "AS 'return \"called\";';");
 -            values.add(typeDef.referenceValue);
 -        }
 -
 -        createTableDDL += ')';
 -        createTable(createTableDDL);
 -
 -        insertDML += ") VALUES (1";
 -        for (TypesTestDef ignored : typeDefs)
 -            insertDML += ", ?";
 -        insertDML += ')';
 -
 -        execute(insertDML, values.toArray());
 -
 -        // second row with null values
 -        for (int i = 0; i < values.size(); i++)
 -            values.set(i, null);
 -        execute(insertDML.replace('1', '2'), values.toArray());
 -
 -        // check argument input + return
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ typeDef.referenceValue }));
 -        }
 -
 -        // check for CALLED ON NULL INPUT with non-null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for CALLED ON NULL INPUT with null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for RETURNS NULL ON NULL INPUT with non-null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for RETURNS NULL ON NULL INPUT with null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
 -                       row(new Object[]{ null }));
 -        }
 -
 -    }
 -
      @Test
-     public void testJavascriptCompileFailure() throws Throwable
-     {
-         assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE javascript\n" +
-                              "AS 'foo bar';");
-     }
- 
-     @Test
-     public void testScriptInvalidLanguage() throws Throwable
-     {
-         assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE artificial_intelligence\n" +
-                              "AS 'question for 42?';");
-     }
- 
-     static class TypesTestDef
-     {
-         final String udfType;
-         final String tableType;
-         final String columnName;
-         final Object referenceValue;
- 
-         String fCheckArgAndReturn;
- 
-         String fCalledOnNull;
-         String fReturnsNullOnNull;
- 
-         TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
-         {
-             this.udfType = udfType;
-             this.tableType = tableType;
-             this.columnName = columnName;
-             this.referenceValue = referenceValue;
-         }
-     }
- 
-     @Test
-     public void testTypesWithAndWithoutNulls() throws Throwable
-     {
-         // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
- 
-         String type = createType("CREATE TYPE %s (txt text, i int)");
- 
-         TypesTestDef[] typeDefs =
-         {
-         //                udf type,            table type,                 column, reference value
-         new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
-         new TypesTestDef("date", "date", "dt", 12345),
-         new TypesTestDef("time", "time", "tim", 12345L),
-         new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
-         new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
-         new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
-         new TypesTestDef("smallint", "smallint", "si", (short) 43),
-         new TypesTestDef("int", "int", "i", 44),
-         new TypesTestDef("bigint", "bigint", "b", 45L),
-         new TypesTestDef("float", "float", "f", 46f),
-         new TypesTestDef("double", "double", "d", 47d),
-         new TypesTestDef("boolean", "boolean", "x", true),
-         new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
-         new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
-         //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
-         new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
-         };
- 
-         String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
-         String insertDML = "INSERT INTO %s (key";
-         List<Object> values = new ArrayList<>();
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
-             insertDML += ", " + typeDef.columnName;
-             String typeName = typeDef.udfType;
-             typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
-                                                         typeName,
-                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                         "CALLED ON NULL INPUT " +
-                                                         "RETURNS " + typeName + ' ' +
-                                                         "LANGUAGE java\n" +
-                                                         "AS 'return val;';");
-             typeDef.fCalledOnNull = createFunction(KEYSPACE,
-                                                    typeName,
-                                                    "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                    "CALLED ON NULL INPUT " +
-                                                    "RETURNS text " +
-                                                    "LANGUAGE java\n" +
-                                                    "AS 'return \"called\";';");
-             typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
-                                                         typeName,
-                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                         "RETURNS NULL ON NULL INPUT " +
-                                                         "RETURNS text " +
-                                                         "LANGUAGE java\n" +
-                                                         "AS 'return \"called\";';");
-             values.add(typeDef.referenceValue);
-         }
- 
-         createTableDDL += ')';
-         createTable(createTableDDL);
- 
-         insertDML += ") VALUES (1";
-         for (TypesTestDef ignored : typeDefs)
-             insertDML += ", ?";
-         insertDML += ')';
- 
-         execute(insertDML, values.toArray());
- 
-         // second row with null values
-         for (int i = 0; i < values.size(); i++)
-             values.set(i, null);
-         execute(insertDML.replace('1', '2'), values.toArray());
- 
-         // check argument input + return
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ typeDef.referenceValue }));
-         }
- 
-         // check for CALLED ON NULL INPUT with non-null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for CALLED ON NULL INPUT with null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for RETURNS NULL ON NULL INPUT with non-null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for RETURNS NULL ON NULL INPUT with null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
-                        row(new Object[]{ null }));
-         }
- 
-     }
- 
-     @Test
      public void testReplaceAllowNulls() throws Throwable
      {
          String fNulls = createFunction(KEYSPACE,
@@@ -1851,638 -1108,4 +860,112 @@@
              }
          }
      }
-     @Test
-     public void testFunctionWithFrozenSetType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<set<int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "set<int>",
-                                              "CREATE FUNCTION %s (values set<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "set<int>",
-                                              "CREATE FUNCTION %s (values set<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS set<int> " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenListType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<list<int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "list<int>",
-                                              "CREATE FUNCTION %s (values list<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "list<int>",
-                                       "CREATE FUNCTION %s (values list<int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS list<int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenMapType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<map<int, int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "map<int, int>",
-                                              "CREATE FUNCTION %s (values map<int, int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "map<int, int>",
-                                       "CREATE FUNCTION %s (values map<int, int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS map<int, int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenTupleType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
-         createIndex("CREATE INDEX ON %s (b)");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values.toString();';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<tuple<int, int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "tuple<int, int>",
-                                              "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values.toString();';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "tuple<int, int>",
-                                       "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS tuple<int, int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenUDType() throws Throwable
-     {
-         String myType = createType("CREATE TYPE %s (f int)");
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-         createIndex("CREATE INDEX ON %s (b)");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values.toString();';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<" + myType + "> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              myType,
-                                              "CREATE FUNCTION %s (values " + myType + ") " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values.toString();';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
- 
-         functionName = createFunction(KEYSPACE,
-                                       myType,
-                                       "CREATE FUNCTION %s (values " + myType + ") " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS " + myType + " " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
-     }
 +
 +    @Test
 +    public void testEmptyString() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
 +        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
 +
 +        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return \"\";'");
 +
 +        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return \"\";'");
 +
 +        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return ByteBuffer.allocate(0);'");
 +
 +        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return ByteBuffer.allocate(0);'");
 +
 +        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return 0;'");
 +
 +        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return 0;'");
 +
 +        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
 +        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +    }
- 
-     @Test
-     public void testAllNativeTypes() throws Throwable
-     {
-         StringBuilder sig = new StringBuilder();
-         StringBuilder args = new StringBuilder();
-         for (CQL3Type.Native type : CQL3Type.Native.values())
-         {
-             if (type == CQL3Type.Native.EMPTY)
-                 continue;
- 
-             if (sig.length() > 0)
-                 sig.append(',');
-             sig.append(type.toString());
- 
-             if (args.length() > 0)
-                 args.append(',');
-             args.append("arg").append(type.toString()).append(' ').append(type.toString());
-         }
-         createFunction(KEYSPACE, sig.toString(),
-                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
-                        "RETURNS NULL ON NULL INPUT " +
-                        "RETURNS int " +
-                        "LANGUAGE JAVA\n" +
-                        "AS 'return 0;'");
- 
-         for (CQL3Type.Native type : CQL3Type.Native.values())
-         {
-             if (type == CQL3Type.Native.EMPTY)
-                 continue;
- 
-             createFunction(KEYSPACE_PER_TEST, type.toString(),
-                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
-                            "RETURNS NULL ON NULL INPUT " +
-                            "RETURNS int " +
-                            "LANGUAGE JAVA\n" +
-                            "AS 'return 0;'");
-         }
-     }
- 
-     @Test
-     public void testSecurityPermissions() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, dval double)");
-         execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
- 
-         // Java UDFs
- 
-         try
-         {
-             String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                           "RETURNS NULL ON NULL INPUT " +
-                                           "RETURNS double " +
-                                           "LANGUAGE JAVA\n" +
-                                           "AS 'System.getProperty(\"foo.bar.baz\"); return 0d;';");
-             execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-             Assert.fail();
-         }
-         catch (FunctionExecutionException e)
-         {
-             assertAccessControlException("System.getProperty(\"foo.bar.baz\"); return 0d;", e);
-         }
- 
-         String[][] typesAndSources =
-         {
-         {"",                        "try { Class.forName(\"" + UDHelper.class.getName() + "\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
-         {"sun.misc.Unsafe",         "sun.misc.Unsafe.getUnsafe(); return 0d;"},
-         {"",                        "try { Class.forName(\"sun.misc.Unsafe\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
-         {"java.nio.file.FileSystems", "try {" +
-                                     "     java.nio.file.FileSystems.getDefault(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.nio.channels.FileChannel", "try {" +
-                                     "     java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")).close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.nio.channels.SocketChannel", "try {" +
-                                     "     java.nio.channels.SocketChannel.open().close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.io.FileInputStream", "try {" +
-                                     "     new java.io.FileInputStream(\"./foobar\").close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.lang.Runtime",       "try {" +
-                                     "     java.lang.Runtime.getRuntime(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"org.apache.cassandra.service.StorageService",
-                                     "try {" +
-                                     "     org.apache.cassandra.service.StorageService v = org.apache.cassandra.service.StorageService.instance; v.isShutdown(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.net.ServerSocket",   "try {" +
-                                     "     new java.net.ServerSocket().bind(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.io.FileOutputStream","try {" +
-                                     "     new java.io.FileOutputStream(\".foo\"); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.lang.Runtime",       "try {" +
-                                     "     java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'}
-         };
- 
-         for (String[] typeAndSource : typesAndSources)
-         {
-             assertInvalidMessage(typeAndSource[0] + " cannot be resolved",
-                                  "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".invalid_class_access(val double) " +
-                                  "RETURNS NULL ON NULL INPUT " +
-                                  "RETURNS double " +
-                                  "LANGUAGE JAVA\n" +
-                                  "AS '" + typeAndSource[1] + "';");
-         }
- 
-         // JavaScript UDFs
- 
-         try
-         {
-             String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                           "RETURNS NULL ON NULL INPUT " +
-                                           "RETURNS double " +
-                                           "LANGUAGE javascript\n" +
-                                           "AS 'org.apache.cassandra.service.StorageService.instance.isShutdown(); 0;';");
-             execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-             Assert.fail("Javascript security check failed");
-         }
-         catch (FunctionExecutionException e)
-         {
-             assertAccessControlException("", e);
-         }
- 
-         String[] javascript =
-         {
-         "java.lang.management.ManagmentFactory.getThreadMXBean(); 0;",
-         "new java.io.FileInputStream(\"/tmp/foo\"); 0;",
-         "new java.io.FileOutputStream(\"/tmp/foo\"); 0;",
-         "java.nio.file.FileSystems.getDefault().createFileExclusively(\"./foo_bar_baz\"); 0;",
-         "java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")); 0;",
-         "java.nio.channels.SocketChannel.open(); 0;",
-         "new java.net.ServerSocket().bind(null); 0;",
-         "var thread = new java.lang.Thread(); thread.start(); 0;",
-         "java.lang.System.getProperty(\"foo.bar.baz\"); 0;",
-         "java.lang.Class.forName(\"java.lang.System\"); 0;",
-         "java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); 0;",
-         "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
-         "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
-         // TODO these (ugly) calls are still possible - these can consume CPU (as one could do with an evil loop, too)
- //        "java.lang.Runtime.getRuntime().traceMethodCalls(true); 0;",
- //        "java.lang.Runtime.getRuntime().gc(); 0;",
- //        "java.lang.Runtime.getRuntime(); 0;",
-         };
- 
-         for (String script : javascript)
-         {
-             try
-             {
-                 String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                               "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                               "RETURNS NULL ON NULL INPUT " +
-                                               "RETURNS double " +
-                                               "LANGUAGE javascript\n" +
-                                               "AS '" + script + "';");
-                 execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-                 Assert.fail("Javascript security check failed: " + script);
-             }
-             catch (FunctionExecutionException e)
-             {
-                 assertAccessControlException(script, e);
-             }
-         }
-     }
- 
-     private static void assertAccessControlException(String script, FunctionExecutionException e)
-     {
-         for (Throwable t = e; t != null && t != t.getCause(); t = t.getCause())
-             if (t instanceof AccessControlException)
-                 return;
-         Assert.fail("no AccessControlException for " + script + " (got " + e + ')');
-     }
- 
-     @Test
-     public void testAmokUDF() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, dval double)");
-         execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
- 
-         long udfWarnTimeout = DatabaseDescriptor.getUserDefinedFunctionWarnTimeout();
-         long udfFailTimeout = DatabaseDescriptor.getUserDefinedFunctionFailTimeout();
-         int maxTries = 5;
-         for (int i = 1; i <= maxTries; i++)
-         {
-             try
-             {
-                 // short timeout
-                 DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(10);
-                 DatabaseDescriptor.setUserDefinedFunctionFailTimeout(250);
-                 // don't kill the unit test... - default policy is "die"
-                 DatabaseDescriptor.setUserFunctionTimeoutPolicy(Config.UserFunctionTimeoutPolicy.ignore);
- 
-                 ClientWarn.instance.captureWarnings();
-                 String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                               "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                               "RETURNS NULL ON NULL INPUT " +
-                                               "RETURNS double " +
-                                               "LANGUAGE JAVA\n" +
-                                               "AS 'long t=System.currentTimeMillis()+110; while (t>System.currentTimeMillis()) { }; return 0d;'");
-                 execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-                 List<String> warnings = ClientWarn.instance.getWarnings();
-                 Assert.assertNotNull(warnings);
-                 Assert.assertFalse(warnings.isEmpty());
-                 ClientWarn.instance.resetWarnings();
- 
-                 // Java UDF
- 
-                 fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                        "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                        "RETURNS NULL ON NULL INPUT " +
-                                        "RETURNS double " +
-                                        "LANGUAGE JAVA\n" +
-                                        "AS 'long t=System.currentTimeMillis()+500; while (t>System.currentTimeMillis()) { }; return 0d;';");
-                 assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
- 
-                 // Javascript UDF
- 
-                 fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                        "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                        "RETURNS NULL ON NULL INPUT " +
-                                        "RETURNS double " +
-                                        "LANGUAGE JAVASCRIPT\n" +
-                                        "AS 'var t=java.lang.System.currentTimeMillis()+500; while (t>java.lang.System.currentTimeMillis()) { }; 0;';");
-                 assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
- 
-                 return;
-             }
-             catch (Error | RuntimeException e)
-             {
-                 if (i == maxTries)
-                     throw e;
-             }
-             finally
-             {
-                 // reset to defaults
-                 DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(udfWarnTimeout);
-                 DatabaseDescriptor.setUserDefinedFunctionFailTimeout(udfFailTimeout);
-             }
-         }
-     }
  }


[07/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index bcfe871..d4d2a10 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@ -17,9 +17,6 @@
  */
 package org.apache.cassandra.cql3.validation.entities;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -34,14 +31,9 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.Row;
-import com.datastax.driver.core.TupleType;
-import com.datastax.driver.core.TupleValue;
-import com.datastax.driver.core.UDTValue;
 import com.datastax.driver.core.exceptions.InvalidQueryException;
 import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.cql3.CQL3Type;
 import org.apache.cassandra.cql3.CQLTester;
 import org.apache.cassandra.cql3.QueryProcessor;
 import org.apache.cassandra.cql3.UntypedResultSet;
@@ -50,13 +42,11 @@ import org.apache.cassandra.cql3.functions.Functions;
 import org.apache.cassandra.cql3.functions.UDFunction;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.dht.ByteOrderedPartitioner;
-import org.apache.cassandra.exceptions.FunctionExecutionException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.transport.Event;
 import org.apache.cassandra.transport.Server;
 import org.apache.cassandra.transport.messages.ResultMessage;
-import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.UUIDGen;
 
 public class UFTest extends CQLTester
@@ -295,7 +285,7 @@ public class UFTest extends CQLTester
         return prepared;
     }
 
-    public void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
+    private void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
     {
         // prepare a statement which doesn't use any function for a control
         createTable("CREATE TABLE %s (" +
@@ -584,164 +574,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaFunctionNoParameters() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = "\n  return 1L;\n";
-
-        String fName = createFunction(KEYSPACE, "",
-                                      "CREATE OR REPLACE FUNCTION %s() " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" +functionBody + "';");
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           KEYSPACE, parseFunctionName(fName).name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
-                   row(1, 1d, 1L),
-                   row(2, 2d, 1L),
-                   row(3, 3d, 1L)
-        );
-    }
-
-    @Test
-    public void testJavaFunctionInvalidBodies() throws Throwable
-    {
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
-        }
-
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz;" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
-        }
-    }
-
-    @Test
-    public void testJavaFunctionInvalidReturn() throws Throwable
-    {
-        assertInvalidMessage("system keyspace is not user-modifiable",
-                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE JAVA\n" +
-                             "AS 'return 1L;';");
-    }
-
-    @Test
-    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val bigint)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return Double.valueOf(val);';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
-        assertInvalidMessage("val cannot be passed as argument 0 of function",
-                             "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaFunctionCounter() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val counter)");
-
-        String fName = createFunction(KEYSPACE, "counter",
-                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return val + 1;';");
-
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1L, 2L));
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 4L, 5L));
-        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-    }
-
-    @Test
     public void testFunctionInTargetKeyspace() throws Throwable
     {
         createTable("CREATE TABLE %s (key int primary key, val double)");
@@ -869,140 +701,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaKeyspaceFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin( val );\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                     "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                     "CALLED ON NULL INPUT " +
-                                     "RETURNS double " +
-                                     "LANGUAGE JAVA " +
-                                     "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaRuntimeException() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  throw new RuntimeException(\"oh no!\");\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-
-        // function throws a RuntimeException which is wrapped by FunctionExecutionException
-        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaDollarQuotedFunction() throws Throwable
-    {
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (input == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE FUNCTION %s( input double ) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$" + functionBody + "$$;");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-    }
-
-    @Test
-    public void testJavaSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                                     "CREATE FUNCTION %s( lst list<double> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS list<double> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return lst;$$;");
-        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                                     "CREATE FUNCTION %s( st set<text> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS set<text> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return st;$$;");
-        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS map<int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return mp;$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
     public void testWrongKeyspace() throws Throwable
     {
         String typeName = createType("CREATE TYPE %s (txt text, i int)");
@@ -1135,206 +833,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
-                                     "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS tuple<double, text, int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavaTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS " + tupleTypeDef + ' ' +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup;$$;");
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       Double.valueOf(tup.getDouble(0));$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS list<double> " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return " +
-                                      "       tup.getList(1, Double.class);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getSet(2, String.class);$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getMap(3, Integer.class, Boolean.class);$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavaUserTypeWithUse() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            executeNet(version, "USE " + KEYSPACE);
-
-            executeNet(version,
-                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS " + type + " " +
-                       "LANGUAGE java " +
-                       "AS $$return " +
-                       "     udt;$$;");
-            try
-            {
-                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
-                Assert.assertEquals(1, rowsNet.size());
-                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-                Assert.assertEquals("one", udtVal.getString("txt"));
-                Assert.assertEquals(1, udtVal.getInt("i"));
-            }
-            finally
-            {
-                executeNet(version, "DROP FUNCTION f_use1");
-            }
-        }
-    }
-
-    @Test
-    public void testJavaUserType() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt0 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS " + type + " " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt;$$;");
-        String fUdt1 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt.getString(\"txt\");$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
-            Assert.assertEquals(1, rowsNet.size());
-            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-            Assert.assertEquals("one", udtVal.getString("txt"));
-            Assert.assertEquals(1, udtVal.getInt("i"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                          row("one"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                          row(1));
-        }
-    }
-
-    @Test
     public void testUserTypeDrop() throws Throwable
     {
         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
@@ -1372,686 +870,22 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaUserTypeRenameField() throws Throwable
+    public void testDuplicateArgNames() throws Throwable
     {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+        assertInvalidMessage("duplicate argument names for given function",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE javascript\n" +
+                             "AS '\"foo bar\";';");
+    }
 
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return udt.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-
-        execute("ALTER TYPE " + type + " RENAME txt TO str");
-
-        assertInvalidMessage("txt is not a field defined in this UDT",
-                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
-
-        execute("ALTER TYPE " + type + " RENAME str TO txt");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-    }
-
-    @Test
-    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName1replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + ") " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS double " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS " + type + " " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt;$$;");
-
-        String fName1noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "CALLED ON NULL INPUT " +
-                                                "RETURNS double " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "RETURNS NULL ON NULL INPUT " +
-                                                "RETURNS " + type + " " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return udt;$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        // add field
-
-        execute("ALTER TYPE " + type + " ADD added double");
-
-        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
-
-        // note: type references of functions remain at the state _before_ the type mutation
-        // means we need to recreate the functions
-
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt.getString(\"txt\");$$;",
-                              fName1replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
-                              fName2replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
-                              fName3replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS %s " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt;$$;",
-                              fName4replace, type, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        // un-replaced functions will work since the user type has changed
-        // and the UDF has exchanged the user type reference
-
-        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        execute("DROP FUNCTION " + fName1replace);
-        execute("DROP FUNCTION " + fName2replace);
-        execute("DROP FUNCTION " + fName3replace);
-        execute("DROP FUNCTION " + fName4replace);
-        execute("DROP FUNCTION " + fName1noReplace);
-        execute("DROP FUNCTION " + fName2noReplace);
-        execute("DROP FUNCTION " + fName3noReplace);
-        execute("DROP FUNCTION " + fName4noReplace);
-    }
-
-    @Test
-    public void testJavaUTCollections() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
-                              "     return udtVal.getString(\"txt\");$$;");
-        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
-                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS text " +
-                                       "LANGUAGE java\n" +
-                                       "AS $$" +
-                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
-                                       "     return udtVal.getString(\"txt\");$$;");
-        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
-                              "     return udtVal.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row("three", "one", "two"));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                "CREATE FUNCTION %s( lst list<double> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS 'lst;';");
-        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                "CREATE FUNCTION %s( st set<text> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS 'st;';");
-        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS 'mp;';");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
-    public void testJavascriptTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
-                "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, text, int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavascriptTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup;$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getDouble(0);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
-        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        // same test - but via native protocol
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavascriptUserType() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt1 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS " + type + " " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt;$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt.getString(\"txt\");$$;");
-        String fUdt3 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "     udt.getInt(\"i\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-    }
-
-    @Test
-    public void testJavascriptUTCollections() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "        lst.get(1).getString(\"txt\");$$;");
-        createFunctionOverload(fName, "set<frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        st.iterator().next().getString(\"txt\");$$;");
-        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                // list<frozen<UDT>>
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                // set<frozen<UDT>>
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                // map<int, frozen<UDT>>
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
-                   row("three"));
-        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
-                   row("two"));
-
-        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
-        assertRows(execute(cqlSelect),
-                   row("three", "one", "two"));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, cqlSelect),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("javascript", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavascriptBadReturnType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '\"string\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ClassCastException
-        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavascriptThrow() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                       "CREATE OR REPLACE FUNCTION %s(val double) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS double " +
-                       "LANGUAGE javascript\n" +
-                       "AS 'throw \"fool\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ScriptException
-        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testDuplicateArgNames() throws Throwable
-    {
-        assertInvalidMessage("duplicate argument names for given function",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE javascript\n" +
-                             "AS '\"foo bar\";';");
-    }
-
-    @Test
-    public void testJavascriptCompileFailure() throws Throwable
-    {
-        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE javascript\n" +
-                             "AS 'foo bar';");
-    }
-
-    @Test
-    public void testScriptInvalidLanguage() throws Throwable
-    {
-        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE artificial_intelligence\n" +
-                             "AS 'question for 42?';");
-    }
-
-    @Test
-    public void testScriptReturnTypeCasting() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-
-        Object[][] variations = {
-                                new Object[]    {   "true",     "boolean",  true    },
-                                new Object[]    {   "false",    "boolean",  false   },
-                                new Object[]    {   "100",      "tinyint",  (byte)100 },
-                                new Object[]    {   "100.",     "tinyint",  (byte)100 },
-                                new Object[]    {   "100",      "smallint", (short)100 },
-                                new Object[]    {   "100.",     "smallint", (short)100 },
-                                new Object[]    {   "100",      "int",      100     },
-                                new Object[]    {   "100.",     "int",      100     },
-                                new Object[]    {   "100",      "double",   100d    },
-                                new Object[]    {   "100.",     "double",   100d    },
-                                new Object[]    {   "100",      "bigint",   100L    },
-                                new Object[]    {   "100.",     "bigint",   100L    },
-                                new Object[]    {   "100",      "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "parseInt(\"100\");", "decimal",  BigDecimal.valueOf(100d)    },
-                                new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object functionBody = variation[0];
-            Object returnType = variation[1];
-            Object expectedResult = variation[2];
-
-            String fName = createFunction(KEYSPACE, "double",
-                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " +returnType + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS '" + functionBody + ";';");
-            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                       row(1, 1d, expectedResult));
-        }
-    }
-
-    @Test
-    public void testScriptParamReturnTypes() throws Throwable
-    {
-        UUID ruuid = UUID.randomUUID();
-        UUID tuuid = UUIDGen.getTimeUUID();
-
-        createTable("CREATE TABLE %s (key int primary key, " +
-                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
-                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
-        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
-                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
-                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
-
-        Object[][] variations = {
-                                new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
-                                new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
-                                new Object[] {  "int",      "ival",     1,                      2  },
-                                new Object[] {  "bigint",   "lval",     1L,                     2L  },
-                                new Object[] {  "float",    "fval",     1f,                     2f  },
-                                new Object[] {  "double",   "dval",     1d,                     2d  },
-                                new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
-                                new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
-                                new Object[] {  "time",     "timval",   1L,                     2L  },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS " + type + ' ' +
-                           "LANGUAGE javascript " +
-                           "AS 'val+1;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-
-        variations = new Object[][] {
-                     new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
-                     new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
-                     new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
-                     new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
-        };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " + type + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS 'val;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-    }
-
-    static class TypesTestDef
-    {
-        final String udfType;
-        final String tableType;
-        final String columnName;
-        final Object referenceValue;
+    private static class TypesTestDef
+    {
+        final String udfType;
+        final String tableType;
+        final String columnName;
+        final Object referenceValue;
 
         String fCheckArgAndReturn;
 
@@ -2274,416 +1108,4 @@ public class UFTest extends CQLTester
             }
         }
     }
-
-    @Test
-    public void testFunctionWithFrozenSetType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<set<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS set<int> " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenListType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<list<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "list<int>",
-                                             "CREATE FUNCTION %s (values list<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "list<int>",
-                                      "CREATE FUNCTION %s (values list<int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS list<int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenMapType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<map<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "map<int, int>",
-                                             "CREATE FUNCTION %s (values map<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "map<int, int>",
-                                      "CREATE FUNCTION %s (values map<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS map<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<tuple<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "tuple<int, int>",
-                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "(null, null)"),
-                   row(1, "(1, 2)"),
-                   row(2, "(4, 5)"),
-                   row(3, "(7, 8)"));
-
-        functionName = createFunction(KEYSPACE,
-                                      "tuple<int, int>",
-                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS tuple<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenUDType() throws Throwable
-    {
-        String myType = createType("CREATE TYPE %s (f int)");
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<" + myType + "> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             myType,
-                                             "CREATE FUNCTION %s (values " + myType + ") " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "{f:0}"),
-                   row(1, "{f:1}"),
-                   row(2, "{f:4}"),
-                   row(3, "{f:7}"));
-
-        functionName = createFunction(KEYSPACE,
-                                      myType,
-                                      "CREATE FUNCTION %s (values " + myType + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS " + myType + " " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
-    }
-
-    @Test
-    public void testEmptyString() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
-        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
-
-        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
-        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
-    }
-
-    @Test
-    public void testAllNativeTypes() throws Throwable
-    {
-        StringBuilder sig = new StringBuilder();
-        StringBuilder args = new StringBuilder();
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            if (sig.length() > 0)
-                sig.append(',');
-            sig.append(type.toString());
-
-            if (args.length() > 0)
-                args.append(',');
-            args.append("arg").append(type.toString()).append(' ').append(type.toString());
-        }
-        createFunction(KEYSPACE, sig.toString(),
-                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS int " +
-                       "LANGUAGE JAVA\n" +
-                       "AS 'return 0;'");
-
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            createFunction(KEYSPACE_PER_TEST, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS int " +
-                           "LANGUAGE JAVA\n" +
-                           "AS 'return 0;'");
-        }
-    }
 }


[17/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
index 0000000,0000000..de98748
new file mode 100644
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
@@@ -1,0 -1,0 +1,549 @@@
++/*
++ * 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.util.ArrayList;
++import java.util.Arrays;
++import java.util.Date;
++import java.util.List;
++import java.util.Map;
++import java.util.Set;
++import java.util.TreeMap;
++import java.util.TreeSet;
++import java.util.UUID;
++
++import org.junit.Assert;
++import org.junit.Test;
++
++import com.datastax.driver.core.Row;
++import org.apache.cassandra.cql3.CQLTester;
++import org.apache.cassandra.cql3.UntypedResultSet;
++import org.apache.cassandra.utils.UUIDGen;
++
++public class UFTypesTest extends CQLTester
++{
++
++    @Test
++    public void testComplexNullValues() throws Throwable
++    {
++        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
++
++        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
++                    "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
++
++        String fList = createFunction(KEYSPACE, "list<double>",
++                                      "CREATE FUNCTION %s( coll list<double> ) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS list<double> " +
++                                      "LANGUAGE java\n" +
++                                      "AS $$return coll;$$;");
++        String fSet = createFunction(KEYSPACE, "set<text>",
++                                     "CREATE FUNCTION %s( coll set<text> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS set<text> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return coll;$$;");
++        String fMap = createFunction(KEYSPACE, "map<int, boolean>",
++                                     "CREATE FUNCTION %s( coll map<int, boolean> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS map<int, boolean> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return coll;$$;");
++        String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
++                                     "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS tuple<double, text, int, boolean> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return val;$$;");
++        String fUdt = createFunction(KEYSPACE, type,
++                                     "CREATE FUNCTION %s( val " + type + " ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS " + type + " " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return val;$$;");
++        List<Double> list = Arrays.asList(1d, 2d, 3d);
++        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
++        Map<Integer, Boolean> map = new TreeMap<>();
++        map.put(1, true);
++        map.put(2, false);
++        map.put(3, true);
++        Object t = tuple(1d, "one", 42, false);
++
++        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
++        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
++
++        execute("SELECT " +
++                fList + "(lst), " +
++                fSet + "(st), " +
++                fMap + "(mp), " +
++                fTup + "(tup), " +
++                fUdt + "(udt) FROM %s WHERE key = 1");
++        UntypedResultSet.Row row = execute("SELECT " +
++                                           fList + "(lst) as l, " +
++                                           fSet + "(st) as s, " +
++                                           fMap + "(mp) as m, " +
++                                           fTup + "(tup) as t, " +
++                                           fUdt + "(udt) as u " +
++                                           "FROM %s WHERE key = 1").one();
++        Assert.assertNotNull(row.getBytes("l"));
++        Assert.assertNotNull(row.getBytes("s"));
++        Assert.assertNotNull(row.getBytes("m"));
++        Assert.assertNotNull(row.getBytes("t"));
++        Assert.assertNotNull(row.getBytes("u"));
++        row = execute("SELECT " +
++                      fList + "(lst) as l, " +
++                      fSet + "(st) as s, " +
++                      fMap + "(mp) as m, " +
++                      fTup + "(tup) as t, " +
++                      fUdt + "(udt) as u " +
++                      "FROM %s WHERE key = 2").one();
++        Assert.assertNull(row.getBytes("l"));
++        Assert.assertNull(row.getBytes("s"));
++        Assert.assertNull(row.getBytes("m"));
++        Assert.assertNull(row.getBytes("t"));
++        Assert.assertNull(row.getBytes("u"));
++
++        for (int version : PROTOCOL_VERSIONS)
++        {
++            Row r = executeNet(version, "SELECT " +
++                                        fList + "(lst) as l, " +
++                                        fSet + "(st) as s, " +
++                                        fMap + "(mp) as m, " +
++                                        fTup + "(tup) as t, " +
++                                        fUdt + "(udt) as u " +
++                                        "FROM %s WHERE key = 1").one();
++            Assert.assertNotNull(r.getBytesUnsafe("l"));
++            Assert.assertNotNull(r.getBytesUnsafe("s"));
++            Assert.assertNotNull(r.getBytesUnsafe("m"));
++            Assert.assertNotNull(r.getBytesUnsafe("t"));
++            Assert.assertNotNull(r.getBytesUnsafe("u"));
++            r = executeNet(version, "SELECT " +
++                                    fList + "(lst) as l, " +
++                                    fSet + "(st) as s, " +
++                                    fMap + "(mp) as m, " +
++                                    fTup + "(tup) as t, " +
++                                    fUdt + "(udt) as u " +
++                                    "FROM %s WHERE key = 2").one();
++            Assert.assertNull(r.getBytesUnsafe("l"));
++            Assert.assertNull(r.getBytesUnsafe("s"));
++            Assert.assertNull(r.getBytesUnsafe("m"));
++            Assert.assertNull(r.getBytesUnsafe("t"));
++            Assert.assertNull(r.getBytesUnsafe("u"));
++        }
++    }
++
++    private static class TypesTestDef
++    {
++        final String udfType;
++        final String tableType;
++        final String columnName;
++        final Object referenceValue;
++
++        String fCheckArgAndReturn;
++
++        String fCalledOnNull;
++        String fReturnsNullOnNull;
++
++        TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
++        {
++            this.udfType = udfType;
++            this.tableType = tableType;
++            this.columnName = columnName;
++            this.referenceValue = referenceValue;
++        }
++    }
++
++    @Test
++    public void testTypesWithAndWithoutNulls() throws Throwable
++    {
++        // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
++
++        String type = createType("CREATE TYPE %s (txt text, i int)");
++
++        TypesTestDef[] typeDefs =
++        {
++        //                udf type,            table type,                 column, reference value
++        new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
++        new TypesTestDef("date", "date", "dt", 12345),
++        new TypesTestDef("time", "time", "tim", 12345L),
++        new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
++        new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
++        new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
++        new TypesTestDef("smallint", "smallint", "si", (short) 43),
++        new TypesTestDef("int", "int", "i", 44),
++        new TypesTestDef("bigint", "bigint", "b", 45L),
++        new TypesTestDef("float", "float", "f", 46f),
++        new TypesTestDef("double", "double", "d", 47d),
++        new TypesTestDef("boolean", "boolean", "x", true),
++        new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
++        new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
++        //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
++        new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
++        };
++
++        String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
++        String insertDML = "INSERT INTO %s (key";
++        List<Object> values = new ArrayList<>();
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
++            insertDML += ", " + typeDef.columnName;
++            String typeName = typeDef.udfType;
++            typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
++                                                        typeName,
++                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                        "CALLED ON NULL INPUT " +
++                                                        "RETURNS " + typeName + ' ' +
++                                                        "LANGUAGE java\n" +
++                                                        "AS 'return val;';");
++            typeDef.fCalledOnNull = createFunction(KEYSPACE,
++                                                   typeName,
++                                                   "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                   "CALLED ON NULL INPUT " +
++                                                   "RETURNS text " +
++                                                   "LANGUAGE java\n" +
++                                                   "AS 'return \"called\";';");
++            typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
++                                                        typeName,
++                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                        "RETURNS NULL ON NULL INPUT " +
++                                                        "RETURNS text " +
++                                                        "LANGUAGE java\n" +
++                                                        "AS 'return \"called\";';");
++            values.add(typeDef.referenceValue);
++        }
++
++        createTableDDL += ')';
++        createTable(createTableDDL);
++
++        insertDML += ") VALUES (1";
++        for (TypesTestDef ignored : typeDefs)
++            insertDML += ", ?";
++        insertDML += ')';
++
++        execute(insertDML, values.toArray());
++
++        // second row with null values
++        for (int i = 0; i < values.size(); i++)
++            values.set(i, null);
++        execute(insertDML.replace('1', '2'), values.toArray());
++
++        // check argument input + return
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ typeDef.referenceValue }));
++        }
++
++        // check for CALLED ON NULL INPUT with non-null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for CALLED ON NULL INPUT with null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for RETURNS NULL ON NULL INPUT with non-null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for RETURNS NULL ON NULL INPUT with null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
++                       row(new Object[]{ null }));
++        }
++
++    }
++
++    @Test
++    public void testFunctionWithFrozenSetType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<set<int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "set<int>",
++                                             "CREATE FUNCTION %s (values set<int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "set<int>",
++                                      "CREATE FUNCTION %s (values set<int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS set<int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenListType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<list<int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "list<int>",
++                                             "CREATE FUNCTION %s (values list<int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "list<int>",
++                                      "CREATE FUNCTION %s (values list<int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS list<int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenMapType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<map<int, int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "map<int, int>",
++                                             "CREATE FUNCTION %s (values map<int, int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "map<int, int>",
++                                      "CREATE FUNCTION %s (values map<int, int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS map<int, int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenTupleType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
++        createIndex("CREATE INDEX ON %s (b)");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS text " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values.toString();';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<tuple<int, int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "tuple<int, int>",
++                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS text " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'return values.toString();';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
++
++        functionName = createFunction(KEYSPACE,
++                                      "tuple<int, int>",
++                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS tuple<int, int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenUDType() throws Throwable
++    {
++        String myType = createType("CREATE TYPE %s (f int)");
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
++        createIndex("CREATE INDEX ON %s (b)");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS text " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values.toString();';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<" + myType + "> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             myType,
++                                             "CREATE FUNCTION %s (values " + myType + ") " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS text " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'return values.toString();';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
++
++        functionName = createFunction(KEYSPACE,
++                                      myType,
++                                      "CREATE FUNCTION %s (values " + myType + ") " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS " + myType + " " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
++    }
++}


[15/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
index 0000000,d3050a5..af3c894
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@@ -1,0 -1,504 +1,428 @@@
+ /*
+  * 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.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.util.Arrays;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ import java.util.UUID;
+ 
+ import org.junit.Assert;
 -import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
 -import com.datastax.driver.core.DataType;
 -import com.datastax.driver.core.TupleType;
 -import com.datastax.driver.core.TupleValue;
+ import org.apache.cassandra.config.DatabaseDescriptor;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
 -import org.apache.cassandra.transport.Server;
+ import org.apache.cassandra.utils.UUIDGen;
+ 
+ public class UFScriptTest extends CQLTester
+ {
 -    @BeforeClass
 -    public static void setUp()
 -    {
 -        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
 -    }
++    // Just JavaScript UDFs to check how UDF - especially security/class-loading/sandboxing stuff -
++    // behaves, if no Java UDF has been executed before.
++
++    // Do not add any other test here - especially none using Java UDFs
+ 
+     @Test
+     public void testJavascriptSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                        "CREATE FUNCTION %s( lst list<double> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS list<double> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'lst;';");
+         String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                        "CREATE FUNCTION %s( st set<text> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS set<text> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'st;';");
+         String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                        "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS map<int, boolean> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'mp;';");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavascriptTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
 -    public void testJavascriptTupleTypeCollection() throws Throwable
 -    {
 -        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
 -        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
 -
 -        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup;$$;");
 -        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS double " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getDouble(0);$$;");
 -        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS list<double> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
 -        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS set<text> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
 -        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS map<int, boolean> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
 -
 -        List<Double> list = Arrays.asList(1d, 2d, 3d);
 -        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
 -        Map<Integer, Boolean> map = new TreeMap<>();
 -        map.put(1, true);
 -        map.put(2, false);
 -        map.put(3, true);
 -
 -        Object t = tuple(1d, list, set, map);
 -
 -        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
 -
 -        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
 -                   row(t));
 -        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
 -                   row(1d));
 -        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
 -                   row(list));
 -        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
 -                   row(set));
 -        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
 -                   row(map));
 -
 -        // same test - but via native protocol
 -        TupleType tType = TupleType.of(DataType.cdouble(),
 -                                       DataType.list(DataType.cdouble()),
 -                                       DataType.set(DataType.text()),
 -                                       DataType.map(DataType.cint(), DataType.cboolean()));
 -        TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
 -        {
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
 -                          row(tup));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
 -                          row(1d));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
 -                          row(list));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
 -                          row(set));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
 -                          row(map));
 -        }
 -    }
 -
 -    @Test
+     public void testJavascriptUserType() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS " + type + " " +
++                                      "RETURNS " + type + ' ' +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt;$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt3 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getInt(\"i\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+     }
+ 
+     @Test
+     public void testJavascriptUTCollections() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "        lst.get(1).getString(\"txt\");$$;");
+         createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        st.iterator().next().getString(\"txt\");$$;");
+         createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 // list<frozen<UDT>>
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 // set<frozen<UDT>>
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 // map<int, frozen<UDT>>
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                    row("three"));
+         assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                    row("two"));
+ 
+         String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+         assertRows(execute(cqlSelect),
+                    row("three", "one", "two"));
+ 
+         // same test - but via native protocol
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, cqlSelect),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testJavascriptFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("javascript", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavascriptBadReturnType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '\"string\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ClassCastException
+         assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavascriptThrow() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'throw \"fool\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ScriptException
+         assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
 -    public void testJavascriptCompileFailure() throws Throwable
 -    {
 -        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
 -                             "RETURNS NULL ON NULL INPUT " +
 -                             "RETURNS double " +
 -                             "LANGUAGE javascript\n" +
 -                             "AS 'foo bar';");
 -    }
 -
 -    @Test
 -    public void testScriptInvalidLanguage() throws Throwable
 -    {
 -        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
 -                             "RETURNS NULL ON NULL INPUT " +
 -                             "RETURNS double " +
 -                             "LANGUAGE artificial_intelligence\n" +
 -                             "AS 'question for 42?';");
 -    }
 -
 -    @Test
+     public void testScriptReturnTypeCasting() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+ 
+         Object[][] variations = {
+         new Object[]    {   "true",     "boolean",  true    },
+         new Object[]    {   "false",    "boolean",  false   },
+         new Object[]    {   "100",      "tinyint",  (byte)100 },
+         new Object[]    {   "100.",     "tinyint",  (byte)100 },
+         new Object[]    {   "100",      "smallint", (short)100 },
+         new Object[]    {   "100.",     "smallint", (short)100 },
+         new Object[]    {   "100",      "int",      100     },
+         new Object[]    {   "100.",     "int",      100     },
+         new Object[]    {   "100",      "double",   100d    },
+         new Object[]    {   "100.",     "double",   100d    },
+         new Object[]    {   "100",      "bigint",   100L    },
+         new Object[]    {   "100.",     "bigint",   100L    },
+         new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+         new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+         new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+         new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object functionBody = variation[0];
+             Object returnType = variation[1];
+             Object expectedResult = variation[2];
+ 
+             String fName = createFunction(KEYSPACE, "double",
+                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " +returnType + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS '" + functionBody + ";';");
+             assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                        row(1, 1d, expectedResult));
+         }
+     }
+ 
+     @Test
+     public void testScriptParamReturnTypes() throws Throwable
+     {
+         UUID ruuid = UUID.randomUUID();
+         UUID tuuid = UUIDGen.getTimeUUID();
+ 
+         createTable("CREATE TABLE %s (key int primary key, " +
+                     "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                     "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+         execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                 (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+ 
+         Object[][] variations = {
+         new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+         new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+         new Object[] {  "int",      "ival",     1,                      2  },
+         new Object[] {  "bigint",   "lval",     1L,                     2L  },
+         new Object[] {  "float",    "fval",     1f,                     2f  },
+         new Object[] {  "double",   "dval",     1d,                     2d  },
+         new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+         new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+         new Object[] {  "time",     "timval",   1L,                     2L  },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val+1;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+ 
+         variations = new Object[][] {
+         new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+         new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+         new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+         new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+     }
++
++    @Test
++    public void testJavascriptDisabled() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, val double)");
++
++        DatabaseDescriptor.enableScriptedUserDefinedFunctions(false);
++        try
++        {
++            assertInvalid("double",
++                          "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".assertNotEnabled(val double) " +
++                          "RETURNS NULL ON NULL INPUT " +
++                          "RETURNS double " +
++                          "LANGUAGE javascript\n" +
++                          "AS 'Math.sin(val);';");
++        }
++        finally
++        {
++            DatabaseDescriptor.enableScriptedUserDefinedFunctions(true);
++        }
++    }
++
++    @Test
++    public void testJavascriptCompileFailure() throws Throwable
++    {
++        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
++                             "RETURNS NULL ON NULL INPUT " +
++                             "RETURNS double " +
++                             "LANGUAGE javascript\n" +
++                             "AS 'foo bar';");
++    }
++
++    @Test
++    public void testScriptInvalidLanguage() throws Throwable
++    {
++        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
++                             "RETURNS NULL ON NULL INPUT " +
++                             "RETURNS double " +
++                             "LANGUAGE artificial_intelligence\n" +
++                             "AS 'question for 42?';");
++    }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
index 0000000,0000000..5c7ca2b
new file mode 100644
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
@@@ -1,0 -1,0 +1,258 @@@
++/*
++ * 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.security.AccessControlException;
++import java.util.List;
++
++import org.junit.Assert;
++import org.junit.Test;
++
++import org.apache.cassandra.config.Config;
++import org.apache.cassandra.config.DatabaseDescriptor;
++import org.apache.cassandra.cql3.CQLTester;
++import org.apache.cassandra.cql3.functions.UDHelper;
++import org.apache.cassandra.exceptions.FunctionExecutionException;
++import org.apache.cassandra.service.ClientWarn;
++
++public class UFSecurityTest extends CQLTester
++{
++    @Test
++    public void testSecurityPermissions() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, dval double)");
++        execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
++
++        // Java UDFs
++
++        try
++        {
++            String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                          "RETURNS NULL ON NULL INPUT " +
++                                          "RETURNS double " +
++                                          "LANGUAGE JAVA\n" +
++                                          "AS 'System.getProperty(\"foo.bar.baz\"); return 0d;';");
++            execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++            Assert.fail();
++        }
++        catch (FunctionExecutionException e)
++        {
++            assertAccessControlException("System.getProperty(\"foo.bar.baz\"); return 0d;", e);
++        }
++
++        String[][] typesAndSources =
++        {
++        {"", "try { Class.forName(\"" + UDHelper.class.getName() + "\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
++        {"sun.misc.Unsafe",         "sun.misc.Unsafe.getUnsafe(); return 0d;"},
++        {"",                        "try { Class.forName(\"sun.misc.Unsafe\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
++        {"java.nio.file.FileSystems", "try {" +
++                                      "     java.nio.file.FileSystems.getDefault(); return 0d;" +
++                                      "} catch (Exception t) {" +
++                                      "     throw new RuntimeException(t);" +
++                                      '}'},
++        {"java.nio.channels.FileChannel", "try {" +
++                                          "     java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")).close(); return 0d;" +
++                                          "} catch (Exception t) {" +
++                                          "     throw new RuntimeException(t);" +
++                                          '}'},
++        {"java.nio.channels.SocketChannel", "try {" +
++                                            "     java.nio.channels.SocketChannel.open().close(); return 0d;" +
++                                            "} catch (Exception t) {" +
++                                            "     throw new RuntimeException(t);" +
++                                            '}'},
++        {"java.io.FileInputStream", "try {" +
++                                    "     new java.io.FileInputStream(\"./foobar\").close(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.lang.Runtime",       "try {" +
++                                    "     java.lang.Runtime.getRuntime(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"org.apache.cassandra.service.StorageService",
++         "try {" +
++         "     org.apache.cassandra.service.StorageService v = org.apache.cassandra.service.StorageService.instance; v.isShutdown(); return 0d;" +
++         "} catch (Exception t) {" +
++         "     throw new RuntimeException(t);" +
++         '}'},
++        {"java.net.ServerSocket",   "try {" +
++                                    "     new java.net.ServerSocket().bind(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.io.FileOutputStream","try {" +
++                                    "     new java.io.FileOutputStream(\".foo\"); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.lang.Runtime",       "try {" +
++                                    "     java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'}
++        };
++
++        for (String[] typeAndSource : typesAndSources)
++        {
++            assertInvalidMessage(typeAndSource[0] + " cannot be resolved",
++                                 "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".invalid_class_access(val double) " +
++                                 "RETURNS NULL ON NULL INPUT " +
++                                 "RETURNS double " +
++                                 "LANGUAGE JAVA\n" +
++                                 "AS '" + typeAndSource[1] + "';");
++        }
++
++        // JavaScript UDFs
++
++        try
++        {
++            String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                          "RETURNS NULL ON NULL INPUT " +
++                                          "RETURNS double " +
++                                          "LANGUAGE javascript\n" +
++                                          "AS 'org.apache.cassandra.service.StorageService.instance.isShutdown(); 0;';");
++            execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++            Assert.fail("Javascript security check failed");
++        }
++        catch (FunctionExecutionException e)
++        {
++            assertAccessControlException("", e);
++        }
++
++        String[] javascript =
++        {
++        "java.lang.management.ManagmentFactory.getThreadMXBean(); 0;",
++        "new java.io.FileInputStream(\"/tmp/foo\"); 0;",
++        "new java.io.FileOutputStream(\"/tmp/foo\"); 0;",
++        "java.nio.file.FileSystems.getDefault().createFileExclusively(\"./foo_bar_baz\"); 0;",
++        "java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")); 0;",
++        "java.nio.channels.SocketChannel.open(); 0;",
++        "new java.net.ServerSocket().bind(null); 0;",
++        "var thread = new java.lang.Thread(); thread.start(); 0;",
++        "java.lang.System.getProperty(\"foo.bar.baz\"); 0;",
++        "java.lang.Class.forName(\"java.lang.System\"); 0;",
++        "java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); 0;",
++        "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
++        "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
++        // TODO these (ugly) calls are still possible - these can consume CPU (as one could do with an evil loop, too)
++//        "java.lang.Runtime.getRuntime().traceMethodCalls(true); 0;",
++//        "java.lang.Runtime.getRuntime().gc(); 0;",
++//        "java.lang.Runtime.getRuntime(); 0;",
++        };
++
++        for (String script : javascript)
++        {
++            try
++            {
++                String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                              "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                              "RETURNS NULL ON NULL INPUT " +
++                                              "RETURNS double " +
++                                              "LANGUAGE javascript\n" +
++                                              "AS '" + script + "';");
++                execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++                Assert.fail("Javascript security check failed: " + script);
++            }
++            catch (FunctionExecutionException e)
++            {
++                assertAccessControlException(script, e);
++            }
++        }
++    }
++
++    private static void assertAccessControlException(String script, FunctionExecutionException e)
++    {
++        for (Throwable t = e; t != null && t != t.getCause(); t = t.getCause())
++            if (t instanceof AccessControlException)
++                return;
++        Assert.fail("no AccessControlException for " + script + " (got " + e + ')');
++    }
++
++    @Test
++    public void testAmokUDF() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, dval double)");
++        execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
++
++        long udfWarnTimeout = DatabaseDescriptor.getUserDefinedFunctionWarnTimeout();
++        long udfFailTimeout = DatabaseDescriptor.getUserDefinedFunctionFailTimeout();
++        int maxTries = 5;
++        for (int i = 1; i <= maxTries; i++)
++        {
++            try
++            {
++                // short timeout
++                DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(10);
++                DatabaseDescriptor.setUserDefinedFunctionFailTimeout(250);
++                // don't kill the unit test... - default policy is "die"
++                DatabaseDescriptor.setUserFunctionTimeoutPolicy(Config.UserFunctionTimeoutPolicy.ignore);
++
++                ClientWarn.instance.captureWarnings();
++                String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                              "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                              "RETURNS NULL ON NULL INPUT " +
++                                              "RETURNS double " +
++                                              "LANGUAGE JAVA\n" +
++                                              "AS 'long t=System.currentTimeMillis()+110; while (t>System.currentTimeMillis()) { }; return 0d;'");
++                execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++                List<String> warnings = ClientWarn.instance.getWarnings();
++                Assert.assertNotNull(warnings);
++                Assert.assertFalse(warnings.isEmpty());
++                ClientWarn.instance.resetWarnings();
++
++                // Java UDF
++
++                fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                       "RETURNS NULL ON NULL INPUT " +
++                                       "RETURNS double " +
++                                       "LANGUAGE JAVA\n" +
++                                       "AS 'long t=System.currentTimeMillis()+500; while (t>System.currentTimeMillis()) { }; return 0d;';");
++                assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
++
++                // Javascript UDF
++
++                fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                       "RETURNS NULL ON NULL INPUT " +
++                                       "RETURNS double " +
++                                       "LANGUAGE JAVASCRIPT\n" +
++                                       "AS 'var t=java.lang.System.currentTimeMillis()+500; while (t>java.lang.System.currentTimeMillis()) { }; 0;';");
++                assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
++
++                return;
++            }
++            catch (Error | RuntimeException e)
++            {
++                if (i == maxTries)
++                    throw e;
++            }
++            finally
++            {
++                // reset to defaults
++                DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(udfWarnTimeout);
++                DatabaseDescriptor.setUserDefinedFunctionFailTimeout(udfFailTimeout);
++            }
++        }
++    }
++
++}


[12/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
Merge branch 'cassandra-2.2' into cassandra-3.0


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3aefe356
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3aefe356
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3aefe356

Branch: refs/heads/cassandra-3.X
Commit: 3aefe356545bcc2f5c4453e0d9d704bef339a008
Parents: 95d0b67 0b97c5d
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:08:35 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:08:35 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    |  797 +++++++++
 .../validation/entities/UFPureScriptTest.java   |  406 -----
 .../cql3/validation/entities/UFScriptTest.java  |  428 +++++
 .../validation/entities/UFSecurityTest.java     |  258 +++
 .../cql3/validation/entities/UFTest.java        | 1519 +-----------------
 .../cql3/validation/entities/UFTypesTest.java   |  549 +++++++
 6 files changed, 2033 insertions(+), 1924 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
index 0000000,caef808..15c8e18
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@@ -1,0 -1,1177 +1,797 @@@
+ /*
+  * 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.Arrays;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ 
+ import org.junit.Assert;
 -import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.DataType;
+ import com.datastax.driver.core.Row;
+ import com.datastax.driver.core.TupleType;
+ import com.datastax.driver.core.TupleValue;
+ import com.datastax.driver.core.UDTValue;
 -import org.apache.cassandra.config.DatabaseDescriptor;
++import org.apache.cassandra.config.Schema;
+ import org.apache.cassandra.cql3.CQL3Type;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.cql3.functions.Functions;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
+ import org.apache.cassandra.transport.Server;
 -import org.apache.cassandra.utils.ByteBufferUtil;
+ 
+ public class UFJavaTest extends CQLTester
+ {
 -    @BeforeClass
 -    public static void setUp()
 -    {
 -        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
 -    }
 -
 -
+     @Test
+     public void testJavaFunctionNoParameters() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = "\n  return 1L;\n";
+ 
+         String fName = createFunction(KEYSPACE, "",
+                                       "CREATE OR REPLACE FUNCTION %s() " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" +functionBody + "';");
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            KEYSPACE, parseFunctionName(fName).name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                    row(1, 1d, 1L),
+                    row(2, 2d, 1L),
+                    row(3, 3d, 1L)
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidBodies() throws Throwable
+     {
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+         }
+ 
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz;" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+         }
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidReturn() throws Throwable
+     {
+         assertInvalidMessage("system keyspace is not user-modifiable",
+                              "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE JAVA\n" +
+                              "AS 'return 1L;';");
+     }
+ 
+     @Test
+     public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val bigint)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return Double.valueOf(val);';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+         assertInvalidMessage("val cannot be passed as argument 0 of function",
+                              "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionCounter() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val counter)");
+ 
+         String fName = createFunction(KEYSPACE, "counter",
+                                       "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return val + 1;';");
+ 
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1L, 2L));
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+         execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 4L, 5L));
+         execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+     }
+ 
+     @Test
+     public void testJavaKeyspaceFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin( val );\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaRuntimeException() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  throw new RuntimeException(\"oh no!\");\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+ 
+         // function throws a RuntimeException which is wrapped by FunctionExecutionException
+         assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaDollarQuotedFunction() throws Throwable
+     {
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (input == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return \"'\"+Math.sin(input)+'\\\'';\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE FUNCTION %s( input double ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" + functionBody + "$$;");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+     }
+ 
+     @Test
+     public void testJavaSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return lst;$$;");
+         String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                      "CREATE FUNCTION %s( st set<text> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return st;$$;");
+         String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return mp;$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         // same test - but via native protocol
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavaTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavaTupleTypeCollection() throws Throwable
+     {
+         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+ 
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+ 
+         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + tupleTypeDef + ' ' +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup;$$;");
+         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       Double.valueOf(tup.getDouble(0));$$;");
+         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getList(1, Double.class);$$;");
+         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getSet(2, String.class);$$;");
+         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         Object t = tuple(1d, list, set, map);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                    row(1d));
+         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                    row(list));
+         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                    row(set));
+         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                    row(map));
+ 
 -        TupleType tType = TupleType.of(DataType.cdouble(),
 -                                       DataType.list(DataType.cdouble()),
 -                                       DataType.set(DataType.text()),
 -                                       DataType.map(DataType.cint(), DataType.cboolean()));
++        // same test - but via native protocol
++        // we use protocol V3 here to encode the expected version because the server
++        // always serializes Collections using V3 - see CollectionSerializer's
++        // serialize and deserialize methods.
++        TupleType tType = tupleTypeOf(Server.VERSION_3,
++                                      DataType.cdouble(),
++                                      DataType.list(DataType.cdouble()),
++                                      DataType.set(DataType.text()),
++                                      DataType.map(DataType.cint(), DataType.cboolean()));
+         TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                           row(tup));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                           row(1d));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                           row(list));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                           row(set));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                           row(map));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeWithUse() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             executeNet(version, "USE " + KEYSPACE);
+ 
+             executeNet(version,
+                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS " + type + " " +
+                        "LANGUAGE java " +
+                        "AS $$return " +
+                        "     udt;$$;");
+             try
+             {
+                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                 Assert.assertEquals(1, rowsNet.size());
+                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                 Assert.assertEquals("one", udtVal.getString("txt"));
+                 Assert.assertEquals(1, udtVal.getInt("i"));
+             }
+             finally
+             {
+                 executeNet(version, "DROP FUNCTION f_use1");
+             }
+         }
+     }
+ 
+     @Test
+     public void testJavaUserType() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt0 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + " " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt;$$;");
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+             Assert.assertEquals(1, rowsNet.size());
+             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+             Assert.assertEquals("one", udtVal.getString("txt"));
+             Assert.assertEquals(1, udtVal.getInt("i"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                           row("one"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                           row(1));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeRenameField() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return udt.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+ 
+         execute("ALTER TYPE " + type + " RENAME txt TO str");
+ 
+         assertInvalidMessage("txt is not a field defined in this UDT",
+                              "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+ 
+         execute("ALTER TYPE " + type + " RENAME str TO txt");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+     }
+ 
+     @Test
+     public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName1replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + ") " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS text " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt.getString(\"txt\");$$;");
+         String fName2replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS int " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS double " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS " + type + " " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt;$$;");
+ 
+         String fName1noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS text " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt.getString(\"txt\");$$;");
+         String fName2noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS int " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS double " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS " + type + " " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt;$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
+         // add field
+ 
+         execute("ALTER TYPE " + type + " ADD added double");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+ 
+         // note: type references of functions remain at the state _before_ the type mutation
+         // means we need to recreate the functions
+ 
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt.getString(\"txt\");$$;",
+                               fName1replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName1replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS int " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                               fName2replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName2replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS double " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                               fName3replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName3replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS %s " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt;$$;",
+                               fName4replace, type, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName4replace)).size());
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         // un-replaced functions will work since the user type has changed
+         // and the UDF has exchanged the user type reference
+ 
+         assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         execute("DROP FUNCTION " + fName1replace);
+         execute("DROP FUNCTION " + fName2replace);
+         execute("DROP FUNCTION " + fName3replace);
+         execute("DROP FUNCTION " + fName4replace);
+         execute("DROP FUNCTION " + fName1noReplace);
+         execute("DROP FUNCTION " + fName2noReplace);
+         execute("DROP FUNCTION " + fName3noReplace);
+         execute("DROP FUNCTION " + fName4noReplace);
+     }
+ 
+     @Test
+     public void testJavaUTCollections() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row("three", "one", "two"));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
 -    public void testFunctionWithFrozenSetType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<set<int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "set<int>",
 -                                             "CREATE FUNCTION %s (values set<int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "set<int>",
 -                                      "CREATE FUNCTION %s (values set<int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS set<int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenListType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<list<int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "list<int>",
 -                                             "CREATE FUNCTION %s (values list<int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "list<int>",
 -                                      "CREATE FUNCTION %s (values list<int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS list<int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenMapType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<map<int, int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "map<int, int>",
 -                                             "CREATE FUNCTION %s (values map<int, int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "map<int, int>",
 -                                      "CREATE FUNCTION %s (values map<int, int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS map<int, int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenTupleType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
 -        createIndex("CREATE INDEX ON %s (b)");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS text " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values.toString();';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<tuple<int, int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "tuple<int, int>",
 -                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS text " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'return values.toString();';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, "(null, null)"),
 -                   row(1, "(1, 2)"),
 -                   row(2, "(4, 5)"),
 -                   row(3, "(7, 8)"));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "tuple<int, int>",
 -                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS tuple<int, int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenUDType() throws Throwable
 -    {
 -        String myType = createType("CREATE TYPE %s (f int)");
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
 -        createIndex("CREATE INDEX ON %s (b)");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS text " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values.toString();';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<" + myType + "> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             myType,
 -                                             "CREATE FUNCTION %s (values " + myType + ") " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS text " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'return values.toString();';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, "{f:0}"),
 -                   row(1, "{f:1}"),
 -                   row(2, "{f:4}"),
 -                   row(3, "{f:7}"));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      myType,
 -                                      "CREATE FUNCTION %s (values " + myType + ") " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS " + myType + " " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
 -    }
 -
 -    @Test
 -    public void testEmptyString() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
 -        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
 -
 -        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return \"\";'");
 -
 -        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return \"\";'");
 -
 -        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return ByteBuffer.allocate(0);'");
 -
 -        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return ByteBuffer.allocate(0);'");
 -
 -        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return 0;'");
 -
 -        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return 0;'");
 -
 -        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
 -        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
 -        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
 -        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
 -    }
 -
 -    @Test
+     public void testAllNativeTypes() throws Throwable
+     {
+         StringBuilder sig = new StringBuilder();
+         StringBuilder args = new StringBuilder();
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
++            if (type == CQL3Type.Native.EMPTY)
++                continue;
++
+             if (sig.length() > 0)
+                 sig.append(',');
+             sig.append(type.toString());
+ 
+             if (args.length() > 0)
+                 args.append(',');
+             args.append("arg").append(type.toString()).append(' ').append(type.toString());
+         }
+         createFunction(KEYSPACE, sig.toString(),
+                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS int " +
+                        "LANGUAGE JAVA\n" +
+                        "AS 'return 0;'");
+ 
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
++            if (type == CQL3Type.Native.EMPTY)
++                continue;
++
+             createFunction(KEYSPACE_PER_TEST, type.toString(),
+                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                            "RETURNS NULL ON NULL INPUT " +
+                            "RETURNS int " +
+                            "LANGUAGE JAVA\n" +
+                            "AS 'return 0;'");
+         }
+     }
+ }


[13/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
index 0000000,0000000..de98748
new file mode 100644
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
@@@ -1,0 -1,0 +1,549 @@@
++/*
++ * 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.util.ArrayList;
++import java.util.Arrays;
++import java.util.Date;
++import java.util.List;
++import java.util.Map;
++import java.util.Set;
++import java.util.TreeMap;
++import java.util.TreeSet;
++import java.util.UUID;
++
++import org.junit.Assert;
++import org.junit.Test;
++
++import com.datastax.driver.core.Row;
++import org.apache.cassandra.cql3.CQLTester;
++import org.apache.cassandra.cql3.UntypedResultSet;
++import org.apache.cassandra.utils.UUIDGen;
++
++public class UFTypesTest extends CQLTester
++{
++
++    @Test
++    public void testComplexNullValues() throws Throwable
++    {
++        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
++
++        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
++                    "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
++
++        String fList = createFunction(KEYSPACE, "list<double>",
++                                      "CREATE FUNCTION %s( coll list<double> ) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS list<double> " +
++                                      "LANGUAGE java\n" +
++                                      "AS $$return coll;$$;");
++        String fSet = createFunction(KEYSPACE, "set<text>",
++                                     "CREATE FUNCTION %s( coll set<text> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS set<text> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return coll;$$;");
++        String fMap = createFunction(KEYSPACE, "map<int, boolean>",
++                                     "CREATE FUNCTION %s( coll map<int, boolean> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS map<int, boolean> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return coll;$$;");
++        String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
++                                     "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS tuple<double, text, int, boolean> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return val;$$;");
++        String fUdt = createFunction(KEYSPACE, type,
++                                     "CREATE FUNCTION %s( val " + type + " ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS " + type + " " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return val;$$;");
++        List<Double> list = Arrays.asList(1d, 2d, 3d);
++        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
++        Map<Integer, Boolean> map = new TreeMap<>();
++        map.put(1, true);
++        map.put(2, false);
++        map.put(3, true);
++        Object t = tuple(1d, "one", 42, false);
++
++        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
++        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
++
++        execute("SELECT " +
++                fList + "(lst), " +
++                fSet + "(st), " +
++                fMap + "(mp), " +
++                fTup + "(tup), " +
++                fUdt + "(udt) FROM %s WHERE key = 1");
++        UntypedResultSet.Row row = execute("SELECT " +
++                                           fList + "(lst) as l, " +
++                                           fSet + "(st) as s, " +
++                                           fMap + "(mp) as m, " +
++                                           fTup + "(tup) as t, " +
++                                           fUdt + "(udt) as u " +
++                                           "FROM %s WHERE key = 1").one();
++        Assert.assertNotNull(row.getBytes("l"));
++        Assert.assertNotNull(row.getBytes("s"));
++        Assert.assertNotNull(row.getBytes("m"));
++        Assert.assertNotNull(row.getBytes("t"));
++        Assert.assertNotNull(row.getBytes("u"));
++        row = execute("SELECT " +
++                      fList + "(lst) as l, " +
++                      fSet + "(st) as s, " +
++                      fMap + "(mp) as m, " +
++                      fTup + "(tup) as t, " +
++                      fUdt + "(udt) as u " +
++                      "FROM %s WHERE key = 2").one();
++        Assert.assertNull(row.getBytes("l"));
++        Assert.assertNull(row.getBytes("s"));
++        Assert.assertNull(row.getBytes("m"));
++        Assert.assertNull(row.getBytes("t"));
++        Assert.assertNull(row.getBytes("u"));
++
++        for (int version : PROTOCOL_VERSIONS)
++        {
++            Row r = executeNet(version, "SELECT " +
++                                        fList + "(lst) as l, " +
++                                        fSet + "(st) as s, " +
++                                        fMap + "(mp) as m, " +
++                                        fTup + "(tup) as t, " +
++                                        fUdt + "(udt) as u " +
++                                        "FROM %s WHERE key = 1").one();
++            Assert.assertNotNull(r.getBytesUnsafe("l"));
++            Assert.assertNotNull(r.getBytesUnsafe("s"));
++            Assert.assertNotNull(r.getBytesUnsafe("m"));
++            Assert.assertNotNull(r.getBytesUnsafe("t"));
++            Assert.assertNotNull(r.getBytesUnsafe("u"));
++            r = executeNet(version, "SELECT " +
++                                    fList + "(lst) as l, " +
++                                    fSet + "(st) as s, " +
++                                    fMap + "(mp) as m, " +
++                                    fTup + "(tup) as t, " +
++                                    fUdt + "(udt) as u " +
++                                    "FROM %s WHERE key = 2").one();
++            Assert.assertNull(r.getBytesUnsafe("l"));
++            Assert.assertNull(r.getBytesUnsafe("s"));
++            Assert.assertNull(r.getBytesUnsafe("m"));
++            Assert.assertNull(r.getBytesUnsafe("t"));
++            Assert.assertNull(r.getBytesUnsafe("u"));
++        }
++    }
++
++    private static class TypesTestDef
++    {
++        final String udfType;
++        final String tableType;
++        final String columnName;
++        final Object referenceValue;
++
++        String fCheckArgAndReturn;
++
++        String fCalledOnNull;
++        String fReturnsNullOnNull;
++
++        TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
++        {
++            this.udfType = udfType;
++            this.tableType = tableType;
++            this.columnName = columnName;
++            this.referenceValue = referenceValue;
++        }
++    }
++
++    @Test
++    public void testTypesWithAndWithoutNulls() throws Throwable
++    {
++        // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
++
++        String type = createType("CREATE TYPE %s (txt text, i int)");
++
++        TypesTestDef[] typeDefs =
++        {
++        //                udf type,            table type,                 column, reference value
++        new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
++        new TypesTestDef("date", "date", "dt", 12345),
++        new TypesTestDef("time", "time", "tim", 12345L),
++        new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
++        new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
++        new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
++        new TypesTestDef("smallint", "smallint", "si", (short) 43),
++        new TypesTestDef("int", "int", "i", 44),
++        new TypesTestDef("bigint", "bigint", "b", 45L),
++        new TypesTestDef("float", "float", "f", 46f),
++        new TypesTestDef("double", "double", "d", 47d),
++        new TypesTestDef("boolean", "boolean", "x", true),
++        new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
++        new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
++        //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
++        new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
++        };
++
++        String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
++        String insertDML = "INSERT INTO %s (key";
++        List<Object> values = new ArrayList<>();
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
++            insertDML += ", " + typeDef.columnName;
++            String typeName = typeDef.udfType;
++            typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
++                                                        typeName,
++                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                        "CALLED ON NULL INPUT " +
++                                                        "RETURNS " + typeName + ' ' +
++                                                        "LANGUAGE java\n" +
++                                                        "AS 'return val;';");
++            typeDef.fCalledOnNull = createFunction(KEYSPACE,
++                                                   typeName,
++                                                   "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                   "CALLED ON NULL INPUT " +
++                                                   "RETURNS text " +
++                                                   "LANGUAGE java\n" +
++                                                   "AS 'return \"called\";';");
++            typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
++                                                        typeName,
++                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                        "RETURNS NULL ON NULL INPUT " +
++                                                        "RETURNS text " +
++                                                        "LANGUAGE java\n" +
++                                                        "AS 'return \"called\";';");
++            values.add(typeDef.referenceValue);
++        }
++
++        createTableDDL += ')';
++        createTable(createTableDDL);
++
++        insertDML += ") VALUES (1";
++        for (TypesTestDef ignored : typeDefs)
++            insertDML += ", ?";
++        insertDML += ')';
++
++        execute(insertDML, values.toArray());
++
++        // second row with null values
++        for (int i = 0; i < values.size(); i++)
++            values.set(i, null);
++        execute(insertDML.replace('1', '2'), values.toArray());
++
++        // check argument input + return
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ typeDef.referenceValue }));
++        }
++
++        // check for CALLED ON NULL INPUT with non-null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for CALLED ON NULL INPUT with null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for RETURNS NULL ON NULL INPUT with non-null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for RETURNS NULL ON NULL INPUT with null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
++                       row(new Object[]{ null }));
++        }
++
++    }
++
++    @Test
++    public void testFunctionWithFrozenSetType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<set<int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "set<int>",
++                                             "CREATE FUNCTION %s (values set<int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "set<int>",
++                                      "CREATE FUNCTION %s (values set<int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS set<int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenListType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<list<int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "list<int>",
++                                             "CREATE FUNCTION %s (values list<int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "list<int>",
++                                      "CREATE FUNCTION %s (values list<int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS list<int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenMapType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<map<int, int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "map<int, int>",
++                                             "CREATE FUNCTION %s (values map<int, int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "map<int, int>",
++                                      "CREATE FUNCTION %s (values map<int, int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS map<int, int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenTupleType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
++        createIndex("CREATE INDEX ON %s (b)");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS text " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values.toString();';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<tuple<int, int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "tuple<int, int>",
++                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS text " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'return values.toString();';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
++
++        functionName = createFunction(KEYSPACE,
++                                      "tuple<int, int>",
++                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS tuple<int, int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenUDType() throws Throwable
++    {
++        String myType = createType("CREATE TYPE %s (f int)");
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
++        createIndex("CREATE INDEX ON %s (b)");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS text " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values.toString();';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<" + myType + "> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             myType,
++                                             "CREATE FUNCTION %s (values " + myType + ") " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS text " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'return values.toString();';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
++
++        functionName = createFunction(KEYSPACE,
++                                      myType,
++                                      "CREATE FUNCTION %s (values " + myType + ") " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS " + myType + " " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
++    }
++}


[02/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Posted by sn...@apache.org.
testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

patch by Robert Stupp; reviewed by Alex Petrov for CASSANDRA-12817


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/0b97c5d1
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/0b97c5d1
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/0b97c5d1

Branch: refs/heads/cassandra-2.2
Commit: 0b97c5d1f717be30a04c59c766465d9c62a4e9ee
Parents: 2e93398
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:06:55 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:06:55 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    | 1177 +++++++++++++
 .../cql3/validation/entities/UFScriptTest.java  |  504 ++++++
 .../cql3/validation/entities/UFTest.java        | 1608 +-----------------
 3 files changed, 1696 insertions(+), 1593 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
new file mode 100644
index 0000000..caef808
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@ -0,0 +1,1177 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import com.datastax.driver.core.UDTValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQL3Type;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.cql3.functions.Functions;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+public class UFJavaTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+
+    @Test
+    public void testJavaFunctionNoParameters() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = "\n  return 1L;\n";
+
+        String fName = createFunction(KEYSPACE, "",
+                                      "CREATE OR REPLACE FUNCTION %s() " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" +functionBody + "';");
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           KEYSPACE, parseFunctionName(fName).name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                   row(1, 1d, 1L),
+                   row(2, 2d, 1L),
+                   row(3, 3d, 1L)
+        );
+    }
+
+    @Test
+    public void testJavaFunctionInvalidBodies() throws Throwable
+    {
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+        }
+
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz;" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+        }
+    }
+
+    @Test
+    public void testJavaFunctionInvalidReturn() throws Throwable
+    {
+        assertInvalidMessage("system keyspace is not user-modifiable",
+                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE JAVA\n" +
+                             "AS 'return 1L;';");
+    }
+
+    @Test
+    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val bigint)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return Double.valueOf(val);';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+        assertInvalidMessage("val cannot be passed as argument 0 of function",
+                             "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaFunctionCounter() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val counter)");
+
+        String fName = createFunction(KEYSPACE, "counter",
+                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return val + 1;';");
+
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1L, 2L));
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 4L, 5L));
+        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+    }
+
+    @Test
+    public void testJavaKeyspaceFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin( val );\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaRuntimeException() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  throw new RuntimeException(\"oh no!\");\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+
+        // function throws a RuntimeException which is wrapped by FunctionExecutionException
+        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaDollarQuotedFunction() throws Throwable
+    {
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (input == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE FUNCTION %s( input double ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$" + functionBody + "$$;");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+    }
+
+    @Test
+    public void testJavaSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                      "CREATE FUNCTION %s( lst list<double> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return lst;$$;");
+        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                     "CREATE FUNCTION %s( st set<text> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS set<text> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return st;$$;");
+        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS map<int, boolean> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return mp;$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavaTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavaTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + tupleTypeDef + ' ' +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup;$$;");
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       Double.valueOf(tup.getDouble(0));$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getList(1, Double.class);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getSet(2, String.class);$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeWithUse() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            executeNet(version, "USE " + KEYSPACE);
+
+            executeNet(version,
+                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS " + type + " " +
+                       "LANGUAGE java " +
+                       "AS $$return " +
+                       "     udt;$$;");
+            try
+            {
+                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                Assert.assertEquals(1, rowsNet.size());
+                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                Assert.assertEquals("one", udtVal.getString("txt"));
+                Assert.assertEquals(1, udtVal.getInt("i"));
+            }
+            finally
+            {
+                executeNet(version, "DROP FUNCTION f_use1");
+            }
+        }
+    }
+
+    @Test
+    public void testJavaUserType() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt0 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt;$$;");
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+            Assert.assertEquals(1, rowsNet.size());
+            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+            Assert.assertEquals("one", udtVal.getString("txt"));
+            Assert.assertEquals(1, udtVal.getInt("i"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                          row("one"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                          row(1));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeRenameField() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return udt.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+
+        execute("ALTER TYPE " + type + " RENAME txt TO str");
+
+        assertInvalidMessage("txt is not a field defined in this UDT",
+                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+
+        execute("ALTER TYPE " + type + " RENAME str TO txt");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+    }
+
+    @Test
+    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName1replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + ") " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt.getString(\"txt\");$$;");
+        String fName2replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS double " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS " + type + " " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt;$$;");
+
+        String fName1noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS text " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt.getString(\"txt\");$$;");
+        String fName2noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS int " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS double " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS " + type + " " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt;$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        // add field
+
+        execute("ALTER TYPE " + type + " ADD added double");
+
+        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+
+        // note: type references of functions remain at the state _before_ the type mutation
+        // means we need to recreate the functions
+
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt.getString(\"txt\");$$;",
+                              fName1replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                              fName2replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                              fName3replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS %s " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt;$$;",
+                              fName4replace, type, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        // un-replaced functions will work since the user type has changed
+        // and the UDF has exchanged the user type reference
+
+        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        execute("DROP FUNCTION " + fName1replace);
+        execute("DROP FUNCTION " + fName2replace);
+        execute("DROP FUNCTION " + fName3replace);
+        execute("DROP FUNCTION " + fName4replace);
+        execute("DROP FUNCTION " + fName1noReplace);
+        execute("DROP FUNCTION " + fName2noReplace);
+        execute("DROP FUNCTION " + fName3noReplace);
+        execute("DROP FUNCTION " + fName4noReplace);
+    }
+
+    @Test
+    public void testJavaUTCollections() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row("three", "one", "two"));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testFunctionWithFrozenSetType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<set<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "set<int>",
+                                             "CREATE FUNCTION %s (values set<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "set<int>",
+                                      "CREATE FUNCTION %s (values set<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS set<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenListType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<list<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "list<int>",
+                                             "CREATE FUNCTION %s (values list<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "list<int>",
+                                      "CREATE FUNCTION %s (values list<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS list<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenMapType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<map<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "map<int, int>",
+                                             "CREATE FUNCTION %s (values map<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "map<int, int>",
+                                      "CREATE FUNCTION %s (values map<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS map<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<tuple<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "tuple<int, int>",
+                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "(null, null)"),
+                   row(1, "(1, 2)"),
+                   row(2, "(4, 5)"),
+                   row(3, "(7, 8)"));
+
+        functionName = createFunction(KEYSPACE,
+                                      "tuple<int, int>",
+                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS tuple<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenUDType() throws Throwable
+    {
+        String myType = createType("CREATE TYPE %s (f int)");
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<" + myType + "> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             myType,
+                                             "CREATE FUNCTION %s (values " + myType + ") " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "{f:0}"),
+                   row(1, "{f:1}"),
+                   row(2, "{f:4}"),
+                   row(3, "{f:7}"));
+
+        functionName = createFunction(KEYSPACE,
+                                      myType,
+                                      "CREATE FUNCTION %s (values " + myType + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + myType + " " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
+    }
+
+    @Test
+    public void testEmptyString() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
+        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
+
+        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
+        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
+    }
+
+    @Test
+    public void testAllNativeTypes() throws Throwable
+    {
+        StringBuilder sig = new StringBuilder();
+        StringBuilder args = new StringBuilder();
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            if (sig.length() > 0)
+                sig.append(',');
+            sig.append(type.toString());
+
+            if (args.length() > 0)
+                args.append(',');
+            args.append("arg").append(type.toString()).append(' ').append(type.toString());
+        }
+        createFunction(KEYSPACE, sig.toString(),
+                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS int " +
+                       "LANGUAGE JAVA\n" +
+                       "AS 'return 0;'");
+
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            createFunction(KEYSPACE_PER_TEST, type.toString(),
+                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                           "RETURNS NULL ON NULL INPUT " +
+                           "RETURNS int " +
+                           "LANGUAGE JAVA\n" +
+                           "AS 'return 0;'");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
new file mode 100644
index 0000000..d3050a5
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@ -0,0 +1,504 @@
+/*
+ * 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.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.UUIDGen;
+
+public class UFScriptTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+    @Test
+    public void testJavascriptSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'lst;';");
+        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                       "CREATE FUNCTION %s( st set<text> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'st;';");
+        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                       "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'mp;';");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavascriptTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavascriptTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup;$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getDouble(0);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
+        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        // same test - but via native protocol
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavascriptUserType() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt;$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt3 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getInt(\"i\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+    }
+
+    @Test
+    public void testJavascriptUTCollections() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "        lst.get(1).getString(\"txt\");$$;");
+        createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        st.iterator().next().getString(\"txt\");$$;");
+        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                // list<frozen<UDT>>
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                // set<frozen<UDT>>
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                // map<int, frozen<UDT>>
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                   row("three"));
+        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                   row("two"));
+
+        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+        assertRows(execute(cqlSelect),
+                   row("three", "one", "two"));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, cqlSelect),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testJavascriptFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("javascript", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavascriptBadReturnType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '\"string\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ClassCastException
+        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptThrow() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS 'throw \"fool\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ScriptException
+        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptCompileFailure() throws Throwable
+    {
+        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE javascript\n" +
+                             "AS 'foo bar';");
+    }
+
+    @Test
+    public void testScriptInvalidLanguage() throws Throwable
+    {
+        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE artificial_intelligence\n" +
+                             "AS 'question for 42?';");
+    }
+
+    @Test
+    public void testScriptReturnTypeCasting() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+
+        Object[][] variations = {
+        new Object[]    {   "true",     "boolean",  true    },
+        new Object[]    {   "false",    "boolean",  false   },
+        new Object[]    {   "100",      "tinyint",  (byte)100 },
+        new Object[]    {   "100.",     "tinyint",  (byte)100 },
+        new Object[]    {   "100",      "smallint", (short)100 },
+        new Object[]    {   "100.",     "smallint", (short)100 },
+        new Object[]    {   "100",      "int",      100     },
+        new Object[]    {   "100.",     "int",      100     },
+        new Object[]    {   "100",      "double",   100d    },
+        new Object[]    {   "100.",     "double",   100d    },
+        new Object[]    {   "100",      "bigint",   100L    },
+        new Object[]    {   "100.",     "bigint",   100L    },
+        new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+        new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+        new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+        new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object functionBody = variation[0];
+            Object returnType = variation[1];
+            Object expectedResult = variation[2];
+
+            String fName = createFunction(KEYSPACE, "double",
+                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " +returnType + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS '" + functionBody + ";';");
+            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                       row(1, 1d, expectedResult));
+        }
+    }
+
+    @Test
+    public void testScriptParamReturnTypes() throws Throwable
+    {
+        UUID ruuid = UUID.randomUUID();
+        UUID tuuid = UUIDGen.getTimeUUID();
+
+        createTable("CREATE TABLE %s (key int primary key, " +
+                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+
+        Object[][] variations = {
+        new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+        new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+        new Object[] {  "int",      "ival",     1,                      2  },
+        new Object[] {  "bigint",   "lval",     1L,                     2L  },
+        new Object[] {  "float",    "fval",     1f,                     2f  },
+        new Object[] {  "double",   "dval",     1d,                     2d  },
+        new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+        new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+        new Object[] {  "time",     "timval",   1L,                     2L  },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val+1;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+
+        variations = new Object[][] {
+        new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+        new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+        new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+        new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+    }
+}


[10/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index c52e178,d4d2a10..8a743ea
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@@ -17,44 -17,37 +17,29 @@@
   */
  package org.apache.cassandra.cql3.validation.entities;
  
 +import java.nio.ByteBuffer;
  import java.util.ArrayList;
--import java.util.Arrays;
  import java.util.Date;
  import java.util.List;
--import java.util.Map;
--import java.util.Set;
--import java.util.TreeMap;
--import java.util.TreeSet;
--import java.util.UUID;
- import java.security.AccessControlException;
  
  import org.junit.Assert;
 -import org.junit.BeforeClass;
  import org.junit.Test;
  
- import com.datastax.driver.core.*;
 -import com.datastax.driver.core.Row;
  import com.datastax.driver.core.exceptions.InvalidQueryException;
--import org.apache.cassandra.config.DatabaseDescriptor;
 +import org.apache.cassandra.config.Schema;
- import org.apache.cassandra.cql3.CQL3Type;
  import org.apache.cassandra.cql3.CQLTester;
  import org.apache.cassandra.cql3.QueryProcessor;
  import org.apache.cassandra.cql3.UntypedResultSet;
- import org.apache.cassandra.config.Config;
  import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.cql3.functions.Functions;
  import org.apache.cassandra.cql3.functions.UDFunction;
- import org.apache.cassandra.cql3.functions.UDHelper;
  import org.apache.cassandra.db.marshal.CollectionType;
- import org.apache.cassandra.exceptions.FunctionExecutionException;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
  import org.apache.cassandra.exceptions.InvalidRequestException;
 +import org.apache.cassandra.schema.KeyspaceMetadata;
  import org.apache.cassandra.service.ClientState;
- import org.apache.cassandra.service.ClientWarn;
  import org.apache.cassandra.transport.Event;
  import org.apache.cassandra.transport.Server;
  import org.apache.cassandra.transport.messages.ResultMessage;
 -import org.apache.cassandra.utils.UUIDGen;
 +import org.apache.cassandra.utils.ByteBufferUtil;
- import org.apache.cassandra.utils.UUIDGen;
  
  public class UFTest extends CQLTester
  {
@@@ -1017,320 -724,115 +710,6 @@@
      }
  
      @Test
--    public void testComplexNullValues() throws Throwable
--    {
--        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
--
--        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
--                    "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
--
--        String fList = createFunction(KEYSPACE, "list<double>",
--                                      "CREATE FUNCTION %s( coll list<double> ) " +
--                                      "CALLED ON NULL INPUT " +
--                                      "RETURNS list<double> " +
--                                      "LANGUAGE java\n" +
--                                      "AS $$return coll;$$;");
--        String fSet = createFunction(KEYSPACE, "set<text>",
--                                     "CREATE FUNCTION %s( coll set<text> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS set<text> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return coll;$$;");
--        String fMap = createFunction(KEYSPACE, "map<int, boolean>",
--                                     "CREATE FUNCTION %s( coll map<int, boolean> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS map<int, boolean> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return coll;$$;");
--        String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
--                                     "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS tuple<double, text, int, boolean> " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return val;$$;");
--        String fUdt = createFunction(KEYSPACE, type,
--                                     "CREATE FUNCTION %s( val " + type + " ) " +
--                                     "CALLED ON NULL INPUT " +
--                                     "RETURNS " + type + " " +
--                                     "LANGUAGE java\n" +
--                                     "AS $$return val;$$;");
--        List<Double> list = Arrays.asList(1d, 2d, 3d);
--        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
--        Map<Integer, Boolean> map = new TreeMap<>();
--        map.put(1, true);
--        map.put(2, false);
--        map.put(3, true);
--        Object t = tuple(1d, "one", 42, false);
--
--        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
--        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
--
--        execute("SELECT " +
--                fList + "(lst), " +
--                fSet + "(st), " +
--                fMap + "(mp), " +
--                fTup + "(tup), " +
--                fUdt + "(udt) FROM %s WHERE key = 1");
--        UntypedResultSet.Row row = execute("SELECT " +
--                                           fList + "(lst) as l, " +
--                                           fSet + "(st) as s, " +
--                                           fMap + "(mp) as m, " +
--                                           fTup + "(tup) as t, " +
--                                           fUdt + "(udt) as u " +
--                                           "FROM %s WHERE key = 1").one();
--        Assert.assertNotNull(row.getBytes("l"));
--        Assert.assertNotNull(row.getBytes("s"));
--        Assert.assertNotNull(row.getBytes("m"));
--        Assert.assertNotNull(row.getBytes("t"));
--        Assert.assertNotNull(row.getBytes("u"));
--        row = execute("SELECT " +
--                      fList + "(lst) as l, " +
--                      fSet + "(st) as s, " +
--                      fMap + "(mp) as m, " +
--                      fTup + "(tup) as t, " +
--                      fUdt + "(udt) as u " +
--                      "FROM %s WHERE key = 2").one();
--        Assert.assertNull(row.getBytes("l"));
--        Assert.assertNull(row.getBytes("s"));
--        Assert.assertNull(row.getBytes("m"));
--        Assert.assertNull(row.getBytes("t"));
--        Assert.assertNull(row.getBytes("u"));
--
-         for (int version : PROTOCOL_VERSIONS)
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
--        {
--            Row r = executeNet(version, "SELECT " +
--                                        fList + "(lst) as l, " +
--                                        fSet + "(st) as s, " +
--                                        fMap + "(mp) as m, " +
--                                        fTup + "(tup) as t, " +
--                                        fUdt + "(udt) as u " +
--                                        "FROM %s WHERE key = 1").one();
--            Assert.assertNotNull(r.getBytesUnsafe("l"));
--            Assert.assertNotNull(r.getBytesUnsafe("s"));
--            Assert.assertNotNull(r.getBytesUnsafe("m"));
--            Assert.assertNotNull(r.getBytesUnsafe("t"));
--            Assert.assertNotNull(r.getBytesUnsafe("u"));
--            r = executeNet(version, "SELECT " +
--                                    fList + "(lst) as l, " +
--                                    fSet + "(st) as s, " +
--                                    fMap + "(mp) as m, " +
--                                    fTup + "(tup) as t, " +
--                                    fUdt + "(udt) as u " +
--                                    "FROM %s WHERE key = 2").one();
--            Assert.assertNull(r.getBytesUnsafe("l"));
--            Assert.assertNull(r.getBytesUnsafe("s"));
--            Assert.assertNull(r.getBytesUnsafe("m"));
--            Assert.assertNull(r.getBytesUnsafe("t"));
--            Assert.assertNull(r.getBytesUnsafe("u"));
-         }
-     }
- 
-     @Test
-     public void testJavaTupleType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
- 
-         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
-                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS tuple<double, text, int, boolean> " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return tup;$$;");
- 
-         Object t = tuple(1d, "foo", 2, true);
- 
-         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
- 
-         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                    row(t));
- 
-         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                    row(t));
-     }
- 
-     @Test
-     public void testJavaTupleTypeCollection() throws Throwable
-     {
-         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
- 
-         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
- 
-         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "CALLED ON NULL INPUT " +
-                 "RETURNS " + tupleTypeDef + ' ' +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup;$$;");
-         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "CALLED ON NULL INPUT " +
-                 "RETURNS double " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       Double.valueOf(tup.getDouble(0));$$;");
-         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS list<double> " +
-                                       "LANGUAGE java\n" +
-                                       "AS $$return " +
-                                       "       tup.getList(1, Double.class);$$;");
-         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "RETURNS NULL ON NULL INPUT " +
-                 "RETURNS set<text> " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup.getSet(2, String.class);$$;");
-         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                 "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                 "RETURNS NULL ON NULL INPUT " +
-                 "RETURNS map<int, boolean> " +
-                 "LANGUAGE java\n" +
-                 "AS $$return " +
-                 "       tup.getMap(3, Integer.class, Boolean.class);$$;");
- 
-         List<Double> list = Arrays.asList(1d, 2d, 3d);
-         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-         Map<Integer, Boolean> map = new TreeMap<>();
-         map.put(1, true);
-         map.put(2, false);
-         map.put(3, true);
- 
-         Object t = tuple(1d, list, set, map);
- 
-         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
- 
-         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                    row(t));
-         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                    row(1d));
-         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                    row(list));
-         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                    row(set));
-         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                    row(map));
- 
-         // same test - but via native protocol
-         // we use protocol V3 here to encode the expected version because the server
-         // always serializes Collections using V3 - see CollectionSerializer's
-         // serialize and deserialize methods.
-         TupleType tType = tupleTypeOf(Server.VERSION_3,
-                                       DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-         TupleValue tup = tType.newValue(1d, list, set, map);
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                           row(tup));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                           row(1d));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                           row(list));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                           row(set));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                           row(map));
-         }
-     }
- 
-     @Test
-     public void testJavaUserTypeWithUse() throws Throwable
-     {
-         String type = createType("CREATE TYPE %s (txt text, i int)");
-         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
-         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
- 
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             executeNet(version, "USE " + KEYSPACE);
- 
-             executeNet(version,
-                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
-                        "RETURNS NULL ON NULL INPUT " +
-                        "RETURNS " + type + " " +
-                        "LANGUAGE java " +
-                        "AS $$return " +
-                        "     udt;$$;");
-             try
-             {
-                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
-                 Assert.assertEquals(1, rowsNet.size());
-                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-                 Assert.assertEquals("one", udtVal.getString("txt"));
-                 Assert.assertEquals(1, udtVal.getInt("i"));
-             }
-             finally
-             {
-                 executeNet(version, "DROP FUNCTION f_use1");
-             }
-         }
-     }
- 
-     @Test
-     public void testJavaUserType() throws Throwable
-     {
-         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
- 
-         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- 
-         String fUdt0 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + " ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS " + type + " " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     udt;$$;");
-         String fUdt1 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + ") " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS text " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     udt.getString(\"txt\");$$;");
-         String fUdt2 = createFunction(KEYSPACE, type,
-                                       "CREATE FUNCTION %s( udt " + type + ") " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS int " +
-                                       "LANGUAGE java " +
-                                       "AS $$return " +
-                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
- 
-         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
- 
-         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
-         Assert.assertEquals(1, rows.size());
-         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                    row("one"));
-         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                    row(1));
- 
-         for (int version : PROTOCOL_VERSIONS)
-         {
-             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
-             Assert.assertEquals(1, rowsNet.size());
-             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-             Assert.assertEquals("one", udtVal.getString("txt"));
-             Assert.assertEquals(1, udtVal.getInt("i"));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                           row("one"));
-             assertRowsNet(version,
-                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                           row(1));
--        }
--    }
--
--    @Test
      public void testUserTypeDrop() throws Throwable
      {
          String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
@@@ -1593,162 -880,140 +757,7 @@@
                               "AS '\"foo bar\";';");
      }
  
 -    private static class TypesTestDef
 -    {
 -        final String udfType;
 -        final String tableType;
 -        final String columnName;
 -        final Object referenceValue;
 -
 -        String fCheckArgAndReturn;
 -
 -        String fCalledOnNull;
 -        String fReturnsNullOnNull;
 -
 -        TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
 -        {
 -            this.udfType = udfType;
 -            this.tableType = tableType;
 -            this.columnName = columnName;
 -            this.referenceValue = referenceValue;
 -        }
 -    }
 -
 -    @Test
 -    public void testTypesWithAndWithoutNulls() throws Throwable
 -    {
 -        // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
 -
 -        String type = createType("CREATE TYPE %s (txt text, i int)");
 -
 -        TypesTestDef[] typeDefs =
 -        {
 -        //                udf type,            table type,                 column, reference value
 -        new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
 -        new TypesTestDef("date", "date", "dt", 12345),
 -        new TypesTestDef("time", "time", "tim", 12345L),
 -        new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
 -        new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
 -        new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
 -        new TypesTestDef("smallint", "smallint", "si", (short) 43),
 -        new TypesTestDef("int", "int", "i", 44),
 -        new TypesTestDef("bigint", "bigint", "b", 45L),
 -        new TypesTestDef("float", "float", "f", 46f),
 -        new TypesTestDef("double", "double", "d", 47d),
 -        new TypesTestDef("boolean", "boolean", "x", true),
 -        new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
 -        new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
 -        //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
 -        new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
 -        };
 -
 -        String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
 -        String insertDML = "INSERT INTO %s (key";
 -        List<Object> values = new ArrayList<>();
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
 -            insertDML += ", " + typeDef.columnName;
 -            String typeName = typeDef.udfType;
 -            typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
 -                                                        typeName,
 -                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                        "CALLED ON NULL INPUT " +
 -                                                        "RETURNS " + typeName + ' ' +
 -                                                        "LANGUAGE java\n" +
 -                                                        "AS 'return val;';");
 -            typeDef.fCalledOnNull = createFunction(KEYSPACE,
 -                                                   typeName,
 -                                                   "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                   "CALLED ON NULL INPUT " +
 -                                                   "RETURNS text " +
 -                                                   "LANGUAGE java\n" +
 -                                                   "AS 'return \"called\";';");
 -            typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
 -                                                        typeName,
 -                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
 -                                                        "RETURNS NULL ON NULL INPUT " +
 -                                                        "RETURNS text " +
 -                                                        "LANGUAGE java\n" +
 -                                                        "AS 'return \"called\";';");
 -            values.add(typeDef.referenceValue);
 -        }
 -
 -        createTableDDL += ')';
 -        createTable(createTableDDL);
 -
 -        insertDML += ") VALUES (1";
 -        for (TypesTestDef ignored : typeDefs)
 -            insertDML += ", ?";
 -        insertDML += ')';
 -
 -        execute(insertDML, values.toArray());
 -
 -        // second row with null values
 -        for (int i = 0; i < values.size(); i++)
 -            values.set(i, null);
 -        execute(insertDML.replace('1', '2'), values.toArray());
 -
 -        // check argument input + return
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ typeDef.referenceValue }));
 -        }
 -
 -        // check for CALLED ON NULL INPUT with non-null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for CALLED ON NULL INPUT with null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for RETURNS NULL ON NULL INPUT with non-null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
 -                       row(new Object[]{ "called" }));
 -        }
 -
 -        // check for RETURNS NULL ON NULL INPUT with null arguments
 -        for (TypesTestDef typeDef : typeDefs)
 -        {
 -            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
 -                       row(new Object[]{ null }));
 -        }
 -
 -    }
 -
      @Test
-     public void testJavascriptCompileFailure() throws Throwable
-     {
-         assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE javascript\n" +
-                              "AS 'foo bar';");
-     }
- 
-     @Test
-     public void testScriptInvalidLanguage() throws Throwable
-     {
-         assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE artificial_intelligence\n" +
-                              "AS 'question for 42?';");
-     }
- 
-     static class TypesTestDef
-     {
-         final String udfType;
-         final String tableType;
-         final String columnName;
-         final Object referenceValue;
- 
-         String fCheckArgAndReturn;
- 
-         String fCalledOnNull;
-         String fReturnsNullOnNull;
- 
-         TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
-         {
-             this.udfType = udfType;
-             this.tableType = tableType;
-             this.columnName = columnName;
-             this.referenceValue = referenceValue;
-         }
-     }
- 
-     @Test
-     public void testTypesWithAndWithoutNulls() throws Throwable
-     {
-         // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
- 
-         String type = createType("CREATE TYPE %s (txt text, i int)");
- 
-         TypesTestDef[] typeDefs =
-         {
-         //                udf type,            table type,                 column, reference value
-         new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
-         new TypesTestDef("date", "date", "dt", 12345),
-         new TypesTestDef("time", "time", "tim", 12345L),
-         new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
-         new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
-         new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
-         new TypesTestDef("smallint", "smallint", "si", (short) 43),
-         new TypesTestDef("int", "int", "i", 44),
-         new TypesTestDef("bigint", "bigint", "b", 45L),
-         new TypesTestDef("float", "float", "f", 46f),
-         new TypesTestDef("double", "double", "d", 47d),
-         new TypesTestDef("boolean", "boolean", "x", true),
-         new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
-         new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
-         //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
-         new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
-         };
- 
-         String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
-         String insertDML = "INSERT INTO %s (key";
-         List<Object> values = new ArrayList<>();
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
-             insertDML += ", " + typeDef.columnName;
-             String typeName = typeDef.udfType;
-             typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
-                                                         typeName,
-                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                         "CALLED ON NULL INPUT " +
-                                                         "RETURNS " + typeName + ' ' +
-                                                         "LANGUAGE java\n" +
-                                                         "AS 'return val;';");
-             typeDef.fCalledOnNull = createFunction(KEYSPACE,
-                                                    typeName,
-                                                    "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                    "CALLED ON NULL INPUT " +
-                                                    "RETURNS text " +
-                                                    "LANGUAGE java\n" +
-                                                    "AS 'return \"called\";';");
-             typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
-                                                         typeName,
-                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
-                                                         "RETURNS NULL ON NULL INPUT " +
-                                                         "RETURNS text " +
-                                                         "LANGUAGE java\n" +
-                                                         "AS 'return \"called\";';");
-             values.add(typeDef.referenceValue);
-         }
- 
-         createTableDDL += ')';
-         createTable(createTableDDL);
- 
-         insertDML += ") VALUES (1";
-         for (TypesTestDef ignored : typeDefs)
-             insertDML += ", ?";
-         insertDML += ')';
- 
-         execute(insertDML, values.toArray());
- 
-         // second row with null values
-         for (int i = 0; i < values.size(); i++)
-             values.set(i, null);
-         execute(insertDML.replace('1', '2'), values.toArray());
- 
-         // check argument input + return
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ typeDef.referenceValue }));
-         }
- 
-         // check for CALLED ON NULL INPUT with non-null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for CALLED ON NULL INPUT with null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for RETURNS NULL ON NULL INPUT with non-null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
-                        row(new Object[]{ "called" }));
-         }
- 
-         // check for RETURNS NULL ON NULL INPUT with null arguments
-         for (TypesTestDef typeDef : typeDefs)
-         {
-             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
-                        row(new Object[]{ null }));
-         }
- 
-     }
- 
-     @Test
      public void testReplaceAllowNulls() throws Throwable
      {
          String fNulls = createFunction(KEYSPACE,
@@@ -1851,638 -1108,4 +860,112 @@@
              }
          }
      }
-     @Test
-     public void testFunctionWithFrozenSetType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<set<int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "set<int>",
-                                              "CREATE FUNCTION %s (values set<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "set<int>",
-                                              "CREATE FUNCTION %s (values set<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS set<int> " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenListType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<list<int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "list<int>",
-                                              "CREATE FUNCTION %s (values list<int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "list<int>",
-                                       "CREATE FUNCTION %s (values list<int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS list<int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenMapType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
-         createIndex("CREATE INDEX ON %s (FULL(b))");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<map<int, int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "map<int, int>",
-                                              "CREATE FUNCTION %s (values map<int, int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "map<int, int>",
-                                       "CREATE FUNCTION %s (values map<int, int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS map<int, int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenTupleType() throws Throwable
-     {
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
-         createIndex("CREATE INDEX ON %s (b)");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
-         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values.toString();';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<tuple<int, int>> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              "tuple<int, int>",
-                                              "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values.toString();';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
- 
-         functionName = createFunction(KEYSPACE,
-                                       "tuple<int, int>",
-                                       "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS tuple<int, int> " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
-     }
- 
-     @Test
-     public void testFunctionWithFrozenUDType() throws Throwable
-     {
-         String myType = createType("CREATE TYPE %s (f int)");
-         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-         createIndex("CREATE INDEX ON %s (b)");
- 
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
-         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values.toString();';");
- 
-         assertInvalidMessage("The function return type should not be frozen",
-                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS frozen<" + myType + "> " +
-                              "LANGUAGE java\n" +
-                              "AS 'return values;';");
- 
-         String functionName = createFunction(KEYSPACE,
-                                              myType,
-                                              "CREATE FUNCTION %s (values " + myType + ") " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS 'return values.toString();';");
- 
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
-         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
- 
-         functionName = createFunction(KEYSPACE,
-                                       myType,
-                                       "CREATE FUNCTION %s (values " + myType + ") " +
-                                       "CALLED ON NULL INPUT " +
-                                       "RETURNS " + myType + " " +
-                                       "LANGUAGE java\n" +
-                                       "AS 'return values;';");
- 
-         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
-                    row(1));
- 
-         assertInvalidMessage("The function arguments should not be frozen",
-                              "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
-     }
 +
 +    @Test
 +    public void testEmptyString() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
 +        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
 +
 +        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return \"\";'");
 +
 +        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
 +                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS text " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return \"\";'");
 +
 +        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return ByteBuffer.allocate(0);'");
 +
 +        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
 +                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS blob " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return ByteBuffer.allocate(0);'");
 +
 +        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "CALLED ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return 0;'");
 +
 +        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return val;'");
 +
 +        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
 +                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 +                                         "RETURNS NULL ON NULL INPUT " +
 +                                         "RETURNS int " +
 +                                         "LANGUAGE JAVA\n" +
 +                                         "AS 'return 0;'");
 +
 +        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
 +        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 +        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
 +        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{ null }));
 +    }
- 
-     @Test
-     public void testAllNativeTypes() throws Throwable
-     {
-         StringBuilder sig = new StringBuilder();
-         StringBuilder args = new StringBuilder();
-         for (CQL3Type.Native type : CQL3Type.Native.values())
-         {
-             if (type == CQL3Type.Native.EMPTY)
-                 continue;
- 
-             if (sig.length() > 0)
-                 sig.append(',');
-             sig.append(type.toString());
- 
-             if (args.length() > 0)
-                 args.append(',');
-             args.append("arg").append(type.toString()).append(' ').append(type.toString());
-         }
-         createFunction(KEYSPACE, sig.toString(),
-                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
-                        "RETURNS NULL ON NULL INPUT " +
-                        "RETURNS int " +
-                        "LANGUAGE JAVA\n" +
-                        "AS 'return 0;'");
- 
-         for (CQL3Type.Native type : CQL3Type.Native.values())
-         {
-             if (type == CQL3Type.Native.EMPTY)
-                 continue;
- 
-             createFunction(KEYSPACE_PER_TEST, type.toString(),
-                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
-                            "RETURNS NULL ON NULL INPUT " +
-                            "RETURNS int " +
-                            "LANGUAGE JAVA\n" +
-                            "AS 'return 0;'");
-         }
-     }
- 
-     @Test
-     public void testSecurityPermissions() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, dval double)");
-         execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
- 
-         // Java UDFs
- 
-         try
-         {
-             String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                           "RETURNS NULL ON NULL INPUT " +
-                                           "RETURNS double " +
-                                           "LANGUAGE JAVA\n" +
-                                           "AS 'System.getProperty(\"foo.bar.baz\"); return 0d;';");
-             execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-             Assert.fail();
-         }
-         catch (FunctionExecutionException e)
-         {
-             assertAccessControlException("System.getProperty(\"foo.bar.baz\"); return 0d;", e);
-         }
- 
-         String[][] typesAndSources =
-         {
-         {"",                        "try { Class.forName(\"" + UDHelper.class.getName() + "\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
-         {"sun.misc.Unsafe",         "sun.misc.Unsafe.getUnsafe(); return 0d;"},
-         {"",                        "try { Class.forName(\"sun.misc.Unsafe\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
-         {"java.nio.file.FileSystems", "try {" +
-                                     "     java.nio.file.FileSystems.getDefault(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.nio.channels.FileChannel", "try {" +
-                                     "     java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")).close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.nio.channels.SocketChannel", "try {" +
-                                     "     java.nio.channels.SocketChannel.open().close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.io.FileInputStream", "try {" +
-                                     "     new java.io.FileInputStream(\"./foobar\").close(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.lang.Runtime",       "try {" +
-                                     "     java.lang.Runtime.getRuntime(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"org.apache.cassandra.service.StorageService",
-                                     "try {" +
-                                     "     org.apache.cassandra.service.StorageService v = org.apache.cassandra.service.StorageService.instance; v.isShutdown(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.net.ServerSocket",   "try {" +
-                                     "     new java.net.ServerSocket().bind(); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.io.FileOutputStream","try {" +
-                                     "     new java.io.FileOutputStream(\".foo\"); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'},
-         {"java.lang.Runtime",       "try {" +
-                                     "     java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); return 0d;" +
-                                     "} catch (Exception t) {" +
-                                     "     throw new RuntimeException(t);" +
-                                     '}'}
-         };
- 
-         for (String[] typeAndSource : typesAndSources)
-         {
-             assertInvalidMessage(typeAndSource[0] + " cannot be resolved",
-                                  "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".invalid_class_access(val double) " +
-                                  "RETURNS NULL ON NULL INPUT " +
-                                  "RETURNS double " +
-                                  "LANGUAGE JAVA\n" +
-                                  "AS '" + typeAndSource[1] + "';");
-         }
- 
-         // JavaScript UDFs
- 
-         try
-         {
-             String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                           "RETURNS NULL ON NULL INPUT " +
-                                           "RETURNS double " +
-                                           "LANGUAGE javascript\n" +
-                                           "AS 'org.apache.cassandra.service.StorageService.instance.isShutdown(); 0;';");
-             execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-             Assert.fail("Javascript security check failed");
-         }
-         catch (FunctionExecutionException e)
-         {
-             assertAccessControlException("", e);
-         }
- 
-         String[] javascript =
-         {
-         "java.lang.management.ManagmentFactory.getThreadMXBean(); 0;",
-         "new java.io.FileInputStream(\"/tmp/foo\"); 0;",
-         "new java.io.FileOutputStream(\"/tmp/foo\"); 0;",
-         "java.nio.file.FileSystems.getDefault().createFileExclusively(\"./foo_bar_baz\"); 0;",
-         "java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")); 0;",
-         "java.nio.channels.SocketChannel.open(); 0;",
-         "new java.net.ServerSocket().bind(null); 0;",
-         "var thread = new java.lang.Thread(); thread.start(); 0;",
-         "java.lang.System.getProperty(\"foo.bar.baz\"); 0;",
-         "java.lang.Class.forName(\"java.lang.System\"); 0;",
-         "java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); 0;",
-         "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
-         "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
-         // TODO these (ugly) calls are still possible - these can consume CPU (as one could do with an evil loop, too)
- //        "java.lang.Runtime.getRuntime().traceMethodCalls(true); 0;",
- //        "java.lang.Runtime.getRuntime().gc(); 0;",
- //        "java.lang.Runtime.getRuntime(); 0;",
-         };
- 
-         for (String script : javascript)
-         {
-             try
-             {
-                 String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                               "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                               "RETURNS NULL ON NULL INPUT " +
-                                               "RETURNS double " +
-                                               "LANGUAGE javascript\n" +
-                                               "AS '" + script + "';");
-                 execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-                 Assert.fail("Javascript security check failed: " + script);
-             }
-             catch (FunctionExecutionException e)
-             {
-                 assertAccessControlException(script, e);
-             }
-         }
-     }
- 
-     private static void assertAccessControlException(String script, FunctionExecutionException e)
-     {
-         for (Throwable t = e; t != null && t != t.getCause(); t = t.getCause())
-             if (t instanceof AccessControlException)
-                 return;
-         Assert.fail("no AccessControlException for " + script + " (got " + e + ')');
-     }
- 
-     @Test
-     public void testAmokUDF() throws Throwable
-     {
-         createTable("CREATE TABLE %s (key int primary key, dval double)");
-         execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
- 
-         long udfWarnTimeout = DatabaseDescriptor.getUserDefinedFunctionWarnTimeout();
-         long udfFailTimeout = DatabaseDescriptor.getUserDefinedFunctionFailTimeout();
-         int maxTries = 5;
-         for (int i = 1; i <= maxTries; i++)
-         {
-             try
-             {
-                 // short timeout
-                 DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(10);
-                 DatabaseDescriptor.setUserDefinedFunctionFailTimeout(250);
-                 // don't kill the unit test... - default policy is "die"
-                 DatabaseDescriptor.setUserFunctionTimeoutPolicy(Config.UserFunctionTimeoutPolicy.ignore);
- 
-                 ClientWarn.instance.captureWarnings();
-                 String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                               "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                               "RETURNS NULL ON NULL INPUT " +
-                                               "RETURNS double " +
-                                               "LANGUAGE JAVA\n" +
-                                               "AS 'long t=System.currentTimeMillis()+110; while (t>System.currentTimeMillis()) { }; return 0d;'");
-                 execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
-                 List<String> warnings = ClientWarn.instance.getWarnings();
-                 Assert.assertNotNull(warnings);
-                 Assert.assertFalse(warnings.isEmpty());
-                 ClientWarn.instance.resetWarnings();
- 
-                 // Java UDF
- 
-                 fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                        "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                        "RETURNS NULL ON NULL INPUT " +
-                                        "RETURNS double " +
-                                        "LANGUAGE JAVA\n" +
-                                        "AS 'long t=System.currentTimeMillis()+500; while (t>System.currentTimeMillis()) { }; return 0d;';");
-                 assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
- 
-                 // Javascript UDF
- 
-                 fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                        "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                        "RETURNS NULL ON NULL INPUT " +
-                                        "RETURNS double " +
-                                        "LANGUAGE JAVASCRIPT\n" +
-                                        "AS 'var t=java.lang.System.currentTimeMillis()+500; while (t>java.lang.System.currentTimeMillis()) { }; 0;';");
-                 assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
- 
-                 return;
-             }
-             catch (Error | RuntimeException e)
-             {
-                 if (i == maxTries)
-                     throw e;
-             }
-             finally
-             {
-                 // reset to defaults
-                 DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(udfWarnTimeout);
-                 DatabaseDescriptor.setUserDefinedFunctionFailTimeout(udfFailTimeout);
-             }
-         }
-     }
  }


[11/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
index 0000000,d3050a5..af3c894
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@@ -1,0 -1,504 +1,428 @@@
+ /*
+  * 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.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.util.Arrays;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ import java.util.UUID;
+ 
+ import org.junit.Assert;
 -import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
 -import com.datastax.driver.core.DataType;
 -import com.datastax.driver.core.TupleType;
 -import com.datastax.driver.core.TupleValue;
+ import org.apache.cassandra.config.DatabaseDescriptor;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
 -import org.apache.cassandra.transport.Server;
+ import org.apache.cassandra.utils.UUIDGen;
+ 
+ public class UFScriptTest extends CQLTester
+ {
 -    @BeforeClass
 -    public static void setUp()
 -    {
 -        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
 -    }
++    // Just JavaScript UDFs to check how UDF - especially security/class-loading/sandboxing stuff -
++    // behaves, if no Java UDF has been executed before.
++
++    // Do not add any other test here - especially none using Java UDFs
+ 
+     @Test
+     public void testJavascriptSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                        "CREATE FUNCTION %s( lst list<double> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS list<double> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'lst;';");
+         String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                        "CREATE FUNCTION %s( st set<text> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS set<text> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'st;';");
+         String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                        "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS map<int, boolean> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'mp;';");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavascriptTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
 -    public void testJavascriptTupleTypeCollection() throws Throwable
 -    {
 -        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
 -        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
 -
 -        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup;$$;");
 -        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS double " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getDouble(0);$$;");
 -        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS list<double> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
 -        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS set<text> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
 -        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS map<int, boolean> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
 -
 -        List<Double> list = Arrays.asList(1d, 2d, 3d);
 -        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
 -        Map<Integer, Boolean> map = new TreeMap<>();
 -        map.put(1, true);
 -        map.put(2, false);
 -        map.put(3, true);
 -
 -        Object t = tuple(1d, list, set, map);
 -
 -        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
 -
 -        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
 -                   row(t));
 -        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
 -                   row(1d));
 -        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
 -                   row(list));
 -        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
 -                   row(set));
 -        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
 -                   row(map));
 -
 -        // same test - but via native protocol
 -        TupleType tType = TupleType.of(DataType.cdouble(),
 -                                       DataType.list(DataType.cdouble()),
 -                                       DataType.set(DataType.text()),
 -                                       DataType.map(DataType.cint(), DataType.cboolean()));
 -        TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
 -        {
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
 -                          row(tup));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
 -                          row(1d));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
 -                          row(list));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
 -                          row(set));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
 -                          row(map));
 -        }
 -    }
 -
 -    @Test
+     public void testJavascriptUserType() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS " + type + " " +
++                                      "RETURNS " + type + ' ' +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt;$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt3 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getInt(\"i\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+     }
+ 
+     @Test
+     public void testJavascriptUTCollections() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "        lst.get(1).getString(\"txt\");$$;");
+         createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        st.iterator().next().getString(\"txt\");$$;");
+         createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 // list<frozen<UDT>>
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 // set<frozen<UDT>>
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 // map<int, frozen<UDT>>
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                    row("three"));
+         assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                    row("two"));
+ 
+         String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+         assertRows(execute(cqlSelect),
+                    row("three", "one", "two"));
+ 
+         // same test - but via native protocol
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, cqlSelect),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testJavascriptFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("javascript", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavascriptBadReturnType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '\"string\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ClassCastException
+         assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavascriptThrow() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'throw \"fool\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ScriptException
+         assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
 -    public void testJavascriptCompileFailure() throws Throwable
 -    {
 -        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
 -                             "RETURNS NULL ON NULL INPUT " +
 -                             "RETURNS double " +
 -                             "LANGUAGE javascript\n" +
 -                             "AS 'foo bar';");
 -    }
 -
 -    @Test
 -    public void testScriptInvalidLanguage() throws Throwable
 -    {
 -        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
 -                             "RETURNS NULL ON NULL INPUT " +
 -                             "RETURNS double " +
 -                             "LANGUAGE artificial_intelligence\n" +
 -                             "AS 'question for 42?';");
 -    }
 -
 -    @Test
+     public void testScriptReturnTypeCasting() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+ 
+         Object[][] variations = {
+         new Object[]    {   "true",     "boolean",  true    },
+         new Object[]    {   "false",    "boolean",  false   },
+         new Object[]    {   "100",      "tinyint",  (byte)100 },
+         new Object[]    {   "100.",     "tinyint",  (byte)100 },
+         new Object[]    {   "100",      "smallint", (short)100 },
+         new Object[]    {   "100.",     "smallint", (short)100 },
+         new Object[]    {   "100",      "int",      100     },
+         new Object[]    {   "100.",     "int",      100     },
+         new Object[]    {   "100",      "double",   100d    },
+         new Object[]    {   "100.",     "double",   100d    },
+         new Object[]    {   "100",      "bigint",   100L    },
+         new Object[]    {   "100.",     "bigint",   100L    },
+         new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+         new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+         new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+         new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object functionBody = variation[0];
+             Object returnType = variation[1];
+             Object expectedResult = variation[2];
+ 
+             String fName = createFunction(KEYSPACE, "double",
+                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " +returnType + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS '" + functionBody + ";';");
+             assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                        row(1, 1d, expectedResult));
+         }
+     }
+ 
+     @Test
+     public void testScriptParamReturnTypes() throws Throwable
+     {
+         UUID ruuid = UUID.randomUUID();
+         UUID tuuid = UUIDGen.getTimeUUID();
+ 
+         createTable("CREATE TABLE %s (key int primary key, " +
+                     "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                     "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+         execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                 (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+ 
+         Object[][] variations = {
+         new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+         new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+         new Object[] {  "int",      "ival",     1,                      2  },
+         new Object[] {  "bigint",   "lval",     1L,                     2L  },
+         new Object[] {  "float",    "fval",     1f,                     2f  },
+         new Object[] {  "double",   "dval",     1d,                     2d  },
+         new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+         new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+         new Object[] {  "time",     "timval",   1L,                     2L  },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val+1;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+ 
+         variations = new Object[][] {
+         new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+         new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+         new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+         new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+     }
++
++    @Test
++    public void testJavascriptDisabled() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, val double)");
++
++        DatabaseDescriptor.enableScriptedUserDefinedFunctions(false);
++        try
++        {
++            assertInvalid("double",
++                          "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".assertNotEnabled(val double) " +
++                          "RETURNS NULL ON NULL INPUT " +
++                          "RETURNS double " +
++                          "LANGUAGE javascript\n" +
++                          "AS 'Math.sin(val);';");
++        }
++        finally
++        {
++            DatabaseDescriptor.enableScriptedUserDefinedFunctions(true);
++        }
++    }
++
++    @Test
++    public void testJavascriptCompileFailure() throws Throwable
++    {
++        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
++                             "RETURNS NULL ON NULL INPUT " +
++                             "RETURNS double " +
++                             "LANGUAGE javascript\n" +
++                             "AS 'foo bar';");
++    }
++
++    @Test
++    public void testScriptInvalidLanguage() throws Throwable
++    {
++        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
++                             "RETURNS NULL ON NULL INPUT " +
++                             "RETURNS double " +
++                             "LANGUAGE artificial_intelligence\n" +
++                             "AS 'question for 42?';");
++    }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
index 0000000,0000000..5c7ca2b
new file mode 100644
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
@@@ -1,0 -1,0 +1,258 @@@
++/*
++ * 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.security.AccessControlException;
++import java.util.List;
++
++import org.junit.Assert;
++import org.junit.Test;
++
++import org.apache.cassandra.config.Config;
++import org.apache.cassandra.config.DatabaseDescriptor;
++import org.apache.cassandra.cql3.CQLTester;
++import org.apache.cassandra.cql3.functions.UDHelper;
++import org.apache.cassandra.exceptions.FunctionExecutionException;
++import org.apache.cassandra.service.ClientWarn;
++
++public class UFSecurityTest extends CQLTester
++{
++    @Test
++    public void testSecurityPermissions() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, dval double)");
++        execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
++
++        // Java UDFs
++
++        try
++        {
++            String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                          "RETURNS NULL ON NULL INPUT " +
++                                          "RETURNS double " +
++                                          "LANGUAGE JAVA\n" +
++                                          "AS 'System.getProperty(\"foo.bar.baz\"); return 0d;';");
++            execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++            Assert.fail();
++        }
++        catch (FunctionExecutionException e)
++        {
++            assertAccessControlException("System.getProperty(\"foo.bar.baz\"); return 0d;", e);
++        }
++
++        String[][] typesAndSources =
++        {
++        {"", "try { Class.forName(\"" + UDHelper.class.getName() + "\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
++        {"sun.misc.Unsafe",         "sun.misc.Unsafe.getUnsafe(); return 0d;"},
++        {"",                        "try { Class.forName(\"sun.misc.Unsafe\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
++        {"java.nio.file.FileSystems", "try {" +
++                                      "     java.nio.file.FileSystems.getDefault(); return 0d;" +
++                                      "} catch (Exception t) {" +
++                                      "     throw new RuntimeException(t);" +
++                                      '}'},
++        {"java.nio.channels.FileChannel", "try {" +
++                                          "     java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")).close(); return 0d;" +
++                                          "} catch (Exception t) {" +
++                                          "     throw new RuntimeException(t);" +
++                                          '}'},
++        {"java.nio.channels.SocketChannel", "try {" +
++                                            "     java.nio.channels.SocketChannel.open().close(); return 0d;" +
++                                            "} catch (Exception t) {" +
++                                            "     throw new RuntimeException(t);" +
++                                            '}'},
++        {"java.io.FileInputStream", "try {" +
++                                    "     new java.io.FileInputStream(\"./foobar\").close(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.lang.Runtime",       "try {" +
++                                    "     java.lang.Runtime.getRuntime(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"org.apache.cassandra.service.StorageService",
++         "try {" +
++         "     org.apache.cassandra.service.StorageService v = org.apache.cassandra.service.StorageService.instance; v.isShutdown(); return 0d;" +
++         "} catch (Exception t) {" +
++         "     throw new RuntimeException(t);" +
++         '}'},
++        {"java.net.ServerSocket",   "try {" +
++                                    "     new java.net.ServerSocket().bind(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.io.FileOutputStream","try {" +
++                                    "     new java.io.FileOutputStream(\".foo\"); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.lang.Runtime",       "try {" +
++                                    "     java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'}
++        };
++
++        for (String[] typeAndSource : typesAndSources)
++        {
++            assertInvalidMessage(typeAndSource[0] + " cannot be resolved",
++                                 "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".invalid_class_access(val double) " +
++                                 "RETURNS NULL ON NULL INPUT " +
++                                 "RETURNS double " +
++                                 "LANGUAGE JAVA\n" +
++                                 "AS '" + typeAndSource[1] + "';");
++        }
++
++        // JavaScript UDFs
++
++        try
++        {
++            String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                          "RETURNS NULL ON NULL INPUT " +
++                                          "RETURNS double " +
++                                          "LANGUAGE javascript\n" +
++                                          "AS 'org.apache.cassandra.service.StorageService.instance.isShutdown(); 0;';");
++            execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++            Assert.fail("Javascript security check failed");
++        }
++        catch (FunctionExecutionException e)
++        {
++            assertAccessControlException("", e);
++        }
++
++        String[] javascript =
++        {
++        "java.lang.management.ManagmentFactory.getThreadMXBean(); 0;",
++        "new java.io.FileInputStream(\"/tmp/foo\"); 0;",
++        "new java.io.FileOutputStream(\"/tmp/foo\"); 0;",
++        "java.nio.file.FileSystems.getDefault().createFileExclusively(\"./foo_bar_baz\"); 0;",
++        "java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")); 0;",
++        "java.nio.channels.SocketChannel.open(); 0;",
++        "new java.net.ServerSocket().bind(null); 0;",
++        "var thread = new java.lang.Thread(); thread.start(); 0;",
++        "java.lang.System.getProperty(\"foo.bar.baz\"); 0;",
++        "java.lang.Class.forName(\"java.lang.System\"); 0;",
++        "java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); 0;",
++        "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
++        "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
++        // TODO these (ugly) calls are still possible - these can consume CPU (as one could do with an evil loop, too)
++//        "java.lang.Runtime.getRuntime().traceMethodCalls(true); 0;",
++//        "java.lang.Runtime.getRuntime().gc(); 0;",
++//        "java.lang.Runtime.getRuntime(); 0;",
++        };
++
++        for (String script : javascript)
++        {
++            try
++            {
++                String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                              "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                              "RETURNS NULL ON NULL INPUT " +
++                                              "RETURNS double " +
++                                              "LANGUAGE javascript\n" +
++                                              "AS '" + script + "';");
++                execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++                Assert.fail("Javascript security check failed: " + script);
++            }
++            catch (FunctionExecutionException e)
++            {
++                assertAccessControlException(script, e);
++            }
++        }
++    }
++
++    private static void assertAccessControlException(String script, FunctionExecutionException e)
++    {
++        for (Throwable t = e; t != null && t != t.getCause(); t = t.getCause())
++            if (t instanceof AccessControlException)
++                return;
++        Assert.fail("no AccessControlException for " + script + " (got " + e + ')');
++    }
++
++    @Test
++    public void testAmokUDF() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, dval double)");
++        execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
++
++        long udfWarnTimeout = DatabaseDescriptor.getUserDefinedFunctionWarnTimeout();
++        long udfFailTimeout = DatabaseDescriptor.getUserDefinedFunctionFailTimeout();
++        int maxTries = 5;
++        for (int i = 1; i <= maxTries; i++)
++        {
++            try
++            {
++                // short timeout
++                DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(10);
++                DatabaseDescriptor.setUserDefinedFunctionFailTimeout(250);
++                // don't kill the unit test... - default policy is "die"
++                DatabaseDescriptor.setUserFunctionTimeoutPolicy(Config.UserFunctionTimeoutPolicy.ignore);
++
++                ClientWarn.instance.captureWarnings();
++                String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                              "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                              "RETURNS NULL ON NULL INPUT " +
++                                              "RETURNS double " +
++                                              "LANGUAGE JAVA\n" +
++                                              "AS 'long t=System.currentTimeMillis()+110; while (t>System.currentTimeMillis()) { }; return 0d;'");
++                execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++                List<String> warnings = ClientWarn.instance.getWarnings();
++                Assert.assertNotNull(warnings);
++                Assert.assertFalse(warnings.isEmpty());
++                ClientWarn.instance.resetWarnings();
++
++                // Java UDF
++
++                fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                       "RETURNS NULL ON NULL INPUT " +
++                                       "RETURNS double " +
++                                       "LANGUAGE JAVA\n" +
++                                       "AS 'long t=System.currentTimeMillis()+500; while (t>System.currentTimeMillis()) { }; return 0d;';");
++                assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
++
++                // Javascript UDF
++
++                fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                       "RETURNS NULL ON NULL INPUT " +
++                                       "RETURNS double " +
++                                       "LANGUAGE JAVASCRIPT\n" +
++                                       "AS 'var t=java.lang.System.currentTimeMillis()+500; while (t>java.lang.System.currentTimeMillis()) { }; 0;';");
++                assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
++
++                return;
++            }
++            catch (Error | RuntimeException e)
++            {
++                if (i == maxTries)
++                    throw e;
++            }
++            finally
++            {
++                // reset to defaults
++                DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(udfWarnTimeout);
++                DatabaseDescriptor.setUserDefinedFunctionFailTimeout(udfFailTimeout);
++            }
++        }
++    }
++
++}


[06/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Posted by sn...@apache.org.
testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

patch by Robert Stupp; reviewed by Alex Petrov for CASSANDRA-12817


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/0b97c5d1
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/0b97c5d1
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/0b97c5d1

Branch: refs/heads/cassandra-3.X
Commit: 0b97c5d1f717be30a04c59c766465d9c62a4e9ee
Parents: 2e93398
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:06:55 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:06:55 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    | 1177 +++++++++++++
 .../cql3/validation/entities/UFScriptTest.java  |  504 ++++++
 .../cql3/validation/entities/UFTest.java        | 1608 +-----------------
 3 files changed, 1696 insertions(+), 1593 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
new file mode 100644
index 0000000..caef808
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@ -0,0 +1,1177 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import com.datastax.driver.core.UDTValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQL3Type;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.cql3.functions.Functions;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+public class UFJavaTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+
+    @Test
+    public void testJavaFunctionNoParameters() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = "\n  return 1L;\n";
+
+        String fName = createFunction(KEYSPACE, "",
+                                      "CREATE OR REPLACE FUNCTION %s() " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" +functionBody + "';");
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           KEYSPACE, parseFunctionName(fName).name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                   row(1, 1d, 1L),
+                   row(2, 2d, 1L),
+                   row(3, 3d, 1L)
+        );
+    }
+
+    @Test
+    public void testJavaFunctionInvalidBodies() throws Throwable
+    {
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+        }
+
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz;" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+        }
+    }
+
+    @Test
+    public void testJavaFunctionInvalidReturn() throws Throwable
+    {
+        assertInvalidMessage("system keyspace is not user-modifiable",
+                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE JAVA\n" +
+                             "AS 'return 1L;';");
+    }
+
+    @Test
+    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val bigint)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return Double.valueOf(val);';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+        assertInvalidMessage("val cannot be passed as argument 0 of function",
+                             "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaFunctionCounter() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val counter)");
+
+        String fName = createFunction(KEYSPACE, "counter",
+                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return val + 1;';");
+
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1L, 2L));
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 4L, 5L));
+        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+    }
+
+    @Test
+    public void testJavaKeyspaceFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin( val );\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaRuntimeException() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  throw new RuntimeException(\"oh no!\");\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+
+        // function throws a RuntimeException which is wrapped by FunctionExecutionException
+        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaDollarQuotedFunction() throws Throwable
+    {
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (input == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE FUNCTION %s( input double ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$" + functionBody + "$$;");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+    }
+
+    @Test
+    public void testJavaSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                      "CREATE FUNCTION %s( lst list<double> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return lst;$$;");
+        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                     "CREATE FUNCTION %s( st set<text> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS set<text> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return st;$$;");
+        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS map<int, boolean> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return mp;$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavaTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavaTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + tupleTypeDef + ' ' +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup;$$;");
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       Double.valueOf(tup.getDouble(0));$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getList(1, Double.class);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getSet(2, String.class);$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeWithUse() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            executeNet(version, "USE " + KEYSPACE);
+
+            executeNet(version,
+                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS " + type + " " +
+                       "LANGUAGE java " +
+                       "AS $$return " +
+                       "     udt;$$;");
+            try
+            {
+                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                Assert.assertEquals(1, rowsNet.size());
+                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                Assert.assertEquals("one", udtVal.getString("txt"));
+                Assert.assertEquals(1, udtVal.getInt("i"));
+            }
+            finally
+            {
+                executeNet(version, "DROP FUNCTION f_use1");
+            }
+        }
+    }
+
+    @Test
+    public void testJavaUserType() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt0 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt;$$;");
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+            Assert.assertEquals(1, rowsNet.size());
+            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+            Assert.assertEquals("one", udtVal.getString("txt"));
+            Assert.assertEquals(1, udtVal.getInt("i"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                          row("one"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                          row(1));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeRenameField() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return udt.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+
+        execute("ALTER TYPE " + type + " RENAME txt TO str");
+
+        assertInvalidMessage("txt is not a field defined in this UDT",
+                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+
+        execute("ALTER TYPE " + type + " RENAME str TO txt");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+    }
+
+    @Test
+    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName1replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + ") " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt.getString(\"txt\");$$;");
+        String fName2replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS double " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS " + type + " " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt;$$;");
+
+        String fName1noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS text " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt.getString(\"txt\");$$;");
+        String fName2noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS int " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS double " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS " + type + " " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt;$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        // add field
+
+        execute("ALTER TYPE " + type + " ADD added double");
+
+        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+
+        // note: type references of functions remain at the state _before_ the type mutation
+        // means we need to recreate the functions
+
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt.getString(\"txt\");$$;",
+                              fName1replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                              fName2replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                              fName3replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS %s " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt;$$;",
+                              fName4replace, type, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        // un-replaced functions will work since the user type has changed
+        // and the UDF has exchanged the user type reference
+
+        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        execute("DROP FUNCTION " + fName1replace);
+        execute("DROP FUNCTION " + fName2replace);
+        execute("DROP FUNCTION " + fName3replace);
+        execute("DROP FUNCTION " + fName4replace);
+        execute("DROP FUNCTION " + fName1noReplace);
+        execute("DROP FUNCTION " + fName2noReplace);
+        execute("DROP FUNCTION " + fName3noReplace);
+        execute("DROP FUNCTION " + fName4noReplace);
+    }
+
+    @Test
+    public void testJavaUTCollections() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row("three", "one", "two"));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testFunctionWithFrozenSetType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<set<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "set<int>",
+                                             "CREATE FUNCTION %s (values set<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "set<int>",
+                                      "CREATE FUNCTION %s (values set<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS set<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenListType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<list<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "list<int>",
+                                             "CREATE FUNCTION %s (values list<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "list<int>",
+                                      "CREATE FUNCTION %s (values list<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS list<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenMapType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<map<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "map<int, int>",
+                                             "CREATE FUNCTION %s (values map<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "map<int, int>",
+                                      "CREATE FUNCTION %s (values map<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS map<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<tuple<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "tuple<int, int>",
+                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "(null, null)"),
+                   row(1, "(1, 2)"),
+                   row(2, "(4, 5)"),
+                   row(3, "(7, 8)"));
+
+        functionName = createFunction(KEYSPACE,
+                                      "tuple<int, int>",
+                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS tuple<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenUDType() throws Throwable
+    {
+        String myType = createType("CREATE TYPE %s (f int)");
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<" + myType + "> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             myType,
+                                             "CREATE FUNCTION %s (values " + myType + ") " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "{f:0}"),
+                   row(1, "{f:1}"),
+                   row(2, "{f:4}"),
+                   row(3, "{f:7}"));
+
+        functionName = createFunction(KEYSPACE,
+                                      myType,
+                                      "CREATE FUNCTION %s (values " + myType + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + myType + " " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
+    }
+
+    @Test
+    public void testEmptyString() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
+        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
+
+        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
+        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
+    }
+
+    @Test
+    public void testAllNativeTypes() throws Throwable
+    {
+        StringBuilder sig = new StringBuilder();
+        StringBuilder args = new StringBuilder();
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            if (sig.length() > 0)
+                sig.append(',');
+            sig.append(type.toString());
+
+            if (args.length() > 0)
+                args.append(',');
+            args.append("arg").append(type.toString()).append(' ').append(type.toString());
+        }
+        createFunction(KEYSPACE, sig.toString(),
+                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS int " +
+                       "LANGUAGE JAVA\n" +
+                       "AS 'return 0;'");
+
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            createFunction(KEYSPACE_PER_TEST, type.toString(),
+                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                           "RETURNS NULL ON NULL INPUT " +
+                           "RETURNS int " +
+                           "LANGUAGE JAVA\n" +
+                           "AS 'return 0;'");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
new file mode 100644
index 0000000..d3050a5
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@ -0,0 +1,504 @@
+/*
+ * 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.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.UUIDGen;
+
+public class UFScriptTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+    @Test
+    public void testJavascriptSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'lst;';");
+        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                       "CREATE FUNCTION %s( st set<text> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'st;';");
+        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                       "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'mp;';");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavascriptTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavascriptTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup;$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getDouble(0);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
+        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        // same test - but via native protocol
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavascriptUserType() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt;$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt3 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getInt(\"i\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+    }
+
+    @Test
+    public void testJavascriptUTCollections() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "        lst.get(1).getString(\"txt\");$$;");
+        createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        st.iterator().next().getString(\"txt\");$$;");
+        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                // list<frozen<UDT>>
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                // set<frozen<UDT>>
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                // map<int, frozen<UDT>>
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                   row("three"));
+        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                   row("two"));
+
+        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+        assertRows(execute(cqlSelect),
+                   row("three", "one", "two"));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, cqlSelect),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testJavascriptFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("javascript", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavascriptBadReturnType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '\"string\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ClassCastException
+        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptThrow() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS 'throw \"fool\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ScriptException
+        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptCompileFailure() throws Throwable
+    {
+        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE javascript\n" +
+                             "AS 'foo bar';");
+    }
+
+    @Test
+    public void testScriptInvalidLanguage() throws Throwable
+    {
+        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE artificial_intelligence\n" +
+                             "AS 'question for 42?';");
+    }
+
+    @Test
+    public void testScriptReturnTypeCasting() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+
+        Object[][] variations = {
+        new Object[]    {   "true",     "boolean",  true    },
+        new Object[]    {   "false",    "boolean",  false   },
+        new Object[]    {   "100",      "tinyint",  (byte)100 },
+        new Object[]    {   "100.",     "tinyint",  (byte)100 },
+        new Object[]    {   "100",      "smallint", (short)100 },
+        new Object[]    {   "100.",     "smallint", (short)100 },
+        new Object[]    {   "100",      "int",      100     },
+        new Object[]    {   "100.",     "int",      100     },
+        new Object[]    {   "100",      "double",   100d    },
+        new Object[]    {   "100.",     "double",   100d    },
+        new Object[]    {   "100",      "bigint",   100L    },
+        new Object[]    {   "100.",     "bigint",   100L    },
+        new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+        new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+        new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+        new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object functionBody = variation[0];
+            Object returnType = variation[1];
+            Object expectedResult = variation[2];
+
+            String fName = createFunction(KEYSPACE, "double",
+                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " +returnType + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS '" + functionBody + ";';");
+            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                       row(1, 1d, expectedResult));
+        }
+    }
+
+    @Test
+    public void testScriptParamReturnTypes() throws Throwable
+    {
+        UUID ruuid = UUID.randomUUID();
+        UUID tuuid = UUIDGen.getTimeUUID();
+
+        createTable("CREATE TABLE %s (key int primary key, " +
+                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+
+        Object[][] variations = {
+        new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+        new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+        new Object[] {  "int",      "ival",     1,                      2  },
+        new Object[] {  "bigint",   "lval",     1L,                     2L  },
+        new Object[] {  "float",    "fval",     1f,                     2f  },
+        new Object[] {  "double",   "dval",     1d,                     2d  },
+        new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+        new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+        new Object[] {  "time",     "timval",   1L,                     2L  },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val+1;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+
+        variations = new Object[][] {
+        new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+        new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+        new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+        new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+    }
+}


[24/25] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.X

Posted by sn...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.X


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/d7b6b7a3
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/d7b6b7a3
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/d7b6b7a3

Branch: refs/heads/trunk
Commit: d7b6b7a34d8a9401b8f615c91230a1fc882e32e1
Parents: 57c2003 3aefe35
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:23:32 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:23:32 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    |  797 ++++++++
 .../validation/entities/UFPureScriptTest.java   |  407 ----
 .../cql3/validation/entities/UFScriptTest.java  |  429 +++++
 .../validation/entities/UFSecurityTest.java     |  258 +++
 .../cql3/validation/entities/UFTest.java        | 1739 +-----------------
 .../cql3/validation/entities/UFTypesTest.java   |  550 ++++++
 6 files changed, 2035 insertions(+), 2145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
index 0000000,15c8e18..4d46b8b
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@@ -1,0 -1,797 +1,797 @@@
+ /*
+  * 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.util.Arrays;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ 
+ import org.junit.Assert;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.DataType;
+ import com.datastax.driver.core.Row;
+ import com.datastax.driver.core.TupleType;
+ import com.datastax.driver.core.TupleValue;
+ import com.datastax.driver.core.UDTValue;
+ import org.apache.cassandra.config.Schema;
+ import org.apache.cassandra.cql3.CQL3Type;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
 -import org.apache.cassandra.transport.Server;
++import org.apache.cassandra.transport.ProtocolVersion;
+ 
+ public class UFJavaTest extends CQLTester
+ {
+     @Test
+     public void testJavaFunctionNoParameters() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = "\n  return 1L;\n";
+ 
+         String fName = createFunction(KEYSPACE, "",
+                                       "CREATE OR REPLACE FUNCTION %s() " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" +functionBody + "';");
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            KEYSPACE, parseFunctionName(fName).name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                    row(1, 1d, 1L),
+                    row(2, 2d, 1L),
+                    row(3, 3d, 1L)
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidBodies() throws Throwable
+     {
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+         }
+ 
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz;" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+         }
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidReturn() throws Throwable
+     {
+         assertInvalidMessage("system keyspace is not user-modifiable",
+                              "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE JAVA\n" +
+                              "AS 'return 1L;';");
+     }
+ 
+     @Test
+     public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val bigint)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return Double.valueOf(val);';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+         assertInvalidMessage("val cannot be passed as argument 0 of function",
+                              "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionCounter() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val counter)");
+ 
+         String fName = createFunction(KEYSPACE, "counter",
+                                       "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return val + 1;';");
+ 
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1L, 2L));
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+         execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 4L, 5L));
+         execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+     }
+ 
+     @Test
+     public void testJavaKeyspaceFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin( val );\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaRuntimeException() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  throw new RuntimeException(\"oh no!\");\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+ 
+         // function throws a RuntimeException which is wrapped by FunctionExecutionException
+         assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaDollarQuotedFunction() throws Throwable
+     {
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (input == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return \"'\"+Math.sin(input)+'\\\'';\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE FUNCTION %s( input double ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" + functionBody + "$$;");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+     }
+ 
+     @Test
+     public void testJavaSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return lst;$$;");
+         String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                      "CREATE FUNCTION %s( st set<text> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return st;$$;");
+         String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return mp;$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         // same test - but via native protocol
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavaTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavaTupleTypeCollection() throws Throwable
+     {
+         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+ 
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+ 
+         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + tupleTypeDef + ' ' +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup;$$;");
+         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       Double.valueOf(tup.getDouble(0));$$;");
+         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getList(1, Double.class);$$;");
+         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getSet(2, String.class);$$;");
+         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         Object t = tuple(1d, list, set, map);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                    row(1d));
+         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                    row(list));
+         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                    row(set));
+         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                    row(map));
+ 
+         // same test - but via native protocol
+         // we use protocol V3 here to encode the expected version because the server
+         // always serializes Collections using V3 - see CollectionSerializer's
+         // serialize and deserialize methods.
 -        TupleType tType = tupleTypeOf(Server.VERSION_3,
++        TupleType tType = tupleTypeOf(ProtocolVersion.V3,
+                                       DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+         TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                           row(tup));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                           row(1d));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                           row(list));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                           row(set));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                           row(map));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeWithUse() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             executeNet(version, "USE " + KEYSPACE);
+ 
+             executeNet(version,
+                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS " + type + " " +
+                        "LANGUAGE java " +
+                        "AS $$return " +
+                        "     udt;$$;");
+             try
+             {
+                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                 Assert.assertEquals(1, rowsNet.size());
+                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                 Assert.assertEquals("one", udtVal.getString("txt"));
+                 Assert.assertEquals(1, udtVal.getInt("i"));
+             }
+             finally
+             {
+                 executeNet(version, "DROP FUNCTION f_use1");
+             }
+         }
+     }
+ 
+     @Test
+     public void testJavaUserType() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt0 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + " " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt;$$;");
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+             Assert.assertEquals(1, rowsNet.size());
+             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+             Assert.assertEquals("one", udtVal.getString("txt"));
+             Assert.assertEquals(1, udtVal.getInt("i"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                           row("one"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                           row(1));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeRenameField() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return udt.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+ 
+         execute("ALTER TYPE " + type + " RENAME txt TO str");
+ 
+         assertInvalidMessage("txt is not a field defined in this UDT",
+                              "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+ 
+         execute("ALTER TYPE " + type + " RENAME str TO txt");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+     }
+ 
+     @Test
+     public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName1replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + ") " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS text " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt.getString(\"txt\");$$;");
+         String fName2replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS int " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS double " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS " + type + " " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt;$$;");
+ 
+         String fName1noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS text " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt.getString(\"txt\");$$;");
+         String fName2noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS int " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS double " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS " + type + " " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt;$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
+         // add field
+ 
+         execute("ALTER TYPE " + type + " ADD added double");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+ 
+         // note: type references of functions remain at the state _before_ the type mutation
+         // means we need to recreate the functions
+ 
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt.getString(\"txt\");$$;",
+                               fName1replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName1replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS int " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                               fName2replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName2replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS double " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                               fName3replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName3replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS %s " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt;$$;",
+                               fName4replace, type, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName4replace)).size());
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         // un-replaced functions will work since the user type has changed
+         // and the UDF has exchanged the user type reference
+ 
+         assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         execute("DROP FUNCTION " + fName1replace);
+         execute("DROP FUNCTION " + fName2replace);
+         execute("DROP FUNCTION " + fName3replace);
+         execute("DROP FUNCTION " + fName4replace);
+         execute("DROP FUNCTION " + fName1noReplace);
+         execute("DROP FUNCTION " + fName2noReplace);
+         execute("DROP FUNCTION " + fName3noReplace);
+         execute("DROP FUNCTION " + fName4noReplace);
+     }
+ 
+     @Test
+     public void testJavaUTCollections() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row("three", "one", "two"));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testAllNativeTypes() throws Throwable
+     {
+         StringBuilder sig = new StringBuilder();
+         StringBuilder args = new StringBuilder();
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
+             if (type == CQL3Type.Native.EMPTY)
+                 continue;
+ 
+             if (sig.length() > 0)
+                 sig.append(',');
+             sig.append(type.toString());
+ 
+             if (args.length() > 0)
+                 args.append(',');
+             args.append("arg").append(type.toString()).append(' ').append(type.toString());
+         }
+         createFunction(KEYSPACE, sig.toString(),
+                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS int " +
+                        "LANGUAGE JAVA\n" +
+                        "AS 'return 0;'");
+ 
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
+             if (type == CQL3Type.Native.EMPTY)
+                 continue;
+ 
+             createFunction(KEYSPACE_PER_TEST, type.toString(),
+                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                            "RETURNS NULL ON NULL INPUT " +
+                            "RETURNS int " +
+                            "LANGUAGE JAVA\n" +
+                            "AS 'return 0;'");
+         }
+     }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
index 0000000,af3c894..02a13e7
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@@ -1,0 -1,428 +1,429 @@@
+ /*
+  * 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.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.util.Arrays;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ import java.util.UUID;
+ 
+ import org.junit.Assert;
+ import org.junit.Test;
+ 
+ import org.apache.cassandra.config.DatabaseDescriptor;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
++import org.apache.cassandra.transport.ProtocolVersion;
+ import org.apache.cassandra.utils.UUIDGen;
+ 
+ public class UFScriptTest extends CQLTester
+ {
+     // Just JavaScript UDFs to check how UDF - especially security/class-loading/sandboxing stuff -
+     // behaves, if no Java UDF has been executed before.
+ 
+     // Do not add any other test here - especially none using Java UDFs
+ 
+     @Test
+     public void testJavascriptSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                        "CREATE FUNCTION %s( lst list<double> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS list<double> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'lst;';");
+         String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                        "CREATE FUNCTION %s( st set<text> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS set<text> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'st;';");
+         String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                        "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS map<int, boolean> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'mp;';");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavascriptTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavascriptUserType() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + ' ' +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt;$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt3 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getInt(\"i\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+     }
+ 
+     @Test
+     public void testJavascriptUTCollections() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "        lst.get(1).getString(\"txt\");$$;");
+         createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        st.iterator().next().getString(\"txt\");$$;");
+         createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 // list<frozen<UDT>>
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 // set<frozen<UDT>>
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 // map<int, frozen<UDT>>
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                    row("three"));
+         assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                    row("two"));
+ 
+         String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+         assertRows(execute(cqlSelect),
+                    row("three", "one", "two"));
+ 
+         // same test - but via native protocol
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, cqlSelect),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testJavascriptFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("javascript", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavascriptBadReturnType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '\"string\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ClassCastException
+         assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavascriptThrow() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'throw \"fool\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ScriptException
+         assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testScriptReturnTypeCasting() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+ 
+         Object[][] variations = {
+         new Object[]    {   "true",     "boolean",  true    },
+         new Object[]    {   "false",    "boolean",  false   },
+         new Object[]    {   "100",      "tinyint",  (byte)100 },
+         new Object[]    {   "100.",     "tinyint",  (byte)100 },
+         new Object[]    {   "100",      "smallint", (short)100 },
+         new Object[]    {   "100.",     "smallint", (short)100 },
+         new Object[]    {   "100",      "int",      100     },
+         new Object[]    {   "100.",     "int",      100     },
+         new Object[]    {   "100",      "double",   100d    },
+         new Object[]    {   "100.",     "double",   100d    },
+         new Object[]    {   "100",      "bigint",   100L    },
+         new Object[]    {   "100.",     "bigint",   100L    },
+         new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+         new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+         new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+         new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object functionBody = variation[0];
+             Object returnType = variation[1];
+             Object expectedResult = variation[2];
+ 
+             String fName = createFunction(KEYSPACE, "double",
+                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " +returnType + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS '" + functionBody + ";';");
+             assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                        row(1, 1d, expectedResult));
+         }
+     }
+ 
+     @Test
+     public void testScriptParamReturnTypes() throws Throwable
+     {
+         UUID ruuid = UUID.randomUUID();
+         UUID tuuid = UUIDGen.getTimeUUID();
+ 
+         createTable("CREATE TABLE %s (key int primary key, " +
+                     "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                     "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+         execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                 (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+ 
+         Object[][] variations = {
+         new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+         new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+         new Object[] {  "int",      "ival",     1,                      2  },
+         new Object[] {  "bigint",   "lval",     1L,                     2L  },
+         new Object[] {  "float",    "fval",     1f,                     2f  },
+         new Object[] {  "double",   "dval",     1d,                     2d  },
+         new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+         new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+         new Object[] {  "time",     "timval",   1L,                     2L  },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val+1;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+ 
+         variations = new Object[][] {
+         new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+         new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+         new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+         new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+     }
+ 
+     @Test
+     public void testJavascriptDisabled() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         DatabaseDescriptor.enableScriptedUserDefinedFunctions(false);
+         try
+         {
+             assertInvalid("double",
+                           "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".assertNotEnabled(val double) " +
+                           "RETURNS NULL ON NULL INPUT " +
+                           "RETURNS double " +
+                           "LANGUAGE javascript\n" +
+                           "AS 'Math.sin(val);';");
+         }
+         finally
+         {
+             DatabaseDescriptor.enableScriptedUserDefinedFunctions(true);
+         }
+     }
+ 
+     @Test
+     public void testJavascriptCompileFailure() throws Throwable
+     {
+         assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE javascript\n" +
+                              "AS 'foo bar';");
+     }
+ 
+     @Test
+     public void testScriptInvalidLanguage() throws Throwable
+     {
+         assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE artificial_intelligence\n" +
+                              "AS 'question for 42?';");
+     }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index 1eccc3f,8a743ea..c54982e
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@@ -18,46 -18,28 +18,31 @@@
  package org.apache.cassandra.cql3.validation.entities;
  
  import java.nio.ByteBuffer;
- import java.security.AccessControlException;
  import java.util.ArrayList;
- import java.util.Arrays;
  import java.util.Date;
  import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.TreeMap;
- import java.util.TreeSet;
- import java.util.UUID;
  
 +import com.google.common.reflect.TypeToken;
  import org.junit.Assert;
  import org.junit.Test;
  
 +import com.datastax.driver.core.*;
- import com.datastax.driver.core.DataType;
  import com.datastax.driver.core.exceptions.InvalidQueryException;
- import org.apache.cassandra.config.Config;
- import org.apache.cassandra.config.DatabaseDescriptor;
  import org.apache.cassandra.config.Schema;
- import org.apache.cassandra.cql3.CQL3Type;
  import org.apache.cassandra.cql3.CQLTester;
  import org.apache.cassandra.cql3.QueryProcessor;
  import org.apache.cassandra.cql3.UntypedResultSet;
  import org.apache.cassandra.cql3.functions.FunctionName;
 +import org.apache.cassandra.cql3.functions.JavaBasedUDFunction;
  import org.apache.cassandra.cql3.functions.UDFunction;
- import org.apache.cassandra.cql3.functions.UDHelper;
  import org.apache.cassandra.db.marshal.CollectionType;
- import org.apache.cassandra.exceptions.FunctionExecutionException;
  import org.apache.cassandra.exceptions.InvalidRequestException;
  import org.apache.cassandra.schema.KeyspaceMetadata;
  import org.apache.cassandra.service.ClientState;
- import org.apache.cassandra.service.ClientWarn;
 -import org.apache.cassandra.transport.Event;
 -import org.apache.cassandra.transport.Server;
 +import org.apache.cassandra.transport.*;
 +import org.apache.cassandra.transport.ProtocolVersion;
  import org.apache.cassandra.transport.messages.ResultMessage;
  import org.apache.cassandra.utils.ByteBufferUtil;
- import org.apache.cassandra.utils.UUIDGen;
  
  public class UFTest extends CQLTester
  {


[21/25] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.X

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
index 0000000,de98748..3f1bcb1
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
@@@ -1,0 -1,549 +1,550 @@@
+ /*
+  * 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.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ import java.util.UUID;
+ 
+ import org.junit.Assert;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.Row;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
++import org.apache.cassandra.transport.ProtocolVersion;
+ import org.apache.cassandra.utils.UUIDGen;
+ 
+ public class UFTypesTest extends CQLTester
+ {
+ 
+     @Test
+     public void testComplexNullValues() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
+                     "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
+ 
+         String fList = createFunction(KEYSPACE, "list<double>",
+                                       "CREATE FUNCTION %s( coll list<double> ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return coll;$$;");
+         String fSet = createFunction(KEYSPACE, "set<text>",
+                                      "CREATE FUNCTION %s( coll set<text> ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return coll;$$;");
+         String fMap = createFunction(KEYSPACE, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( coll map<int, boolean> ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return coll;$$;");
+         String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return val;$$;");
+         String fUdt = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( val " + type + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return val;$$;");
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+         Object t = tuple(1d, "one", 42, false);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
+         execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
+ 
+         execute("SELECT " +
+                 fList + "(lst), " +
+                 fSet + "(st), " +
+                 fMap + "(mp), " +
+                 fTup + "(tup), " +
+                 fUdt + "(udt) FROM %s WHERE key = 1");
+         UntypedResultSet.Row row = execute("SELECT " +
+                                            fList + "(lst) as l, " +
+                                            fSet + "(st) as s, " +
+                                            fMap + "(mp) as m, " +
+                                            fTup + "(tup) as t, " +
+                                            fUdt + "(udt) as u " +
+                                            "FROM %s WHERE key = 1").one();
+         Assert.assertNotNull(row.getBytes("l"));
+         Assert.assertNotNull(row.getBytes("s"));
+         Assert.assertNotNull(row.getBytes("m"));
+         Assert.assertNotNull(row.getBytes("t"));
+         Assert.assertNotNull(row.getBytes("u"));
+         row = execute("SELECT " +
+                       fList + "(lst) as l, " +
+                       fSet + "(st) as s, " +
+                       fMap + "(mp) as m, " +
+                       fTup + "(tup) as t, " +
+                       fUdt + "(udt) as u " +
+                       "FROM %s WHERE key = 2").one();
+         Assert.assertNull(row.getBytes("l"));
+         Assert.assertNull(row.getBytes("s"));
+         Assert.assertNull(row.getBytes("m"));
+         Assert.assertNull(row.getBytes("t"));
+         Assert.assertNull(row.getBytes("u"));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             Row r = executeNet(version, "SELECT " +
+                                         fList + "(lst) as l, " +
+                                         fSet + "(st) as s, " +
+                                         fMap + "(mp) as m, " +
+                                         fTup + "(tup) as t, " +
+                                         fUdt + "(udt) as u " +
+                                         "FROM %s WHERE key = 1").one();
+             Assert.assertNotNull(r.getBytesUnsafe("l"));
+             Assert.assertNotNull(r.getBytesUnsafe("s"));
+             Assert.assertNotNull(r.getBytesUnsafe("m"));
+             Assert.assertNotNull(r.getBytesUnsafe("t"));
+             Assert.assertNotNull(r.getBytesUnsafe("u"));
+             r = executeNet(version, "SELECT " +
+                                     fList + "(lst) as l, " +
+                                     fSet + "(st) as s, " +
+                                     fMap + "(mp) as m, " +
+                                     fTup + "(tup) as t, " +
+                                     fUdt + "(udt) as u " +
+                                     "FROM %s WHERE key = 2").one();
+             Assert.assertNull(r.getBytesUnsafe("l"));
+             Assert.assertNull(r.getBytesUnsafe("s"));
+             Assert.assertNull(r.getBytesUnsafe("m"));
+             Assert.assertNull(r.getBytesUnsafe("t"));
+             Assert.assertNull(r.getBytesUnsafe("u"));
+         }
+     }
+ 
+     private static class TypesTestDef
+     {
+         final String udfType;
+         final String tableType;
+         final String columnName;
+         final Object referenceValue;
+ 
+         String fCheckArgAndReturn;
+ 
+         String fCalledOnNull;
+         String fReturnsNullOnNull;
+ 
+         TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
+         {
+             this.udfType = udfType;
+             this.tableType = tableType;
+             this.columnName = columnName;
+             this.referenceValue = referenceValue;
+         }
+     }
+ 
+     @Test
+     public void testTypesWithAndWithoutNulls() throws Throwable
+     {
+         // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
+ 
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         TypesTestDef[] typeDefs =
+         {
+         //                udf type,            table type,                 column, reference value
+         new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
+         new TypesTestDef("date", "date", "dt", 12345),
+         new TypesTestDef("time", "time", "tim", 12345L),
+         new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
+         new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
+         new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
+         new TypesTestDef("smallint", "smallint", "si", (short) 43),
+         new TypesTestDef("int", "int", "i", 44),
+         new TypesTestDef("bigint", "bigint", "b", 45L),
+         new TypesTestDef("float", "float", "f", 46f),
+         new TypesTestDef("double", "double", "d", 47d),
+         new TypesTestDef("boolean", "boolean", "x", true),
+         new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
+         new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
+         //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
+         new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
+         };
+ 
+         String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
+         String insertDML = "INSERT INTO %s (key";
+         List<Object> values = new ArrayList<>();
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
+             insertDML += ", " + typeDef.columnName;
+             String typeName = typeDef.udfType;
+             typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
+                                                         typeName,
+                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
+                                                         "CALLED ON NULL INPUT " +
+                                                         "RETURNS " + typeName + ' ' +
+                                                         "LANGUAGE java\n" +
+                                                         "AS 'return val;';");
+             typeDef.fCalledOnNull = createFunction(KEYSPACE,
+                                                    typeName,
+                                                    "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
+                                                    "CALLED ON NULL INPUT " +
+                                                    "RETURNS text " +
+                                                    "LANGUAGE java\n" +
+                                                    "AS 'return \"called\";';");
+             typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
+                                                         typeName,
+                                                         "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
+                                                         "RETURNS NULL ON NULL INPUT " +
+                                                         "RETURNS text " +
+                                                         "LANGUAGE java\n" +
+                                                         "AS 'return \"called\";';");
+             values.add(typeDef.referenceValue);
+         }
+ 
+         createTableDDL += ')';
+         createTable(createTableDDL);
+ 
+         insertDML += ") VALUES (1";
+         for (TypesTestDef ignored : typeDefs)
+             insertDML += ", ?";
+         insertDML += ')';
+ 
+         execute(insertDML, values.toArray());
+ 
+         // second row with null values
+         for (int i = 0; i < values.size(); i++)
+             values.set(i, null);
+         execute(insertDML.replace('1', '2'), values.toArray());
+ 
+         // check argument input + return
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
+                        row(new Object[]{ typeDef.referenceValue }));
+         }
+ 
+         // check for CALLED ON NULL INPUT with non-null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
+                        row(new Object[]{ "called" }));
+         }
+ 
+         // check for CALLED ON NULL INPUT with null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
+                        row(new Object[]{ "called" }));
+         }
+ 
+         // check for RETURNS NULL ON NULL INPUT with non-null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
+                        row(new Object[]{ "called" }));
+         }
+ 
+         // check for RETURNS NULL ON NULL INPUT with null arguments
+         for (TypesTestDef typeDef : typeDefs)
+         {
+             assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
+                        row(new Object[]{ null }));
+         }
+ 
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenSetType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+         createIndex("CREATE INDEX ON %s (FULL(b))");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<set<int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "set<int>",
+                                              "CREATE FUNCTION %s (values set<int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "set<int>",
+                                       "CREATE FUNCTION %s (values set<int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS set<int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenListType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+         createIndex("CREATE INDEX ON %s (FULL(b))");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<list<int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "list<int>",
+                                              "CREATE FUNCTION %s (values list<int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "list<int>",
+                                       "CREATE FUNCTION %s (values list<int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS list<int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenMapType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+         createIndex("CREATE INDEX ON %s (FULL(b))");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<map<int, int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "map<int, int>",
+                                              "CREATE FUNCTION %s (values map<int, int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "map<int, int>",
+                                       "CREATE FUNCTION %s (values map<int, int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS map<int, int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+         createIndex("CREATE INDEX ON %s (b)");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+         execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values.toString();';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<tuple<int, int>> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              "tuple<int, int>",
+                                              "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'return values.toString();';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       "tuple<int, int>",
+                                       "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS tuple<int, int> " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
+     }
+ 
+     @Test
+     public void testFunctionWithFrozenUDType() throws Throwable
+     {
+         String myType = createType("CREATE TYPE %s (f int)");
+         createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+         createIndex("CREATE INDEX ON %s (b)");
+ 
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+         execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values.toString();';");
+ 
+         assertInvalidMessage("The function return type should not be frozen",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS frozen<" + myType + "> " +
+                              "LANGUAGE java\n" +
+                              "AS 'return values;';");
+ 
+         String functionName = createFunction(KEYSPACE,
+                                              myType,
+                                              "CREATE FUNCTION %s (values " + myType + ") " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS 'return values.toString();';");
+ 
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
+         assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
+ 
+         functionName = createFunction(KEYSPACE,
+                                       myType,
+                                       "CREATE FUNCTION %s (values " + myType + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + myType + " " +
+                                       "LANGUAGE java\n" +
+                                       "AS 'return values;';");
+ 
+         assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
+                    row(1));
+ 
+         assertInvalidMessage("The function arguments should not be frozen",
+                              "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
+     }
+ }


[22/25] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.X

Posted by sn...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.X


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/d7b6b7a3
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/d7b6b7a3
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/d7b6b7a3

Branch: refs/heads/cassandra-3.X
Commit: d7b6b7a34d8a9401b8f615c91230a1fc882e32e1
Parents: 57c2003 3aefe35
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:23:32 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:23:32 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    |  797 ++++++++
 .../validation/entities/UFPureScriptTest.java   |  407 ----
 .../cql3/validation/entities/UFScriptTest.java  |  429 +++++
 .../validation/entities/UFSecurityTest.java     |  258 +++
 .../cql3/validation/entities/UFTest.java        | 1739 +-----------------
 .../cql3/validation/entities/UFTypesTest.java   |  550 ++++++
 6 files changed, 2035 insertions(+), 2145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
index 0000000,15c8e18..4d46b8b
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@@ -1,0 -1,797 +1,797 @@@
+ /*
+  * 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.util.Arrays;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ 
+ import org.junit.Assert;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.DataType;
+ import com.datastax.driver.core.Row;
+ import com.datastax.driver.core.TupleType;
+ import com.datastax.driver.core.TupleValue;
+ import com.datastax.driver.core.UDTValue;
+ import org.apache.cassandra.config.Schema;
+ import org.apache.cassandra.cql3.CQL3Type;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
 -import org.apache.cassandra.transport.Server;
++import org.apache.cassandra.transport.ProtocolVersion;
+ 
+ public class UFJavaTest extends CQLTester
+ {
+     @Test
+     public void testJavaFunctionNoParameters() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = "\n  return 1L;\n";
+ 
+         String fName = createFunction(KEYSPACE, "",
+                                       "CREATE OR REPLACE FUNCTION %s() " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" +functionBody + "';");
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            KEYSPACE, parseFunctionName(fName).name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                    row(1, 1d, 1L),
+                    row(2, 2d, 1L),
+                    row(3, 3d, 1L)
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidBodies() throws Throwable
+     {
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+         }
+ 
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz;" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+         }
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidReturn() throws Throwable
+     {
+         assertInvalidMessage("system keyspace is not user-modifiable",
+                              "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE JAVA\n" +
+                              "AS 'return 1L;';");
+     }
+ 
+     @Test
+     public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val bigint)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return Double.valueOf(val);';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+         assertInvalidMessage("val cannot be passed as argument 0 of function",
+                              "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionCounter() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val counter)");
+ 
+         String fName = createFunction(KEYSPACE, "counter",
+                                       "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return val + 1;';");
+ 
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1L, 2L));
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+         execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 4L, 5L));
+         execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+     }
+ 
+     @Test
+     public void testJavaKeyspaceFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin( val );\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaRuntimeException() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  throw new RuntimeException(\"oh no!\");\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+ 
+         // function throws a RuntimeException which is wrapped by FunctionExecutionException
+         assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaDollarQuotedFunction() throws Throwable
+     {
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (input == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return \"'\"+Math.sin(input)+'\\\'';\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE FUNCTION %s( input double ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" + functionBody + "$$;");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+     }
+ 
+     @Test
+     public void testJavaSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return lst;$$;");
+         String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                      "CREATE FUNCTION %s( st set<text> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return st;$$;");
+         String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return mp;$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         // same test - but via native protocol
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavaTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavaTupleTypeCollection() throws Throwable
+     {
+         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+ 
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+ 
+         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + tupleTypeDef + ' ' +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup;$$;");
+         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       Double.valueOf(tup.getDouble(0));$$;");
+         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getList(1, Double.class);$$;");
+         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getSet(2, String.class);$$;");
+         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         Object t = tuple(1d, list, set, map);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                    row(1d));
+         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                    row(list));
+         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                    row(set));
+         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                    row(map));
+ 
+         // same test - but via native protocol
+         // we use protocol V3 here to encode the expected version because the server
+         // always serializes Collections using V3 - see CollectionSerializer's
+         // serialize and deserialize methods.
 -        TupleType tType = tupleTypeOf(Server.VERSION_3,
++        TupleType tType = tupleTypeOf(ProtocolVersion.V3,
+                                       DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+         TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                           row(tup));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                           row(1d));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                           row(list));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                           row(set));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                           row(map));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeWithUse() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             executeNet(version, "USE " + KEYSPACE);
+ 
+             executeNet(version,
+                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS " + type + " " +
+                        "LANGUAGE java " +
+                        "AS $$return " +
+                        "     udt;$$;");
+             try
+             {
+                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                 Assert.assertEquals(1, rowsNet.size());
+                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                 Assert.assertEquals("one", udtVal.getString("txt"));
+                 Assert.assertEquals(1, udtVal.getInt("i"));
+             }
+             finally
+             {
+                 executeNet(version, "DROP FUNCTION f_use1");
+             }
+         }
+     }
+ 
+     @Test
+     public void testJavaUserType() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt0 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + " " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt;$$;");
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+         {
+             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+             Assert.assertEquals(1, rowsNet.size());
+             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+             Assert.assertEquals("one", udtVal.getString("txt"));
+             Assert.assertEquals(1, udtVal.getInt("i"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                           row("one"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                           row(1));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeRenameField() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return udt.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+ 
+         execute("ALTER TYPE " + type + " RENAME txt TO str");
+ 
+         assertInvalidMessage("txt is not a field defined in this UDT",
+                              "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+ 
+         execute("ALTER TYPE " + type + " RENAME str TO txt");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+     }
+ 
+     @Test
+     public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName1replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + ") " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS text " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt.getString(\"txt\");$$;");
+         String fName2replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS int " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS double " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS " + type + " " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt;$$;");
+ 
+         String fName1noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS text " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt.getString(\"txt\");$$;");
+         String fName2noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS int " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS double " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS " + type + " " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt;$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
+         // add field
+ 
+         execute("ALTER TYPE " + type + " ADD added double");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+ 
+         // note: type references of functions remain at the state _before_ the type mutation
+         // means we need to recreate the functions
+ 
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt.getString(\"txt\");$$;",
+                               fName1replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName1replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS int " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                               fName2replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName2replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS double " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                               fName3replace, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName3replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS %s " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt;$$;",
+                               fName4replace, type, type));
+         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName4replace)).size());
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         // un-replaced functions will work since the user type has changed
+         // and the UDF has exchanged the user type reference
+ 
+         assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         execute("DROP FUNCTION " + fName1replace);
+         execute("DROP FUNCTION " + fName2replace);
+         execute("DROP FUNCTION " + fName3replace);
+         execute("DROP FUNCTION " + fName4replace);
+         execute("DROP FUNCTION " + fName1noReplace);
+         execute("DROP FUNCTION " + fName2noReplace);
+         execute("DROP FUNCTION " + fName3noReplace);
+         execute("DROP FUNCTION " + fName4noReplace);
+     }
+ 
+     @Test
+     public void testJavaUTCollections() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row("three", "one", "two"));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testAllNativeTypes() throws Throwable
+     {
+         StringBuilder sig = new StringBuilder();
+         StringBuilder args = new StringBuilder();
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
+             if (type == CQL3Type.Native.EMPTY)
+                 continue;
+ 
+             if (sig.length() > 0)
+                 sig.append(',');
+             sig.append(type.toString());
+ 
+             if (args.length() > 0)
+                 args.append(',');
+             args.append("arg").append(type.toString()).append(' ').append(type.toString());
+         }
+         createFunction(KEYSPACE, sig.toString(),
+                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS int " +
+                        "LANGUAGE JAVA\n" +
+                        "AS 'return 0;'");
+ 
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
+             if (type == CQL3Type.Native.EMPTY)
+                 continue;
+ 
+             createFunction(KEYSPACE_PER_TEST, type.toString(),
+                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                            "RETURNS NULL ON NULL INPUT " +
+                            "RETURNS int " +
+                            "LANGUAGE JAVA\n" +
+                            "AS 'return 0;'");
+         }
+     }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
index 0000000,af3c894..02a13e7
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@@ -1,0 -1,428 +1,429 @@@
+ /*
+  * 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.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.util.Arrays;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ import java.util.UUID;
+ 
+ import org.junit.Assert;
+ import org.junit.Test;
+ 
+ import org.apache.cassandra.config.DatabaseDescriptor;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
++import org.apache.cassandra.transport.ProtocolVersion;
+ import org.apache.cassandra.utils.UUIDGen;
+ 
+ public class UFScriptTest extends CQLTester
+ {
+     // Just JavaScript UDFs to check how UDF - especially security/class-loading/sandboxing stuff -
+     // behaves, if no Java UDF has been executed before.
+ 
+     // Do not add any other test here - especially none using Java UDFs
+ 
+     @Test
+     public void testJavascriptSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                        "CREATE FUNCTION %s( lst list<double> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS list<double> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'lst;';");
+         String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                        "CREATE FUNCTION %s( st set<text> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS set<text> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'st;';");
+         String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                        "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS map<int, boolean> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'mp;';");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavascriptTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavascriptUserType() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + ' ' +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt;$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt3 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getInt(\"i\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+     }
+ 
+     @Test
+     public void testJavascriptUTCollections() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "        lst.get(1).getString(\"txt\");$$;");
+         createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        st.iterator().next().getString(\"txt\");$$;");
+         createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 // list<frozen<UDT>>
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 // set<frozen<UDT>>
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 // map<int, frozen<UDT>>
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                    row("three"));
+         assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                    row("two"));
+ 
+         String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+         assertRows(execute(cqlSelect),
+                    row("three", "one", "two"));
+ 
+         // same test - but via native protocol
 -        for (int version : PROTOCOL_VERSIONS)
++        for (ProtocolVersion version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, cqlSelect),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testJavascriptFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
+         assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("javascript", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavascriptBadReturnType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '\"string\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ClassCastException
+         assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavascriptThrow() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'throw \"fool\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ScriptException
+         assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testScriptReturnTypeCasting() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+ 
+         Object[][] variations = {
+         new Object[]    {   "true",     "boolean",  true    },
+         new Object[]    {   "false",    "boolean",  false   },
+         new Object[]    {   "100",      "tinyint",  (byte)100 },
+         new Object[]    {   "100.",     "tinyint",  (byte)100 },
+         new Object[]    {   "100",      "smallint", (short)100 },
+         new Object[]    {   "100.",     "smallint", (short)100 },
+         new Object[]    {   "100",      "int",      100     },
+         new Object[]    {   "100.",     "int",      100     },
+         new Object[]    {   "100",      "double",   100d    },
+         new Object[]    {   "100.",     "double",   100d    },
+         new Object[]    {   "100",      "bigint",   100L    },
+         new Object[]    {   "100.",     "bigint",   100L    },
+         new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+         new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+         new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+         new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object functionBody = variation[0];
+             Object returnType = variation[1];
+             Object expectedResult = variation[2];
+ 
+             String fName = createFunction(KEYSPACE, "double",
+                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " +returnType + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS '" + functionBody + ";';");
+             assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                        row(1, 1d, expectedResult));
+         }
+     }
+ 
+     @Test
+     public void testScriptParamReturnTypes() throws Throwable
+     {
+         UUID ruuid = UUID.randomUUID();
+         UUID tuuid = UUIDGen.getTimeUUID();
+ 
+         createTable("CREATE TABLE %s (key int primary key, " +
+                     "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                     "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+         execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                 (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+ 
+         Object[][] variations = {
+         new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+         new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+         new Object[] {  "int",      "ival",     1,                      2  },
+         new Object[] {  "bigint",   "lval",     1L,                     2L  },
+         new Object[] {  "float",    "fval",     1f,                     2f  },
+         new Object[] {  "double",   "dval",     1d,                     2d  },
+         new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+         new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+         new Object[] {  "time",     "timval",   1L,                     2L  },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val+1;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+ 
+         variations = new Object[][] {
+         new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+         new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+         new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+         new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+     }
+ 
+     @Test
+     public void testJavascriptDisabled() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         DatabaseDescriptor.enableScriptedUserDefinedFunctions(false);
+         try
+         {
+             assertInvalid("double",
+                           "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".assertNotEnabled(val double) " +
+                           "RETURNS NULL ON NULL INPUT " +
+                           "RETURNS double " +
+                           "LANGUAGE javascript\n" +
+                           "AS 'Math.sin(val);';");
+         }
+         finally
+         {
+             DatabaseDescriptor.enableScriptedUserDefinedFunctions(true);
+         }
+     }
+ 
+     @Test
+     public void testJavascriptCompileFailure() throws Throwable
+     {
+         assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE javascript\n" +
+                              "AS 'foo bar';");
+     }
+ 
+     @Test
+     public void testScriptInvalidLanguage() throws Throwable
+     {
+         assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
+                              "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE artificial_intelligence\n" +
+                              "AS 'question for 42?';");
+     }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d7b6b7a3/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index 1eccc3f,8a743ea..c54982e
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@@ -18,46 -18,28 +18,31 @@@
  package org.apache.cassandra.cql3.validation.entities;
  
  import java.nio.ByteBuffer;
- import java.security.AccessControlException;
  import java.util.ArrayList;
- import java.util.Arrays;
  import java.util.Date;
  import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.TreeMap;
- import java.util.TreeSet;
- import java.util.UUID;
  
 +import com.google.common.reflect.TypeToken;
  import org.junit.Assert;
  import org.junit.Test;
  
 +import com.datastax.driver.core.*;
- import com.datastax.driver.core.DataType;
  import com.datastax.driver.core.exceptions.InvalidQueryException;
- import org.apache.cassandra.config.Config;
- import org.apache.cassandra.config.DatabaseDescriptor;
  import org.apache.cassandra.config.Schema;
- import org.apache.cassandra.cql3.CQL3Type;
  import org.apache.cassandra.cql3.CQLTester;
  import org.apache.cassandra.cql3.QueryProcessor;
  import org.apache.cassandra.cql3.UntypedResultSet;
  import org.apache.cassandra.cql3.functions.FunctionName;
 +import org.apache.cassandra.cql3.functions.JavaBasedUDFunction;
  import org.apache.cassandra.cql3.functions.UDFunction;
- import org.apache.cassandra.cql3.functions.UDHelper;
  import org.apache.cassandra.db.marshal.CollectionType;
- import org.apache.cassandra.exceptions.FunctionExecutionException;
  import org.apache.cassandra.exceptions.InvalidRequestException;
  import org.apache.cassandra.schema.KeyspaceMetadata;
  import org.apache.cassandra.service.ClientState;
- import org.apache.cassandra.service.ClientWarn;
 -import org.apache.cassandra.transport.Event;
 -import org.apache.cassandra.transport.Server;
 +import org.apache.cassandra.transport.*;
 +import org.apache.cassandra.transport.ProtocolVersion;
  import org.apache.cassandra.transport.messages.ResultMessage;
  import org.apache.cassandra.utils.ByteBufferUtil;
- import org.apache.cassandra.utils.UUIDGen;
  
  public class UFTest extends CQLTester
  {


[19/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
index 0000000,d3050a5..af3c894
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@@ -1,0 -1,504 +1,428 @@@
+ /*
+  * 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.math.BigDecimal;
+ import java.math.BigInteger;
+ import java.util.Arrays;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ import java.util.UUID;
+ 
+ import org.junit.Assert;
 -import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
 -import com.datastax.driver.core.DataType;
 -import com.datastax.driver.core.TupleType;
 -import com.datastax.driver.core.TupleValue;
+ import org.apache.cassandra.config.DatabaseDescriptor;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
 -import org.apache.cassandra.transport.Server;
+ import org.apache.cassandra.utils.UUIDGen;
+ 
+ public class UFScriptTest extends CQLTester
+ {
 -    @BeforeClass
 -    public static void setUp()
 -    {
 -        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
 -    }
++    // Just JavaScript UDFs to check how UDF - especially security/class-loading/sandboxing stuff -
++    // behaves, if no Java UDF has been executed before.
++
++    // Do not add any other test here - especially none using Java UDFs
+ 
+     @Test
+     public void testJavascriptSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                        "CREATE FUNCTION %s( lst list<double> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS list<double> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'lst;';");
+         String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                        "CREATE FUNCTION %s( st set<text> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS set<text> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'st;';");
+         String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                        "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS map<int, boolean> " +
+                                        "LANGUAGE javascript\n" +
+                                        "AS 'mp;';");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavascriptTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
 -    public void testJavascriptTupleTypeCollection() throws Throwable
 -    {
 -        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
 -        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
 -
 -        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup;$$;");
 -        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS double " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getDouble(0);$$;");
 -        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS list<double> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
 -        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS set<text> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
 -        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
 -                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
 -                                      "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS map<int, boolean> " +
 -                                      "LANGUAGE javascript\n" +
 -                                      "AS $$" +
 -                                      "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
 -
 -        List<Double> list = Arrays.asList(1d, 2d, 3d);
 -        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
 -        Map<Integer, Boolean> map = new TreeMap<>();
 -        map.put(1, true);
 -        map.put(2, false);
 -        map.put(3, true);
 -
 -        Object t = tuple(1d, list, set, map);
 -
 -        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
 -
 -        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
 -                   row(t));
 -        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
 -                   row(1d));
 -        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
 -                   row(list));
 -        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
 -                   row(set));
 -        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
 -                   row(map));
 -
 -        // same test - but via native protocol
 -        TupleType tType = TupleType.of(DataType.cdouble(),
 -                                       DataType.list(DataType.cdouble()),
 -                                       DataType.set(DataType.text()),
 -                                       DataType.map(DataType.cint(), DataType.cboolean()));
 -        TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
 -        {
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
 -                          row(tup));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
 -                          row(1d));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
 -                          row(list));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
 -                          row(set));
 -            assertRowsNet(version,
 -                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
 -                          row(map));
 -        }
 -    }
 -
 -    @Test
+     public void testJavascriptUserType() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
 -                                      "RETURNS " + type + " " +
++                                      "RETURNS " + type + ' ' +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt;$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt3 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "     udt.getInt(\"i\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+     }
+ 
+     @Test
+     public void testJavascriptUTCollections() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS $$" +
+                                       "        lst.get(1).getString(\"txt\");$$;");
+         createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        st.iterator().next().getString(\"txt\");$$;");
+         createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                                "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                "RETURNS NULL ON NULL INPUT " +
+                                "RETURNS text " +
+                                "LANGUAGE javascript\n" +
+                                "AS $$" +
+                                "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 // list<frozen<UDT>>
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 // set<frozen<UDT>>
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 // map<int, frozen<UDT>>
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                    row("three"));
+         assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                    row("two"));
+ 
+         String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+         assertRows(execute(cqlSelect),
+                    row("three", "one", "two"));
+ 
+         // same test - but via native protocol
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, cqlSelect),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
+     public void testJavascriptFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("javascript", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavascriptBadReturnType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS '\"string\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ClassCastException
+         assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavascriptThrow() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'throw \"fool\";';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         // throws IRE with ScriptException
+         assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
 -    public void testJavascriptCompileFailure() throws Throwable
 -    {
 -        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
 -                             "RETURNS NULL ON NULL INPUT " +
 -                             "RETURNS double " +
 -                             "LANGUAGE javascript\n" +
 -                             "AS 'foo bar';");
 -    }
 -
 -    @Test
 -    public void testScriptInvalidLanguage() throws Throwable
 -    {
 -        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
 -                             "RETURNS NULL ON NULL INPUT " +
 -                             "RETURNS double " +
 -                             "LANGUAGE artificial_intelligence\n" +
 -                             "AS 'question for 42?';");
 -    }
 -
 -    @Test
+     public void testScriptReturnTypeCasting() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+ 
+         Object[][] variations = {
+         new Object[]    {   "true",     "boolean",  true    },
+         new Object[]    {   "false",    "boolean",  false   },
+         new Object[]    {   "100",      "tinyint",  (byte)100 },
+         new Object[]    {   "100.",     "tinyint",  (byte)100 },
+         new Object[]    {   "100",      "smallint", (short)100 },
+         new Object[]    {   "100.",     "smallint", (short)100 },
+         new Object[]    {   "100",      "int",      100     },
+         new Object[]    {   "100.",     "int",      100     },
+         new Object[]    {   "100",      "double",   100d    },
+         new Object[]    {   "100.",     "double",   100d    },
+         new Object[]    {   "100",      "bigint",   100L    },
+         new Object[]    {   "100.",     "bigint",   100L    },
+         new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+         new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+         new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+         new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object functionBody = variation[0];
+             Object returnType = variation[1];
+             Object expectedResult = variation[2];
+ 
+             String fName = createFunction(KEYSPACE, "double",
+                                           "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " +returnType + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS '" + functionBody + ";';");
+             assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                        row(1, 1d, expectedResult));
+         }
+     }
+ 
+     @Test
+     public void testScriptParamReturnTypes() throws Throwable
+     {
+         UUID ruuid = UUID.randomUUID();
+         UUID tuuid = UUIDGen.getTimeUUID();
+ 
+         createTable("CREATE TABLE %s (key int primary key, " +
+                     "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                     "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+         execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                 (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+ 
+         Object[][] variations = {
+         new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+         new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+         new Object[] {  "int",      "ival",     1,                      2  },
+         new Object[] {  "bigint",   "lval",     1L,                     2L  },
+         new Object[] {  "float",    "fval",     1f,                     2f  },
+         new Object[] {  "double",   "dval",     1d,                     2d  },
+         new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+         new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+         new Object[] {  "time",     "timval",   1L,                     2L  },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val+1;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+ 
+         variations = new Object[][] {
+         new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+         new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+         new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+         new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+         };
+ 
+         for (Object[] variation : variations)
+         {
+             Object type = variation[0];
+             Object col = variation[1];
+             Object expected1 = variation[2];
+             Object expected2 = variation[3];
+             String fName = createFunction(KEYSPACE, type.toString(),
+                                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                           "RETURNS NULL ON NULL INPUT " +
+                                           "RETURNS " + type + ' ' +
+                                           "LANGUAGE javascript " +
+                                           "AS 'val;';");
+             assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                        row(1, expected1, expected2));
+         }
+     }
++
++    @Test
++    public void testJavascriptDisabled() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, val double)");
++
++        DatabaseDescriptor.enableScriptedUserDefinedFunctions(false);
++        try
++        {
++            assertInvalid("double",
++                          "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".assertNotEnabled(val double) " +
++                          "RETURNS NULL ON NULL INPUT " +
++                          "RETURNS double " +
++                          "LANGUAGE javascript\n" +
++                          "AS 'Math.sin(val);';");
++        }
++        finally
++        {
++            DatabaseDescriptor.enableScriptedUserDefinedFunctions(true);
++        }
++    }
++
++    @Test
++    public void testJavascriptCompileFailure() throws Throwable
++    {
++        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
++                             "RETURNS NULL ON NULL INPUT " +
++                             "RETURNS double " +
++                             "LANGUAGE javascript\n" +
++                             "AS 'foo bar';");
++    }
++
++    @Test
++    public void testScriptInvalidLanguage() throws Throwable
++    {
++        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
++                             "RETURNS NULL ON NULL INPUT " +
++                             "RETURNS double " +
++                             "LANGUAGE artificial_intelligence\n" +
++                             "AS 'question for 42?';");
++    }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
index 0000000,0000000..5c7ca2b
new file mode 100644
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFSecurityTest.java
@@@ -1,0 -1,0 +1,258 @@@
++/*
++ * 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.security.AccessControlException;
++import java.util.List;
++
++import org.junit.Assert;
++import org.junit.Test;
++
++import org.apache.cassandra.config.Config;
++import org.apache.cassandra.config.DatabaseDescriptor;
++import org.apache.cassandra.cql3.CQLTester;
++import org.apache.cassandra.cql3.functions.UDHelper;
++import org.apache.cassandra.exceptions.FunctionExecutionException;
++import org.apache.cassandra.service.ClientWarn;
++
++public class UFSecurityTest extends CQLTester
++{
++    @Test
++    public void testSecurityPermissions() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, dval double)");
++        execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
++
++        // Java UDFs
++
++        try
++        {
++            String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                          "RETURNS NULL ON NULL INPUT " +
++                                          "RETURNS double " +
++                                          "LANGUAGE JAVA\n" +
++                                          "AS 'System.getProperty(\"foo.bar.baz\"); return 0d;';");
++            execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++            Assert.fail();
++        }
++        catch (FunctionExecutionException e)
++        {
++            assertAccessControlException("System.getProperty(\"foo.bar.baz\"); return 0d;", e);
++        }
++
++        String[][] typesAndSources =
++        {
++        {"", "try { Class.forName(\"" + UDHelper.class.getName() + "\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
++        {"sun.misc.Unsafe",         "sun.misc.Unsafe.getUnsafe(); return 0d;"},
++        {"",                        "try { Class.forName(\"sun.misc.Unsafe\"); } catch (Exception e) { throw new RuntimeException(e); } return 0d;"},
++        {"java.nio.file.FileSystems", "try {" +
++                                      "     java.nio.file.FileSystems.getDefault(); return 0d;" +
++                                      "} catch (Exception t) {" +
++                                      "     throw new RuntimeException(t);" +
++                                      '}'},
++        {"java.nio.channels.FileChannel", "try {" +
++                                          "     java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")).close(); return 0d;" +
++                                          "} catch (Exception t) {" +
++                                          "     throw new RuntimeException(t);" +
++                                          '}'},
++        {"java.nio.channels.SocketChannel", "try {" +
++                                            "     java.nio.channels.SocketChannel.open().close(); return 0d;" +
++                                            "} catch (Exception t) {" +
++                                            "     throw new RuntimeException(t);" +
++                                            '}'},
++        {"java.io.FileInputStream", "try {" +
++                                    "     new java.io.FileInputStream(\"./foobar\").close(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.lang.Runtime",       "try {" +
++                                    "     java.lang.Runtime.getRuntime(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"org.apache.cassandra.service.StorageService",
++         "try {" +
++         "     org.apache.cassandra.service.StorageService v = org.apache.cassandra.service.StorageService.instance; v.isShutdown(); return 0d;" +
++         "} catch (Exception t) {" +
++         "     throw new RuntimeException(t);" +
++         '}'},
++        {"java.net.ServerSocket",   "try {" +
++                                    "     new java.net.ServerSocket().bind(); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.io.FileOutputStream","try {" +
++                                    "     new java.io.FileOutputStream(\".foo\"); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'},
++        {"java.lang.Runtime",       "try {" +
++                                    "     java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); return 0d;" +
++                                    "} catch (Exception t) {" +
++                                    "     throw new RuntimeException(t);" +
++                                    '}'}
++        };
++
++        for (String[] typeAndSource : typesAndSources)
++        {
++            assertInvalidMessage(typeAndSource[0] + " cannot be resolved",
++                                 "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".invalid_class_access(val double) " +
++                                 "RETURNS NULL ON NULL INPUT " +
++                                 "RETURNS double " +
++                                 "LANGUAGE JAVA\n" +
++                                 "AS '" + typeAndSource[1] + "';");
++        }
++
++        // JavaScript UDFs
++
++        try
++        {
++            String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                          "RETURNS NULL ON NULL INPUT " +
++                                          "RETURNS double " +
++                                          "LANGUAGE javascript\n" +
++                                          "AS 'org.apache.cassandra.service.StorageService.instance.isShutdown(); 0;';");
++            execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++            Assert.fail("Javascript security check failed");
++        }
++        catch (FunctionExecutionException e)
++        {
++            assertAccessControlException("", e);
++        }
++
++        String[] javascript =
++        {
++        "java.lang.management.ManagmentFactory.getThreadMXBean(); 0;",
++        "new java.io.FileInputStream(\"/tmp/foo\"); 0;",
++        "new java.io.FileOutputStream(\"/tmp/foo\"); 0;",
++        "java.nio.file.FileSystems.getDefault().createFileExclusively(\"./foo_bar_baz\"); 0;",
++        "java.nio.channels.FileChannel.open(java.nio.file.FileSystems.getDefault().getPath(\"/etc/passwd\")); 0;",
++        "java.nio.channels.SocketChannel.open(); 0;",
++        "new java.net.ServerSocket().bind(null); 0;",
++        "var thread = new java.lang.Thread(); thread.start(); 0;",
++        "java.lang.System.getProperty(\"foo.bar.baz\"); 0;",
++        "java.lang.Class.forName(\"java.lang.System\"); 0;",
++        "java.lang.Runtime.getRuntime().exec(\"/tmp/foo\"); 0;",
++        "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
++        "java.lang.Runtime.getRuntime().loadLibrary(\"foobar\"); 0;",
++        // TODO these (ugly) calls are still possible - these can consume CPU (as one could do with an evil loop, too)
++//        "java.lang.Runtime.getRuntime().traceMethodCalls(true); 0;",
++//        "java.lang.Runtime.getRuntime().gc(); 0;",
++//        "java.lang.Runtime.getRuntime(); 0;",
++        };
++
++        for (String script : javascript)
++        {
++            try
++            {
++                String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                              "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                              "RETURNS NULL ON NULL INPUT " +
++                                              "RETURNS double " +
++                                              "LANGUAGE javascript\n" +
++                                              "AS '" + script + "';");
++                execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++                Assert.fail("Javascript security check failed: " + script);
++            }
++            catch (FunctionExecutionException e)
++            {
++                assertAccessControlException(script, e);
++            }
++        }
++    }
++
++    private static void assertAccessControlException(String script, FunctionExecutionException e)
++    {
++        for (Throwable t = e; t != null && t != t.getCause(); t = t.getCause())
++            if (t instanceof AccessControlException)
++                return;
++        Assert.fail("no AccessControlException for " + script + " (got " + e + ')');
++    }
++
++    @Test
++    public void testAmokUDF() throws Throwable
++    {
++        createTable("CREATE TABLE %s (key int primary key, dval double)");
++        execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
++
++        long udfWarnTimeout = DatabaseDescriptor.getUserDefinedFunctionWarnTimeout();
++        long udfFailTimeout = DatabaseDescriptor.getUserDefinedFunctionFailTimeout();
++        int maxTries = 5;
++        for (int i = 1; i <= maxTries; i++)
++        {
++            try
++            {
++                // short timeout
++                DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(10);
++                DatabaseDescriptor.setUserDefinedFunctionFailTimeout(250);
++                // don't kill the unit test... - default policy is "die"
++                DatabaseDescriptor.setUserFunctionTimeoutPolicy(Config.UserFunctionTimeoutPolicy.ignore);
++
++                ClientWarn.instance.captureWarnings();
++                String fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                              "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                              "RETURNS NULL ON NULL INPUT " +
++                                              "RETURNS double " +
++                                              "LANGUAGE JAVA\n" +
++                                              "AS 'long t=System.currentTimeMillis()+110; while (t>System.currentTimeMillis()) { }; return 0d;'");
++                execute("SELECT " + fName + "(dval) FROM %s WHERE key=1");
++                List<String> warnings = ClientWarn.instance.getWarnings();
++                Assert.assertNotNull(warnings);
++                Assert.assertFalse(warnings.isEmpty());
++                ClientWarn.instance.resetWarnings();
++
++                // Java UDF
++
++                fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                       "RETURNS NULL ON NULL INPUT " +
++                                       "RETURNS double " +
++                                       "LANGUAGE JAVA\n" +
++                                       "AS 'long t=System.currentTimeMillis()+500; while (t>System.currentTimeMillis()) { }; return 0d;';");
++                assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
++
++                // Javascript UDF
++
++                fName = createFunction(KEYSPACE_PER_TEST, "double",
++                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
++                                       "RETURNS NULL ON NULL INPUT " +
++                                       "RETURNS double " +
++                                       "LANGUAGE JAVASCRIPT\n" +
++                                       "AS 'var t=java.lang.System.currentTimeMillis()+500; while (t>java.lang.System.currentTimeMillis()) { }; 0;';");
++                assertInvalidMessage("ran longer than 250ms", "SELECT " + fName + "(dval) FROM %s WHERE key=1");
++
++                return;
++            }
++            catch (Error | RuntimeException e)
++            {
++                if (i == maxTries)
++                    throw e;
++            }
++            finally
++            {
++                // reset to defaults
++                DatabaseDescriptor.setUserDefinedFunctionWarnTimeout(udfWarnTimeout);
++                DatabaseDescriptor.setUserDefinedFunctionFailTimeout(udfFailTimeout);
++            }
++        }
++    }
++
++}


[09/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
index 0000000,0000000..de98748
new file mode 100644
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTypesTest.java
@@@ -1,0 -1,0 +1,549 @@@
++/*
++ * 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.util.ArrayList;
++import java.util.Arrays;
++import java.util.Date;
++import java.util.List;
++import java.util.Map;
++import java.util.Set;
++import java.util.TreeMap;
++import java.util.TreeSet;
++import java.util.UUID;
++
++import org.junit.Assert;
++import org.junit.Test;
++
++import com.datastax.driver.core.Row;
++import org.apache.cassandra.cql3.CQLTester;
++import org.apache.cassandra.cql3.UntypedResultSet;
++import org.apache.cassandra.utils.UUIDGen;
++
++public class UFTypesTest extends CQLTester
++{
++
++    @Test
++    public void testComplexNullValues() throws Throwable
++    {
++        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
++
++        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>," +
++                    "tup frozen<tuple<double, text, int, boolean>>, udt frozen<" + type + ">)");
++
++        String fList = createFunction(KEYSPACE, "list<double>",
++                                      "CREATE FUNCTION %s( coll list<double> ) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS list<double> " +
++                                      "LANGUAGE java\n" +
++                                      "AS $$return coll;$$;");
++        String fSet = createFunction(KEYSPACE, "set<text>",
++                                     "CREATE FUNCTION %s( coll set<text> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS set<text> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return coll;$$;");
++        String fMap = createFunction(KEYSPACE, "map<int, boolean>",
++                                     "CREATE FUNCTION %s( coll map<int, boolean> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS map<int, boolean> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return coll;$$;");
++        String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
++                                     "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS tuple<double, text, int, boolean> " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return val;$$;");
++        String fUdt = createFunction(KEYSPACE, type,
++                                     "CREATE FUNCTION %s( val " + type + " ) " +
++                                     "CALLED ON NULL INPUT " +
++                                     "RETURNS " + type + " " +
++                                     "LANGUAGE java\n" +
++                                     "AS $$return val;$$;");
++        List<Double> list = Arrays.asList(1d, 2d, 3d);
++        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
++        Map<Integer, Boolean> map = new TreeMap<>();
++        map.put(1, true);
++        map.put(2, false);
++        map.put(3, true);
++        Object t = tuple(1d, "one", 42, false);
++
++        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (1, ?, ?, ?, ?, {txt: 'one', i:1})", list, set, map, t);
++        execute("INSERT INTO %s (key, lst, st, mp, tup, udt) VALUES (2, ?, ?, ?, ?, null)", null, null, null, null);
++
++        execute("SELECT " +
++                fList + "(lst), " +
++                fSet + "(st), " +
++                fMap + "(mp), " +
++                fTup + "(tup), " +
++                fUdt + "(udt) FROM %s WHERE key = 1");
++        UntypedResultSet.Row row = execute("SELECT " +
++                                           fList + "(lst) as l, " +
++                                           fSet + "(st) as s, " +
++                                           fMap + "(mp) as m, " +
++                                           fTup + "(tup) as t, " +
++                                           fUdt + "(udt) as u " +
++                                           "FROM %s WHERE key = 1").one();
++        Assert.assertNotNull(row.getBytes("l"));
++        Assert.assertNotNull(row.getBytes("s"));
++        Assert.assertNotNull(row.getBytes("m"));
++        Assert.assertNotNull(row.getBytes("t"));
++        Assert.assertNotNull(row.getBytes("u"));
++        row = execute("SELECT " +
++                      fList + "(lst) as l, " +
++                      fSet + "(st) as s, " +
++                      fMap + "(mp) as m, " +
++                      fTup + "(tup) as t, " +
++                      fUdt + "(udt) as u " +
++                      "FROM %s WHERE key = 2").one();
++        Assert.assertNull(row.getBytes("l"));
++        Assert.assertNull(row.getBytes("s"));
++        Assert.assertNull(row.getBytes("m"));
++        Assert.assertNull(row.getBytes("t"));
++        Assert.assertNull(row.getBytes("u"));
++
++        for (int version : PROTOCOL_VERSIONS)
++        {
++            Row r = executeNet(version, "SELECT " +
++                                        fList + "(lst) as l, " +
++                                        fSet + "(st) as s, " +
++                                        fMap + "(mp) as m, " +
++                                        fTup + "(tup) as t, " +
++                                        fUdt + "(udt) as u " +
++                                        "FROM %s WHERE key = 1").one();
++            Assert.assertNotNull(r.getBytesUnsafe("l"));
++            Assert.assertNotNull(r.getBytesUnsafe("s"));
++            Assert.assertNotNull(r.getBytesUnsafe("m"));
++            Assert.assertNotNull(r.getBytesUnsafe("t"));
++            Assert.assertNotNull(r.getBytesUnsafe("u"));
++            r = executeNet(version, "SELECT " +
++                                    fList + "(lst) as l, " +
++                                    fSet + "(st) as s, " +
++                                    fMap + "(mp) as m, " +
++                                    fTup + "(tup) as t, " +
++                                    fUdt + "(udt) as u " +
++                                    "FROM %s WHERE key = 2").one();
++            Assert.assertNull(r.getBytesUnsafe("l"));
++            Assert.assertNull(r.getBytesUnsafe("s"));
++            Assert.assertNull(r.getBytesUnsafe("m"));
++            Assert.assertNull(r.getBytesUnsafe("t"));
++            Assert.assertNull(r.getBytesUnsafe("u"));
++        }
++    }
++
++    private static class TypesTestDef
++    {
++        final String udfType;
++        final String tableType;
++        final String columnName;
++        final Object referenceValue;
++
++        String fCheckArgAndReturn;
++
++        String fCalledOnNull;
++        String fReturnsNullOnNull;
++
++        TypesTestDef(String udfType, String tableType, String columnName, Object referenceValue)
++        {
++            this.udfType = udfType;
++            this.tableType = tableType;
++            this.columnName = columnName;
++            this.referenceValue = referenceValue;
++        }
++    }
++
++    @Test
++    public void testTypesWithAndWithoutNulls() throws Throwable
++    {
++        // test various combinations of types against UDFs with CALLED ON NULL or RETURNS NULL ON NULL
++
++        String type = createType("CREATE TYPE %s (txt text, i int)");
++
++        TypesTestDef[] typeDefs =
++        {
++        //                udf type,            table type,                 column, reference value
++        new TypesTestDef("timestamp", "timestamp", "ts", new Date()),
++        new TypesTestDef("date", "date", "dt", 12345),
++        new TypesTestDef("time", "time", "tim", 12345L),
++        new TypesTestDef("uuid", "uuid", "uu", UUID.randomUUID()),
++        new TypesTestDef("timeuuid", "timeuuid", "tu", UUIDGen.getTimeUUID()),
++        new TypesTestDef("tinyint", "tinyint", "ti", (byte) 42),
++        new TypesTestDef("smallint", "smallint", "si", (short) 43),
++        new TypesTestDef("int", "int", "i", 44),
++        new TypesTestDef("bigint", "bigint", "b", 45L),
++        new TypesTestDef("float", "float", "f", 46f),
++        new TypesTestDef("double", "double", "d", 47d),
++        new TypesTestDef("boolean", "boolean", "x", true),
++        new TypesTestDef("ascii", "ascii", "a", "tqbfjutld"),
++        new TypesTestDef("text", "text", "t", "k\u00f6lsche jung"),
++        //new TypesTestDef(type,                 "frozen<" + type + '>',     "u",    null),
++        new TypesTestDef("tuple<int, text>", "frozen<tuple<int, text>>", "tup", tuple(1, "foo"))
++        };
++
++        String createTableDDL = "CREATE TABLE %s (key int PRIMARY KEY";
++        String insertDML = "INSERT INTO %s (key";
++        List<Object> values = new ArrayList<>();
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            createTableDDL += ", " + typeDef.columnName + ' ' + typeDef.tableType;
++            insertDML += ", " + typeDef.columnName;
++            String typeName = typeDef.udfType;
++            typeDef.fCheckArgAndReturn = createFunction(KEYSPACE,
++                                                        typeName,
++                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                        "CALLED ON NULL INPUT " +
++                                                        "RETURNS " + typeName + ' ' +
++                                                        "LANGUAGE java\n" +
++                                                        "AS 'return val;';");
++            typeDef.fCalledOnNull = createFunction(KEYSPACE,
++                                                   typeName,
++                                                   "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                   "CALLED ON NULL INPUT " +
++                                                   "RETURNS text " +
++                                                   "LANGUAGE java\n" +
++                                                   "AS 'return \"called\";';");
++            typeDef.fReturnsNullOnNull = createFunction(KEYSPACE,
++                                                        typeName,
++                                                        "CREATE OR REPLACE FUNCTION %s(val " + typeName + ") " +
++                                                        "RETURNS NULL ON NULL INPUT " +
++                                                        "RETURNS text " +
++                                                        "LANGUAGE java\n" +
++                                                        "AS 'return \"called\";';");
++            values.add(typeDef.referenceValue);
++        }
++
++        createTableDDL += ')';
++        createTable(createTableDDL);
++
++        insertDML += ") VALUES (1";
++        for (TypesTestDef ignored : typeDefs)
++            insertDML += ", ?";
++        insertDML += ')';
++
++        execute(insertDML, values.toArray());
++
++        // second row with null values
++        for (int i = 0; i < values.size(); i++)
++            values.set(i, null);
++        execute(insertDML.replace('1', '2'), values.toArray());
++
++        // check argument input + return
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCheckArgAndReturn + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ typeDef.referenceValue }));
++        }
++
++        // check for CALLED ON NULL INPUT with non-null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for CALLED ON NULL INPUT with null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fCalledOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for RETURNS NULL ON NULL INPUT with non-null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 1"),
++                       row(new Object[]{ "called" }));
++        }
++
++        // check for RETURNS NULL ON NULL INPUT with null arguments
++        for (TypesTestDef typeDef : typeDefs)
++        {
++            assertRows(execute("SELECT " + typeDef.fReturnsNullOnNull + '(' + typeDef.columnName + ") FROM %s WHERE key = 2"),
++                       row(new Object[]{ null }));
++        }
++
++    }
++
++    @Test
++    public void testFunctionWithFrozenSetType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<set<int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "set<int>",
++                                             "CREATE FUNCTION %s (values set<int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "set<int>",
++                                      "CREATE FUNCTION %s (values set<int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS set<int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenListType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<list<int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "list<int>",
++                                             "CREATE FUNCTION %s (values list<int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "list<int>",
++                                      "CREATE FUNCTION %s (values list<int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS list<int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenMapType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
++        createIndex("CREATE INDEX ON %s (FULL(b))");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS int " +
++                             "LANGUAGE java\n" +
++                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<map<int, int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "map<int, int>",
++                                             "CREATE FUNCTION %s (values map<int, int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS int " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, 0));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, 6));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, 15));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, 24));
++
++        functionName = createFunction(KEYSPACE,
++                                      "map<int, int>",
++                                      "CREATE FUNCTION %s (values map<int, int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS map<int, int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenTupleType() throws Throwable
++    {
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
++        createIndex("CREATE INDEX ON %s (b)");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
++        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS text " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values.toString();';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<tuple<int, int>> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             "tuple<int, int>",
++                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS text " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'return values.toString();';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "(NULL,NULL)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "(1,2)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "(4,5)"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "(7,8)"));
++
++        functionName = createFunction(KEYSPACE,
++                                      "tuple<int, int>",
++                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS tuple<int, int> " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
++    }
++
++    @Test
++    public void testFunctionWithFrozenUDType() throws Throwable
++    {
++        String myType = createType("CREATE TYPE %s (f int)");
++        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
++        createIndex("CREATE INDEX ON %s (b)");
++
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
++        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS text " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values.toString();';");
++
++        assertInvalidMessage("The function return type should not be frozen",
++                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
++                             "CALLED ON NULL INPUT " +
++                             "RETURNS frozen<" + myType + "> " +
++                             "LANGUAGE java\n" +
++                             "AS 'return values;';");
++
++        String functionName = createFunction(KEYSPACE,
++                                             myType,
++                                             "CREATE FUNCTION %s (values " + myType + ") " +
++                                             "CALLED ON NULL INPUT " +
++                                             "RETURNS text " +
++                                             "LANGUAGE java\n" +
++                                             "AS 'return values.toString();';");
++
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 0"), row(0, "{f:0}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 1"), row(1, "{f:1}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 2"), row(2, "{f:4}"));
++        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s WHERE a = 3"), row(3, "{f:7}"));
++
++        functionName = createFunction(KEYSPACE,
++                                      myType,
++                                      "CREATE FUNCTION %s (values " + myType + ") " +
++                                      "CALLED ON NULL INPUT " +
++                                      "RETURNS " + myType + " " +
++                                      "LANGUAGE java\n" +
++                                      "AS 'return values;';");
++
++        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
++                   row(1));
++
++        assertInvalidMessage("The function arguments should not be frozen",
++                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
++    }
++}


[04/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Posted by sn...@apache.org.
testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

patch by Robert Stupp; reviewed by Alex Petrov for CASSANDRA-12817


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/0b97c5d1
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/0b97c5d1
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/0b97c5d1

Branch: refs/heads/cassandra-3.0
Commit: 0b97c5d1f717be30a04c59c766465d9c62a4e9ee
Parents: 2e93398
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:06:55 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:06:55 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    | 1177 +++++++++++++
 .../cql3/validation/entities/UFScriptTest.java  |  504 ++++++
 .../cql3/validation/entities/UFTest.java        | 1608 +-----------------
 3 files changed, 1696 insertions(+), 1593 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
new file mode 100644
index 0000000..caef808
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@ -0,0 +1,1177 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import com.datastax.driver.core.UDTValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQL3Type;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.cql3.functions.Functions;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+public class UFJavaTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+
+    @Test
+    public void testJavaFunctionNoParameters() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = "\n  return 1L;\n";
+
+        String fName = createFunction(KEYSPACE, "",
+                                      "CREATE OR REPLACE FUNCTION %s() " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" +functionBody + "';");
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           KEYSPACE, parseFunctionName(fName).name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                   row(1, 1d, 1L),
+                   row(2, 2d, 1L),
+                   row(3, 3d, 1L)
+        );
+    }
+
+    @Test
+    public void testJavaFunctionInvalidBodies() throws Throwable
+    {
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+        }
+
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz;" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+        }
+    }
+
+    @Test
+    public void testJavaFunctionInvalidReturn() throws Throwable
+    {
+        assertInvalidMessage("system keyspace is not user-modifiable",
+                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE JAVA\n" +
+                             "AS 'return 1L;';");
+    }
+
+    @Test
+    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val bigint)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return Double.valueOf(val);';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+        assertInvalidMessage("val cannot be passed as argument 0 of function",
+                             "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaFunctionCounter() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val counter)");
+
+        String fName = createFunction(KEYSPACE, "counter",
+                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return val + 1;';");
+
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1L, 2L));
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 4L, 5L));
+        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+    }
+
+    @Test
+    public void testJavaKeyspaceFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin( val );\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaRuntimeException() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  throw new RuntimeException(\"oh no!\");\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+
+        // function throws a RuntimeException which is wrapped by FunctionExecutionException
+        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaDollarQuotedFunction() throws Throwable
+    {
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (input == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE FUNCTION %s( input double ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$" + functionBody + "$$;");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+    }
+
+    @Test
+    public void testJavaSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                      "CREATE FUNCTION %s( lst list<double> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return lst;$$;");
+        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                     "CREATE FUNCTION %s( st set<text> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS set<text> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return st;$$;");
+        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS map<int, boolean> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return mp;$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavaTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavaTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + tupleTypeDef + ' ' +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup;$$;");
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       Double.valueOf(tup.getDouble(0));$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getList(1, Double.class);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getSet(2, String.class);$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeWithUse() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            executeNet(version, "USE " + KEYSPACE);
+
+            executeNet(version,
+                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS " + type + " " +
+                       "LANGUAGE java " +
+                       "AS $$return " +
+                       "     udt;$$;");
+            try
+            {
+                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                Assert.assertEquals(1, rowsNet.size());
+                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                Assert.assertEquals("one", udtVal.getString("txt"));
+                Assert.assertEquals(1, udtVal.getInt("i"));
+            }
+            finally
+            {
+                executeNet(version, "DROP FUNCTION f_use1");
+            }
+        }
+    }
+
+    @Test
+    public void testJavaUserType() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt0 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt;$$;");
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+            Assert.assertEquals(1, rowsNet.size());
+            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+            Assert.assertEquals("one", udtVal.getString("txt"));
+            Assert.assertEquals(1, udtVal.getInt("i"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                          row("one"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                          row(1));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeRenameField() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return udt.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+
+        execute("ALTER TYPE " + type + " RENAME txt TO str");
+
+        assertInvalidMessage("txt is not a field defined in this UDT",
+                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+
+        execute("ALTER TYPE " + type + " RENAME str TO txt");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+    }
+
+    @Test
+    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName1replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + ") " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt.getString(\"txt\");$$;");
+        String fName2replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS double " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS " + type + " " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt;$$;");
+
+        String fName1noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS text " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt.getString(\"txt\");$$;");
+        String fName2noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS int " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS double " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS " + type + " " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt;$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        // add field
+
+        execute("ALTER TYPE " + type + " ADD added double");
+
+        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+
+        // note: type references of functions remain at the state _before_ the type mutation
+        // means we need to recreate the functions
+
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt.getString(\"txt\");$$;",
+                              fName1replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                              fName2replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                              fName3replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS %s " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt;$$;",
+                              fName4replace, type, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        // un-replaced functions will work since the user type has changed
+        // and the UDF has exchanged the user type reference
+
+        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        execute("DROP FUNCTION " + fName1replace);
+        execute("DROP FUNCTION " + fName2replace);
+        execute("DROP FUNCTION " + fName3replace);
+        execute("DROP FUNCTION " + fName4replace);
+        execute("DROP FUNCTION " + fName1noReplace);
+        execute("DROP FUNCTION " + fName2noReplace);
+        execute("DROP FUNCTION " + fName3noReplace);
+        execute("DROP FUNCTION " + fName4noReplace);
+    }
+
+    @Test
+    public void testJavaUTCollections() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row("three", "one", "two"));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testFunctionWithFrozenSetType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<set<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "set<int>",
+                                             "CREATE FUNCTION %s (values set<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "set<int>",
+                                      "CREATE FUNCTION %s (values set<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS set<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenListType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<list<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "list<int>",
+                                             "CREATE FUNCTION %s (values list<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "list<int>",
+                                      "CREATE FUNCTION %s (values list<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS list<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenMapType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<map<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "map<int, int>",
+                                             "CREATE FUNCTION %s (values map<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "map<int, int>",
+                                      "CREATE FUNCTION %s (values map<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS map<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<tuple<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "tuple<int, int>",
+                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "(null, null)"),
+                   row(1, "(1, 2)"),
+                   row(2, "(4, 5)"),
+                   row(3, "(7, 8)"));
+
+        functionName = createFunction(KEYSPACE,
+                                      "tuple<int, int>",
+                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS tuple<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenUDType() throws Throwable
+    {
+        String myType = createType("CREATE TYPE %s (f int)");
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<" + myType + "> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             myType,
+                                             "CREATE FUNCTION %s (values " + myType + ") " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "{f:0}"),
+                   row(1, "{f:1}"),
+                   row(2, "{f:4}"),
+                   row(3, "{f:7}"));
+
+        functionName = createFunction(KEYSPACE,
+                                      myType,
+                                      "CREATE FUNCTION %s (values " + myType + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + myType + " " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
+    }
+
+    @Test
+    public void testEmptyString() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
+        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
+
+        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
+        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
+    }
+
+    @Test
+    public void testAllNativeTypes() throws Throwable
+    {
+        StringBuilder sig = new StringBuilder();
+        StringBuilder args = new StringBuilder();
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            if (sig.length() > 0)
+                sig.append(',');
+            sig.append(type.toString());
+
+            if (args.length() > 0)
+                args.append(',');
+            args.append("arg").append(type.toString()).append(' ').append(type.toString());
+        }
+        createFunction(KEYSPACE, sig.toString(),
+                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS int " +
+                       "LANGUAGE JAVA\n" +
+                       "AS 'return 0;'");
+
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            createFunction(KEYSPACE_PER_TEST, type.toString(),
+                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                           "RETURNS NULL ON NULL INPUT " +
+                           "RETURNS int " +
+                           "LANGUAGE JAVA\n" +
+                           "AS 'return 0;'");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
new file mode 100644
index 0000000..d3050a5
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@ -0,0 +1,504 @@
+/*
+ * 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.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.UUIDGen;
+
+public class UFScriptTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+    @Test
+    public void testJavascriptSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'lst;';");
+        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                       "CREATE FUNCTION %s( st set<text> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'st;';");
+        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                       "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'mp;';");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavascriptTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavascriptTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup;$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getDouble(0);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
+        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        // same test - but via native protocol
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavascriptUserType() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt;$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt3 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getInt(\"i\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+    }
+
+    @Test
+    public void testJavascriptUTCollections() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "        lst.get(1).getString(\"txt\");$$;");
+        createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        st.iterator().next().getString(\"txt\");$$;");
+        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                // list<frozen<UDT>>
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                // set<frozen<UDT>>
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                // map<int, frozen<UDT>>
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                   row("three"));
+        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                   row("two"));
+
+        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+        assertRows(execute(cqlSelect),
+                   row("three", "one", "two"));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, cqlSelect),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testJavascriptFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("javascript", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavascriptBadReturnType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '\"string\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ClassCastException
+        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptThrow() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS 'throw \"fool\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ScriptException
+        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptCompileFailure() throws Throwable
+    {
+        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE javascript\n" +
+                             "AS 'foo bar';");
+    }
+
+    @Test
+    public void testScriptInvalidLanguage() throws Throwable
+    {
+        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE artificial_intelligence\n" +
+                             "AS 'question for 42?';");
+    }
+
+    @Test
+    public void testScriptReturnTypeCasting() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+
+        Object[][] variations = {
+        new Object[]    {   "true",     "boolean",  true    },
+        new Object[]    {   "false",    "boolean",  false   },
+        new Object[]    {   "100",      "tinyint",  (byte)100 },
+        new Object[]    {   "100.",     "tinyint",  (byte)100 },
+        new Object[]    {   "100",      "smallint", (short)100 },
+        new Object[]    {   "100.",     "smallint", (short)100 },
+        new Object[]    {   "100",      "int",      100     },
+        new Object[]    {   "100.",     "int",      100     },
+        new Object[]    {   "100",      "double",   100d    },
+        new Object[]    {   "100.",     "double",   100d    },
+        new Object[]    {   "100",      "bigint",   100L    },
+        new Object[]    {   "100.",     "bigint",   100L    },
+        new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+        new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+        new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+        new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object functionBody = variation[0];
+            Object returnType = variation[1];
+            Object expectedResult = variation[2];
+
+            String fName = createFunction(KEYSPACE, "double",
+                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " +returnType + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS '" + functionBody + ";';");
+            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                       row(1, 1d, expectedResult));
+        }
+    }
+
+    @Test
+    public void testScriptParamReturnTypes() throws Throwable
+    {
+        UUID ruuid = UUID.randomUUID();
+        UUID tuuid = UUIDGen.getTimeUUID();
+
+        createTable("CREATE TABLE %s (key int primary key, " +
+                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+
+        Object[][] variations = {
+        new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+        new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+        new Object[] {  "int",      "ival",     1,                      2  },
+        new Object[] {  "bigint",   "lval",     1L,                     2L  },
+        new Object[] {  "float",    "fval",     1f,                     2f  },
+        new Object[] {  "double",   "dval",     1d,                     2d  },
+        new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+        new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+        new Object[] {  "time",     "timval",   1L,                     2L  },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val+1;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+
+        variations = new Object[][] {
+        new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+        new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+        new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+        new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+    }
+}


[16/25] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by sn...@apache.org.
Merge branch 'cassandra-2.2' into cassandra-3.0


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3aefe356
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3aefe356
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3aefe356

Branch: refs/heads/cassandra-3.0
Commit: 3aefe356545bcc2f5c4453e0d9d704bef339a008
Parents: 95d0b67 0b97c5d
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:08:35 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:08:35 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    |  797 +++++++++
 .../validation/entities/UFPureScriptTest.java   |  406 -----
 .../cql3/validation/entities/UFScriptTest.java  |  428 +++++
 .../validation/entities/UFSecurityTest.java     |  258 +++
 .../cql3/validation/entities/UFTest.java        | 1519 +-----------------
 .../cql3/validation/entities/UFTypesTest.java   |  549 +++++++
 6 files changed, 2033 insertions(+), 1924 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/3aefe356/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
index 0000000,caef808..15c8e18
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@@ -1,0 -1,1177 +1,797 @@@
+ /*
+  * 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.Arrays;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+ 
+ import org.junit.Assert;
 -import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
+ import com.datastax.driver.core.DataType;
+ import com.datastax.driver.core.Row;
+ import com.datastax.driver.core.TupleType;
+ import com.datastax.driver.core.TupleValue;
+ import com.datastax.driver.core.UDTValue;
 -import org.apache.cassandra.config.DatabaseDescriptor;
++import org.apache.cassandra.config.Schema;
+ import org.apache.cassandra.cql3.CQL3Type;
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.functions.FunctionName;
 -import org.apache.cassandra.cql3.functions.Functions;
 -import org.apache.cassandra.dht.ByteOrderedPartitioner;
+ import org.apache.cassandra.exceptions.FunctionExecutionException;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
+ import org.apache.cassandra.transport.Server;
 -import org.apache.cassandra.utils.ByteBufferUtil;
+ 
+ public class UFJavaTest extends CQLTester
+ {
 -    @BeforeClass
 -    public static void setUp()
 -    {
 -        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
 -    }
 -
 -
+     @Test
+     public void testJavaFunctionNoParameters() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = "\n  return 1L;\n";
+ 
+         String fName = createFunction(KEYSPACE, "",
+                                       "CREATE OR REPLACE FUNCTION %s() " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" +functionBody + "';");
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            KEYSPACE, parseFunctionName(fName).name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                    row(1, 1d, 1L),
+                    row(2, 2d, 1L),
+                    row(3, 3d, 1L)
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidBodies() throws Throwable
+     {
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+         }
+ 
+         try
+         {
+             execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                     "RETURNS NULL ON NULL INPUT " +
+                     "RETURNS bigint " +
+                     "LANGUAGE JAVA\n" +
+                     "AS '\n" +
+                     "foobarbaz;" +
+                     "\n';");
+             Assert.fail();
+         }
+         catch (InvalidRequestException e)
+         {
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+             Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+         }
+     }
+ 
+     @Test
+     public void testJavaFunctionInvalidReturn() throws Throwable
+     {
+         assertInvalidMessage("system keyspace is not user-modifiable",
+                              "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE JAVA\n" +
+                              "AS 'return 1L;';");
+     }
+ 
+     @Test
+     public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val bigint)");
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return Double.valueOf(val);';");
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+         assertInvalidMessage("val cannot be passed as argument 0 of function",
+                              "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin(val);\n";
+ 
+         String fName = createFunction(KEYSPACE, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaFunctionCounter() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val counter)");
+ 
+         String fName = createFunction(KEYSPACE, "counter",
+                                       "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS bigint " +
+                                       "LANGUAGE JAVA " +
+                                       "AS 'return val + 1;';");
+ 
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1L, 2L));
+         execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+         execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 4L, 5L));
+         execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 2L, 3L));
+     }
+ 
+     @Test
+     public void testJavaKeyspaceFunction() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (val == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return Math.sin( val );\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA " +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+         assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                    row(1, 1d, Math.sin(1d)),
+                    row(2, 2d, Math.sin(2d)),
+                    row(3, 3d, Math.sin(3d))
+         );
+     }
+ 
+     @Test
+     public void testJavaRuntimeException() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, val double)");
+ 
+         String functionBody = '\n' +
+                               "  throw new RuntimeException(\"oh no!\");\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE JAVA\n" +
+                                       "AS '" + functionBody + "';");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+ 
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+ 
+         // function throws a RuntimeException which is wrapped by FunctionExecutionException
+         assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                   "SELECT key, val, " + fName + "(val) FROM %s");
+     }
+ 
+     @Test
+     public void testJavaDollarQuotedFunction() throws Throwable
+     {
+         String functionBody = '\n' +
+                               "  // parameter val is of type java.lang.Double\n" +
+                               "  /* return type is of type java.lang.Double */\n" +
+                               "  if (input == null) {\n" +
+                               "    return null;\n" +
+                               "  }\n" +
+                               "  return \"'\"+Math.sin(input)+'\\\'';\n";
+ 
+         String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                       "CREATE FUNCTION %s( input double ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" + functionBody + "$$;");
+ 
+         FunctionName fNameName = parseFunctionName(fName);
+ 
 -        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
++        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
+                            fNameName.keyspace, fNameName.name),
+                    row("java", functionBody));
+     }
+ 
+     @Test
+     public void testJavaSimpleCollections() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+ 
+         String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return lst;$$;");
+         String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                      "CREATE FUNCTION %s( st set<text> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return st;$$;");
+         String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                      "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return mp;$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+ 
+         assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                    row(list, set, map));
+ 
+         // same test - but via native protocol
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                           row(list, set, map));
+     }
+ 
+     @Test
+     public void testJavaTupleType() throws Throwable
+     {
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+ 
+         String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                       "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS tuple<double, text, int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return tup;$$;");
+ 
+         Object t = tuple(1d, "foo", 2, true);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                    row(t));
+ 
+         assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+     }
+ 
+     @Test
+     public void testJavaTupleTypeCollection() throws Throwable
+     {
+         String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+ 
+         createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+ 
+         String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS " + tupleTypeDef + ' ' +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup;$$;");
+         String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS double " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       Double.valueOf(tup.getDouble(0));$$;");
+         String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getList(1, Double.class);$$;");
+         String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getSet(2, String.class);$$;");
+         String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                       "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return " +
+                                       "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+ 
+         List<Double> list = Arrays.asList(1d, 2d, 3d);
+         Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+         Map<Integer, Boolean> map = new TreeMap<>();
+         map.put(1, true);
+         map.put(2, false);
+         map.put(3, true);
+ 
+         Object t = tuple(1d, list, set, map);
+ 
+         execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+ 
+         assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                    row(t));
+         assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                    row(1d));
+         assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                    row(list));
+         assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                    row(set));
+         assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                    row(map));
+ 
 -        TupleType tType = TupleType.of(DataType.cdouble(),
 -                                       DataType.list(DataType.cdouble()),
 -                                       DataType.set(DataType.text()),
 -                                       DataType.map(DataType.cint(), DataType.cboolean()));
++        // same test - but via native protocol
++        // we use protocol V3 here to encode the expected version because the server
++        // always serializes Collections using V3 - see CollectionSerializer's
++        // serialize and deserialize methods.
++        TupleType tType = tupleTypeOf(Server.VERSION_3,
++                                      DataType.cdouble(),
++                                      DataType.list(DataType.cdouble()),
++                                      DataType.set(DataType.text()),
++                                      DataType.map(DataType.cint(), DataType.cboolean()));
+         TupleValue tup = tType.newValue(1d, list, set, map);
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                           row(tup));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                           row(1d));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                           row(list));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                           row(set));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                           row(map));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeWithUse() throws Throwable
+     {
+         String type = createType("CREATE TYPE %s (txt text, i int)");
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             executeNet(version, "USE " + KEYSPACE);
+ 
+             executeNet(version,
+                        "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS " + type + " " +
+                        "LANGUAGE java " +
+                        "AS $$return " +
+                        "     udt;$$;");
+             try
+             {
+                 List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                 Assert.assertEquals(1, rowsNet.size());
+                 UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                 Assert.assertEquals("one", udtVal.getString("txt"));
+                 Assert.assertEquals(1, udtVal.getInt("i"));
+             }
+             finally
+             {
+                 executeNet(version, "DROP FUNCTION f_use1");
+             }
+         }
+     }
+ 
+     @Test
+     public void testJavaUserType() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fUdt0 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS " + type + " " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt;$$;");
+         String fUdt1 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     udt.getString(\"txt\");$$;");
+         String fUdt2 = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + ") " +
+                                       "CALLED ON NULL INPUT " +
+                                       "RETURNS int " +
+                                       "LANGUAGE java " +
+                                       "AS $$return " +
+                                       "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+         Assert.assertEquals(1, rows.size());
+         assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+         {
+             List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+             Assert.assertEquals(1, rowsNet.size());
+             UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+             Assert.assertEquals("one", udtVal.getString("txt"));
+             Assert.assertEquals(1, udtVal.getInt("i"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                           row("one"));
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                           row(1));
+         }
+     }
+ 
+     @Test
+     public void testJavaUserTypeRenameField() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName = createFunction(KEYSPACE, type,
+                                       "CREATE FUNCTION %s( udt " + type + " ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$return udt.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+ 
+         execute("ALTER TYPE " + type + " RENAME txt TO str");
+ 
+         assertInvalidMessage("txt is not a field defined in this UDT",
+                              "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+ 
+         execute("ALTER TYPE " + type + " RENAME str TO txt");
+ 
+         assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+     }
+ 
+     @Test
+     public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+ 
+         String fName1replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + ") " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS text " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt.getString(\"txt\");$$;");
+         String fName2replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS int " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "CALLED ON NULL INPUT " +
+                                               "RETURNS double " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4replace = createFunction(KEYSPACE, type,
+                                               "CREATE FUNCTION %s( udt " + type + " ) " +
+                                               "RETURNS NULL ON NULL INPUT " +
+                                               "RETURNS " + type + " " +
+                                               "LANGUAGE java\n" +
+                                               "AS $$return udt;$$;");
+ 
+         String fName1noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS text " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt.getString(\"txt\");$$;");
+         String fName2noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS int " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+         String fName3noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "CALLED ON NULL INPUT " +
+                                                 "RETURNS double " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+         String fName4noReplace = createFunction(KEYSPACE, type,
+                                                 "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                 "RETURNS NULL ON NULL INPUT " +
+                                                 "RETURNS " + type + " " +
+                                                 "LANGUAGE java\n" +
+                                                 "AS $$return udt;$$;");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                    row("one"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                    row(1));
+ 
+         // add field
+ 
+         execute("ALTER TYPE " + type + " ADD added double");
+ 
+         execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+ 
+         // note: type references of functions remain at the state _before_ the type mutation
+         // means we need to recreate the functions
+ 
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt.getString(\"txt\");$$;",
+                               fName1replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName1replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS int " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                               fName2replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName2replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "CALLED ON NULL INPUT " +
+                               "RETURNS double " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                               fName3replace, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName3replace)).size());
+         execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS %s " +
+                               "LANGUAGE java\n" +
+                               "AS $$return " +
+                               "     udt;$$;",
+                               fName4replace, type, type));
 -        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
++        Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fName4replace)).size());
+ 
+         assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         // un-replaced functions will work since the user type has changed
+         // and the UDF has exchanged the user type reference
+ 
+         assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row("two"));
+         assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                    row(2d));
+         assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                    row(0d));
+ 
+         execute("DROP FUNCTION " + fName1replace);
+         execute("DROP FUNCTION " + fName2replace);
+         execute("DROP FUNCTION " + fName3replace);
+         execute("DROP FUNCTION " + fName4replace);
+         execute("DROP FUNCTION " + fName1noReplace);
+         execute("DROP FUNCTION " + fName2noReplace);
+         execute("DROP FUNCTION " + fName3noReplace);
+         execute("DROP FUNCTION " + fName4noReplace);
+     }
+ 
+     @Test
+     public void testJavaUTCollections() throws Throwable
+     {
+         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+ 
+         createTable(String.format("CREATE TABLE %%s " +
+                                   "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                   type, type, type));
+ 
+         String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+         String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                        "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                        "RETURNS NULL ON NULL INPUT " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java\n" +
+                                        "AS $$" +
+                                        "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                        "     return udtVal.getString(\"txt\");$$;");
+ 
+         execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                 "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                 "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                 "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+ 
+         assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                    row("three", "one", "two"));
+ 
 -        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
++        for (int version : PROTOCOL_VERSIONS)
+             assertRowsNet(version,
+                           executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                           row("three", "one", "two"));
+     }
+ 
+     @Test
 -    public void testFunctionWithFrozenSetType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<set<int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "set<int>",
 -                                             "CREATE FUNCTION %s (values set<int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "set<int>",
 -                                      "CREATE FUNCTION %s (values set<int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS set<int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenListType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<list<int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "list<int>",
 -                                             "CREATE FUNCTION %s (values list<int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "list<int>",
 -                                      "CREATE FUNCTION %s (values list<int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS list<int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenMapType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
 -        createIndex("CREATE INDEX ON %s (FULL(b))");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS int " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<map<int, int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "map<int, int>",
 -                                             "CREATE FUNCTION %s (values map<int, int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS int " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, 0),
 -                   row(1, 6),
 -                   row(2, 15),
 -                   row(3, 24));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "map<int, int>",
 -                                      "CREATE FUNCTION %s (values map<int, int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS map<int, int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenTupleType() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
 -        createIndex("CREATE INDEX ON %s (b)");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
 -        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS text " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values.toString();';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<tuple<int, int>> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             "tuple<int, int>",
 -                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS text " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'return values.toString();';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, "(null, null)"),
 -                   row(1, "(1, 2)"),
 -                   row(2, "(4, 5)"),
 -                   row(3, "(7, 8)"));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      "tuple<int, int>",
 -                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS tuple<int, int> " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
 -    }
 -
 -    @Test
 -    public void testFunctionWithFrozenUDType() throws Throwable
 -    {
 -        String myType = createType("CREATE TYPE %s (f int)");
 -        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
 -        createIndex("CREATE INDEX ON %s (b)");
 -
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
 -        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS text " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values.toString();';");
 -
 -        assertInvalidMessage("The function return type should not be frozen",
 -                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
 -                             "CALLED ON NULL INPUT " +
 -                             "RETURNS frozen<" + myType + "> " +
 -                             "LANGUAGE java\n" +
 -                             "AS 'return values;';");
 -
 -        String functionName = createFunction(KEYSPACE,
 -                                             myType,
 -                                             "CREATE FUNCTION %s (values " + myType + ") " +
 -                                             "CALLED ON NULL INPUT " +
 -                                             "RETURNS text " +
 -                                             "LANGUAGE java\n" +
 -                                             "AS 'return values.toString();';");
 -
 -        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
 -                   row(0, "{f:0}"),
 -                   row(1, "{f:1}"),
 -                   row(2, "{f:4}"),
 -                   row(3, "{f:7}"));
 -
 -        functionName = createFunction(KEYSPACE,
 -                                      myType,
 -                                      "CREATE FUNCTION %s (values " + myType + ") " +
 -                                      "CALLED ON NULL INPUT " +
 -                                      "RETURNS " + myType + " " +
 -                                      "LANGUAGE java\n" +
 -                                      "AS 'return values;';");
 -
 -        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
 -                   row(1));
 -
 -        assertInvalidMessage("The function arguments should not be frozen",
 -                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
 -    }
 -
 -    @Test
 -    public void testEmptyString() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
 -        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
 -
 -        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return \"\";'");
 -
 -        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
 -                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS text " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return \"\";'");
 -
 -        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return ByteBuffer.allocate(0);'");
 -
 -        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
 -                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS blob " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return ByteBuffer.allocate(0);'");
 -
 -        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "CALLED ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return 0;'");
 -
 -        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return val;'");
 -
 -        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
 -                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
 -                                         "RETURNS NULL ON NULL INPUT " +
 -                                         "RETURNS int " +
 -                                         "LANGUAGE JAVA\n" +
 -                                         "AS 'return 0;'");
 -
 -        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
 -        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
 -        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
 -        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
 -        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
 -        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
 -    }
 -
 -    @Test
+     public void testAllNativeTypes() throws Throwable
+     {
+         StringBuilder sig = new StringBuilder();
+         StringBuilder args = new StringBuilder();
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
++            if (type == CQL3Type.Native.EMPTY)
++                continue;
++
+             if (sig.length() > 0)
+                 sig.append(',');
+             sig.append(type.toString());
+ 
+             if (args.length() > 0)
+                 args.append(',');
+             args.append("arg").append(type.toString()).append(' ').append(type.toString());
+         }
+         createFunction(KEYSPACE, sig.toString(),
+                        "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                        "RETURNS NULL ON NULL INPUT " +
+                        "RETURNS int " +
+                        "LANGUAGE JAVA\n" +
+                        "AS 'return 0;'");
+ 
+         for (CQL3Type.Native type : CQL3Type.Native.values())
+         {
++            if (type == CQL3Type.Native.EMPTY)
++                continue;
++
+             createFunction(KEYSPACE_PER_TEST, type.toString(),
+                            "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                            "RETURNS NULL ON NULL INPUT " +
+                            "RETURNS int " +
+                            "LANGUAGE JAVA\n" +
+                            "AS 'return 0;'");
+         }
+     }
+ }


[08/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Posted by sn...@apache.org.
testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

patch by Robert Stupp; reviewed by Alex Petrov for CASSANDRA-12817


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/0b97c5d1
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/0b97c5d1
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/0b97c5d1

Branch: refs/heads/trunk
Commit: 0b97c5d1f717be30a04c59c766465d9c62a4e9ee
Parents: 2e93398
Author: Robert Stupp <sn...@snazy.de>
Authored: Wed Dec 7 13:06:55 2016 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Wed Dec 7 13:06:55 2016 +0100

----------------------------------------------------------------------
 .../cql3/validation/entities/UFJavaTest.java    | 1177 +++++++++++++
 .../cql3/validation/entities/UFScriptTest.java  |  504 ++++++
 .../cql3/validation/entities/UFTest.java        | 1608 +-----------------
 3 files changed, 1696 insertions(+), 1593 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
new file mode 100644
index 0000000..caef808
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFJavaTest.java
@@ -0,0 +1,1177 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import com.datastax.driver.core.UDTValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQL3Type;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.cql3.functions.Functions;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+public class UFJavaTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+
+    @Test
+    public void testJavaFunctionNoParameters() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = "\n  return 1L;\n";
+
+        String fName = createFunction(KEYSPACE, "",
+                                      "CREATE OR REPLACE FUNCTION %s() " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" +functionBody + "';");
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           KEYSPACE, parseFunctionName(fName).name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
+                   row(1, 1d, 1L),
+                   row(2, 2d, 1L),
+                   row(3, 3d, 1L)
+        );
+    }
+
+    @Test
+    public void testJavaFunctionInvalidBodies() throws Throwable
+    {
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
+        }
+
+        try
+        {
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
+                    "RETURNS NULL ON NULL INPUT " +
+                    "RETURNS bigint " +
+                    "LANGUAGE JAVA\n" +
+                    "AS '\n" +
+                    "foobarbaz;" +
+                    "\n';");
+            Assert.fail();
+        }
+        catch (InvalidRequestException e)
+        {
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
+            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
+        }
+    }
+
+    @Test
+    public void testJavaFunctionInvalidReturn() throws Throwable
+    {
+        assertInvalidMessage("system keyspace is not user-modifiable",
+                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE JAVA\n" +
+                             "AS 'return 1L;';");
+    }
+
+    @Test
+    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val bigint)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return Double.valueOf(val);';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
+        assertInvalidMessage("val cannot be passed as argument 0 of function",
+                             "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaFunctionCounter() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val counter)");
+
+        String fName = createFunction(KEYSPACE, "counter",
+                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS bigint " +
+                                      "LANGUAGE JAVA " +
+                                      "AS 'return val + 1;';");
+
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1L, 2L));
+        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 4L, 5L));
+        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 2L, 3L));
+    }
+
+    @Test
+    public void testJavaKeyspaceFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (val == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return Math.sin( val );\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavaRuntimeException() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  throw new RuntimeException(\"oh no!\");\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+
+        // function throws a RuntimeException which is wrapped by FunctionExecutionException
+        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavaDollarQuotedFunction() throws Throwable
+    {
+        String functionBody = '\n' +
+                              "  // parameter val is of type java.lang.Double\n" +
+                              "  /* return type is of type java.lang.Double */\n" +
+                              "  if (input == null) {\n" +
+                              "    return null;\n" +
+                              "  }\n" +
+                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE FUNCTION %s( input double ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$" + functionBody + "$$;");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("java", functionBody));
+    }
+
+    @Test
+    public void testJavaSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                      "CREATE FUNCTION %s( lst list<double> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return lst;$$;");
+        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                     "CREATE FUNCTION %s( st set<text> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS set<text> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return st;$$;");
+        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                     "RETURNS NULL ON NULL INPUT " +
+                                     "RETURNS map<int, boolean> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return mp;$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavaTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavaTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + tupleTypeDef + ' ' +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup;$$;");
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       Double.valueOf(tup.getDouble(0));$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getList(1, Double.class);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getSet(2, String.class);$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return " +
+                                      "       tup.getMap(3, Integer.class, Boolean.class);$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeWithUse() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            executeNet(version, "USE " + KEYSPACE);
+
+            executeNet(version,
+                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS " + type + " " +
+                       "LANGUAGE java " +
+                       "AS $$return " +
+                       "     udt;$$;");
+            try
+            {
+                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
+                Assert.assertEquals(1, rowsNet.size());
+                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+                Assert.assertEquals("one", udtVal.getString("txt"));
+                Assert.assertEquals(1, udtVal.getInt("i"));
+            }
+            finally
+            {
+                executeNet(version, "DROP FUNCTION f_use1");
+            }
+        }
+    }
+
+    @Test
+    public void testJavaUserType() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt0 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt;$$;");
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
+            Assert.assertEquals(1, rowsNet.size());
+            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
+            Assert.assertEquals("one", udtVal.getString("txt"));
+            Assert.assertEquals(1, udtVal.getInt("i"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
+                          row("one"));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                          row(1));
+        }
+    }
+
+    @Test
+    public void testJavaUserTypeRenameField() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return udt.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+
+        execute("ALTER TYPE " + type + " RENAME txt TO str");
+
+        assertInvalidMessage("txt is not a field defined in this UDT",
+                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
+
+        execute("ALTER TYPE " + type + " RENAME str TO txt");
+
+        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+    }
+
+    @Test
+    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fName1replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + ") " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS text " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt.getString(\"txt\");$$;");
+        String fName2replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS int " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "CALLED ON NULL INPUT " +
+                                              "RETURNS double " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4replace = createFunction(KEYSPACE, type,
+                                              "CREATE FUNCTION %s( udt " + type + " ) " +
+                                              "RETURNS NULL ON NULL INPUT " +
+                                              "RETURNS " + type + " " +
+                                              "LANGUAGE java\n" +
+                                              "AS $$return udt;$$;");
+
+        String fName1noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS text " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt.getString(\"txt\");$$;");
+        String fName2noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS int " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "CALLED ON NULL INPUT " +
+                                                "RETURNS double " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4noReplace = createFunction(KEYSPACE, type,
+                                                "CREATE FUNCTION %s( udt " + type + " ) " +
+                                                "RETURNS NULL ON NULL INPUT " +
+                                                "RETURNS " + type + " " +
+                                                "LANGUAGE java\n" +
+                                                "AS $$return udt;$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+
+        // add field
+
+        execute("ALTER TYPE " + type + " ADD added double");
+
+        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
+
+        // note: type references of functions remain at the state _before_ the type mutation
+        // means we need to recreate the functions
+
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS text " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt.getString(\"txt\");$$;",
+                              fName1replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS int " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
+                              fName2replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "CALLED ON NULL INPUT " +
+                              "RETURNS double " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
+                              fName3replace, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
+        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
+                              "RETURNS NULL ON NULL INPUT " +
+                              "RETURNS %s " +
+                              "LANGUAGE java\n" +
+                              "AS $$return " +
+                              "     udt;$$;",
+                              fName4replace, type, type));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
+
+        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        // un-replaced functions will work since the user type has changed
+        // and the UDF has exchanged the user type reference
+
+        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row("two"));
+        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
+                   row(2d));
+        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
+                   row(0d));
+
+        execute("DROP FUNCTION " + fName1replace);
+        execute("DROP FUNCTION " + fName2replace);
+        execute("DROP FUNCTION " + fName3replace);
+        execute("DROP FUNCTION " + fName4replace);
+        execute("DROP FUNCTION " + fName1noReplace);
+        execute("DROP FUNCTION " + fName2noReplace);
+        execute("DROP FUNCTION " + fName3noReplace);
+        execute("DROP FUNCTION " + fName4noReplace);
+    }
+
+    @Test
+    public void testJavaUTCollections() throws Throwable
+    {
+        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
+                                       "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS text " +
+                                       "LANGUAGE java\n" +
+                                       "AS $$" +
+                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
+                                       "     return udtVal.getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row("three", "one", "two"));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testFunctionWithFrozenSetType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<set<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "set<int>",
+                                             "CREATE FUNCTION %s (values set<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "set<int>",
+                                      "CREATE FUNCTION %s (values set<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS set<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenListType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<list<int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "list<int>",
+                                             "CREATE FUNCTION %s (values list<int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "list<int>",
+                                      "CREATE FUNCTION %s (values list<int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS list<int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenMapType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+        createIndex("CREATE INDEX ON %s (FULL(b))");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS int " +
+                             "LANGUAGE java\n" +
+                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<map<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "map<int, int>",
+                                             "CREATE FUNCTION %s (values map<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS int " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, 0),
+                   row(1, 6),
+                   row(2, 15),
+                   row(3, 24));
+
+        functionName = createFunction(KEYSPACE,
+                                      "map<int, int>",
+                                      "CREATE FUNCTION %s (values map<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS map<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<tuple<int, int>> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             "tuple<int, int>",
+                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "(null, null)"),
+                   row(1, "(1, 2)"),
+                   row(2, "(4, 5)"),
+                   row(3, "(7, 8)"));
+
+        functionName = createFunction(KEYSPACE,
+                                      "tuple<int, int>",
+                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS tuple<int, int> " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
+    }
+
+    @Test
+    public void testFunctionWithFrozenUDType() throws Throwable
+    {
+        String myType = createType("CREATE TYPE %s (f int)");
+        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+        createIndex("CREATE INDEX ON %s (b)");
+
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values.toString();';");
+
+        assertInvalidMessage("The function return type should not be frozen",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
+                             "CALLED ON NULL INPUT " +
+                             "RETURNS frozen<" + myType + "> " +
+                             "LANGUAGE java\n" +
+                             "AS 'return values;';");
+
+        String functionName = createFunction(KEYSPACE,
+                                             myType,
+                                             "CREATE FUNCTION %s (values " + myType + ") " +
+                                             "CALLED ON NULL INPUT " +
+                                             "RETURNS text " +
+                                             "LANGUAGE java\n" +
+                                             "AS 'return values.toString();';");
+
+        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+                   row(0, "{f:0}"),
+                   row(1, "{f:1}"),
+                   row(2, "{f:4}"),
+                   row(3, "{f:7}"));
+
+        functionName = createFunction(KEYSPACE,
+                                      myType,
+                                      "CREATE FUNCTION %s (values " + myType + ") " +
+                                      "CALLED ON NULL INPUT " +
+                                      "RETURNS " + myType + " " +
+                                      "LANGUAGE java\n" +
+                                      "AS 'return values;';");
+
+        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
+                   row(1));
+
+        assertInvalidMessage("The function arguments should not be frozen",
+                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
+    }
+
+    @Test
+    public void testEmptyString() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
+        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
+
+        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
+                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS text " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return \"\";'");
+
+        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
+                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS blob " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return ByteBuffer.allocate(0);'");
+
+        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "CALLED ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return val;'");
+
+        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
+                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
+                                         "RETURNS NULL ON NULL INPUT " +
+                                         "RETURNS int " +
+                                         "LANGUAGE JAVA\n" +
+                                         "AS 'return 0;'");
+
+        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
+        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
+        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
+        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
+        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
+    }
+
+    @Test
+    public void testAllNativeTypes() throws Throwable
+    {
+        StringBuilder sig = new StringBuilder();
+        StringBuilder args = new StringBuilder();
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            if (sig.length() > 0)
+                sig.append(',');
+            sig.append(type.toString());
+
+            if (args.length() > 0)
+                args.append(',');
+            args.append("arg").append(type.toString()).append(' ').append(type.toString());
+        }
+        createFunction(KEYSPACE, sig.toString(),
+                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
+                       "RETURNS NULL ON NULL INPUT " +
+                       "RETURNS int " +
+                       "LANGUAGE JAVA\n" +
+                       "AS 'return 0;'");
+
+        for (CQL3Type.Native type : CQL3Type.Native.values())
+        {
+            createFunction(KEYSPACE_PER_TEST, type.toString(),
+                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
+                           "RETURNS NULL ON NULL INPUT " +
+                           "RETURNS int " +
+                           "LANGUAGE JAVA\n" +
+                           "AS 'return 0;'");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
new file mode 100644
index 0000000..d3050a5
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFScriptTest.java
@@ -0,0 +1,504 @@
+/*
+ * 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.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TupleType;
+import com.datastax.driver.core.TupleValue;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.cql3.functions.FunctionName;
+import org.apache.cassandra.dht.ByteOrderedPartitioner;
+import org.apache.cassandra.exceptions.FunctionExecutionException;
+import org.apache.cassandra.transport.Server;
+import org.apache.cassandra.utils.UUIDGen;
+
+public class UFScriptTest extends CQLTester
+{
+    @BeforeClass
+    public static void setUp()
+    {
+        DatabaseDescriptor.setPartitioner(ByteOrderedPartitioner.instance);
+    }
+
+    @Test
+    public void testJavascriptSimpleCollections() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
+
+        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
+                                       "CREATE FUNCTION %s( lst list<double> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS list<double> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'lst;';");
+        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                       "CREATE FUNCTION %s( st set<text> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS set<text> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'st;';");
+        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
+                                       "CREATE FUNCTION %s( mp map<int, boolean> ) " +
+                                       "RETURNS NULL ON NULL INPUT " +
+                                       "RETURNS map<int, boolean> " +
+                                       "LANGUAGE javascript\n" +
+                                       "AS 'mp;';");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
+
+        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                   row(list, set, map));
+
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @Test
+    public void testJavascriptTupleType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+                                      "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, text, int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$tup;$$;");
+
+        Object t = tuple(1d, "foo", 2, true);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
+                   row(t));
+
+        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+    }
+
+    @Test
+    public void testJavascriptTupleTypeCollection() throws Throwable
+    {
+        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
+
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup;$$;");
+        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getDouble(0);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
+        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS set<text> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
+        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS map<int, boolean> " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
+
+        List<Double> list = Arrays.asList(1d, 2d, 3d);
+        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
+        Map<Integer, Boolean> map = new TreeMap<>();
+        map.put(1, true);
+        map.put(2, false);
+        map.put(3, true);
+
+        Object t = tuple(1d, list, set, map);
+
+        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
+
+        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                   row(t));
+        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                   row(1d));
+        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                   row(list));
+        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                   row(set));
+        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                   row(map));
+
+        // same test - but via native protocol
+        TupleType tType = TupleType.of(DataType.cdouble(),
+                                       DataType.list(DataType.cdouble()),
+                                       DataType.set(DataType.text()),
+                                       DataType.map(DataType.cint(), DataType.cboolean()));
+        TupleValue tup = tType.newValue(1d, list, set, map);
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+        {
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
+                          row(tup));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
+                          row(1d));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
+                          row(list));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
+                          row(set));
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
+                          row(map));
+        }
+    }
+
+    @Test
+    public void testJavascriptUserType() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
+
+        String fUdt1 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS " + type + " " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt;$$;");
+        String fUdt2 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt3 = createFunction(KEYSPACE, type,
+                                      "CREATE FUNCTION %s( udt " + type + " ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS int " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "     udt.getInt(\"i\");$$;");
+
+        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
+
+        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
+        Assert.assertEquals(1, rows.size());
+        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
+                   row(1));
+    }
+
+    @Test
+    public void testJavascriptUTCollections() throws Throwable
+    {
+        String type = createType("CREATE TYPE %s (txt text, i int)");
+
+        createTable(String.format("CREATE TABLE %%s " +
+                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
+                                  type, type, type));
+
+        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
+                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS text " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS $$" +
+                                      "        lst.get(1).getString(\"txt\");$$;");
+        createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        st.iterator().next().getString(\"txt\");$$;");
+        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
+                               "RETURNS NULL ON NULL INPUT " +
+                               "RETURNS text " +
+                               "LANGUAGE javascript\n" +
+                               "AS $$" +
+                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
+
+        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
+                // list<frozen<UDT>>
+                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
+                // set<frozen<UDT>>
+                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
+                // map<int, frozen<UDT>>
+                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
+
+        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
+                   row("three"));
+        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
+                   row("one"));
+        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
+                   row("two"));
+
+        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
+        assertRows(execute(cqlSelect),
+                   row("three", "one", "two"));
+
+        // same test - but via native protocol
+        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
+            assertRowsNet(version,
+                          executeNet(version, cqlSelect),
+                          row("three", "one", "two"));
+    }
+
+    @Test
+    public void testJavascriptFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String functionBody = '\n' +
+                              "  Math.sin(val);\n";
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '" + functionBody + "';");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+                           fNameName.keyspace, fNameName.name),
+                   row("javascript", functionBody));
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                   row(1, 1d, Math.sin(1d)),
+                   row(2, 2d, Math.sin(2d)),
+                   row(3, 3d, Math.sin(3d))
+        );
+    }
+
+    @Test
+    public void testJavascriptBadReturnType() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '\"string\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ClassCastException
+        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptThrow() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                      "RETURNS NULL ON NULL INPUT " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS 'throw \"fool\";';");
+
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+        // throws IRE with ScriptException
+        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
+                                  "SELECT key, val, " + fName + "(val) FROM %s");
+    }
+
+    @Test
+    public void testJavascriptCompileFailure() throws Throwable
+    {
+        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE javascript\n" +
+                             "AS 'foo bar';");
+    }
+
+    @Test
+    public void testScriptInvalidLanguage() throws Throwable
+    {
+        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS double " +
+                             "LANGUAGE artificial_intelligence\n" +
+                             "AS 'question for 42?';");
+    }
+
+    @Test
+    public void testScriptReturnTypeCasting() throws Throwable
+    {
+        createTable("CREATE TABLE %s (key int primary key, val double)");
+        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
+
+        Object[][] variations = {
+        new Object[]    {   "true",     "boolean",  true    },
+        new Object[]    {   "false",    "boolean",  false   },
+        new Object[]    {   "100",      "tinyint",  (byte)100 },
+        new Object[]    {   "100.",     "tinyint",  (byte)100 },
+        new Object[]    {   "100",      "smallint", (short)100 },
+        new Object[]    {   "100.",     "smallint", (short)100 },
+        new Object[]    {   "100",      "int",      100     },
+        new Object[]    {   "100.",     "int",      100     },
+        new Object[]    {   "100",      "double",   100d    },
+        new Object[]    {   "100.",     "double",   100d    },
+        new Object[]    {   "100",      "bigint",   100L    },
+        new Object[]    {   "100.",     "bigint",   100L    },
+        new Object[]    { "100", "varint", BigInteger.valueOf(100L)    },
+        new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
+        new Object[]    { "parseInt(\"100\");", "decimal", BigDecimal.valueOf(100d)    },
+        new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object functionBody = variation[0];
+            Object returnType = variation[1];
+            Object expectedResult = variation[2];
+
+            String fName = createFunction(KEYSPACE, "double",
+                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " +returnType + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS '" + functionBody + ";';");
+            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                       row(1, 1d, expectedResult));
+        }
+    }
+
+    @Test
+    public void testScriptParamReturnTypes() throws Throwable
+    {
+        UUID ruuid = UUID.randomUUID();
+        UUID tuuid = UUIDGen.getTimeUUID();
+
+        createTable("CREATE TABLE %s (key int primary key, " +
+                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
+                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
+        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
+                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
+                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
+
+        Object[][] variations = {
+        new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
+        new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
+        new Object[] {  "int",      "ival",     1,                      2  },
+        new Object[] {  "bigint",   "lval",     1L,                     2L  },
+        new Object[] {  "float",    "fval",     1f,                     2f  },
+        new Object[] {  "double",   "dval",     1d,                     2d  },
+        new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
+        new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
+        new Object[] {  "time",     "timval",   1L,                     2L  },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val+1;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+
+        variations = new Object[][] {
+        new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
+        new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
+        new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
+        new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
+        };
+
+        for (Object[] variation : variations)
+        {
+            Object type = variation[0];
+            Object col = variation[1];
+            Object expected1 = variation[2];
+            Object expected2 = variation[3];
+            String fName = createFunction(KEYSPACE, type.toString(),
+                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
+                                          "RETURNS NULL ON NULL INPUT " +
+                                          "RETURNS " + type + ' ' +
+                                          "LANGUAGE javascript " +
+                                          "AS 'val;';");
+            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
+                       row(1, expected1, expected2));
+        }
+    }
+}


[03/25] cassandra git commit: testall failure in org.apache.cassandra.cql3.validation.entities.UFTest.testAllNativeTypes

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/0b97c5d1/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index bcfe871..d4d2a10 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@ -17,9 +17,6 @@
  */
 package org.apache.cassandra.cql3.validation.entities;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -34,14 +31,9 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.Row;
-import com.datastax.driver.core.TupleType;
-import com.datastax.driver.core.TupleValue;
-import com.datastax.driver.core.UDTValue;
 import com.datastax.driver.core.exceptions.InvalidQueryException;
 import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.cql3.CQL3Type;
 import org.apache.cassandra.cql3.CQLTester;
 import org.apache.cassandra.cql3.QueryProcessor;
 import org.apache.cassandra.cql3.UntypedResultSet;
@@ -50,13 +42,11 @@ import org.apache.cassandra.cql3.functions.Functions;
 import org.apache.cassandra.cql3.functions.UDFunction;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.dht.ByteOrderedPartitioner;
-import org.apache.cassandra.exceptions.FunctionExecutionException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.transport.Event;
 import org.apache.cassandra.transport.Server;
 import org.apache.cassandra.transport.messages.ResultMessage;
-import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.UUIDGen;
 
 public class UFTest extends CQLTester
@@ -295,7 +285,7 @@ public class UFTest extends CQLTester
         return prepared;
     }
 
-    public void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
+    private void checkDelayedValuesCorrectlyIdentifyFunctionsInUse(boolean dropKeyspace) throws Throwable
     {
         // prepare a statement which doesn't use any function for a control
         createTable("CREATE TABLE %s (" +
@@ -584,164 +574,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaFunctionNoParameters() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = "\n  return 1L;\n";
-
-        String fName = createFunction(KEYSPACE, "",
-                                      "CREATE OR REPLACE FUNCTION %s() " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" +functionBody + "';");
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           KEYSPACE, parseFunctionName(fName).name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
-                   row(1, 1d, 1L),
-                   row(2, 2d, 1L),
-                   row(3, 3d, 1L)
-        );
-    }
-
-    @Test
-    public void testJavaFunctionInvalidBodies() throws Throwable
-    {
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("insert \";\" to complete BlockStatements"));
-        }
-
-        try
-        {
-            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() " +
-                    "RETURNS NULL ON NULL INPUT " +
-                    "RETURNS bigint " +
-                    "LANGUAGE JAVA\n" +
-                    "AS '\n" +
-                    "foobarbaz;" +
-                    "\n';");
-            Assert.fail();
-        }
-        catch (InvalidRequestException e)
-        {
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("Java source compilation failed"));
-            Assert.assertTrue(e.getMessage(), e.getMessage().contains("foobarbaz cannot be resolved to a type"));
-        }
-    }
-
-    @Test
-    public void testJavaFunctionInvalidReturn() throws Throwable
-    {
-        assertInvalidMessage("system keyspace is not user-modifiable",
-                             "CREATE OR REPLACE FUNCTION jfir(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE JAVA\n" +
-                             "AS 'return 1L;';");
-    }
-
-    @Test
-    public void testJavaFunctionArgumentTypeMismatch() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val bigint)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double)" +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return Double.valueOf(val);';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2L);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3L);
-        assertInvalidMessage("val cannot be passed as argument 0 of function",
-                             "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA " +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaFunctionCounter() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val counter)");
-
-        String fName = createFunction(KEYSPACE, "counter",
-                                      "CREATE OR REPLACE FUNCTION %s(val counter) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS bigint " +
-                                      "LANGUAGE JAVA " +
-                                      "AS 'return val + 1;';");
-
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1L, 2L));
-        execute("UPDATE %s SET val = val + 1 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-        execute("UPDATE %s SET val = val + 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 4L, 5L));
-        execute("UPDATE %s SET val = val - 2 WHERE key = 1");
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 2L, 3L));
-    }
-
-    @Test
     public void testFunctionInTargetKeyspace() throws Throwable
     {
         createTable("CREATE TABLE %s (key int primary key, val double)");
@@ -869,140 +701,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaKeyspaceFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (val == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return Math.sin( val );\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                     "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                     "CALLED ON NULL INPUT " +
-                                     "RETURNS double " +
-                                     "LANGUAGE JAVA " +
-                                     "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavaRuntimeException() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  throw new RuntimeException(\"oh no!\");\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE JAVA\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-
-        // function throws a RuntimeException which is wrapped by FunctionExecutionException
-        assertInvalidThrowMessage("java.lang.RuntimeException: oh no", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavaDollarQuotedFunction() throws Throwable
-    {
-        String functionBody = '\n' +
-                              "  // parameter val is of type java.lang.Double\n" +
-                              "  /* return type is of type java.lang.Double */\n" +
-                              "  if (input == null) {\n" +
-                              "    return null;\n" +
-                              "  }\n" +
-                              "  return \"'\"+Math.sin(input)+'\\\'';\n";
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "double",
-                                      "CREATE FUNCTION %s( input double ) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$" + functionBody + "$$;");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("java", functionBody));
-    }
-
-    @Test
-    public void testJavaSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                                     "CREATE FUNCTION %s( lst list<double> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS list<double> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return lst;$$;");
-        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                                     "CREATE FUNCTION %s( st set<text> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS set<text> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return st;$$;");
-        String fMap = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                                     "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS map<int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return mp;$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fList + "(lst), " + fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
     public void testWrongKeyspace() throws Throwable
     {
         String typeName = createType("CREATE TYPE %s (txt text, i int)");
@@ -1135,206 +833,6 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
-                                     "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                                     "RETURNS NULL ON NULL INPUT " +
-                                     "RETURNS tuple<double, text, int, boolean> " +
-                                     "LANGUAGE java\n" +
-                                     "AS $$return tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavaTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS " + tupleTypeDef + ' ' +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup;$$;");
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "CALLED ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       Double.valueOf(tup.getDouble(0));$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                                      "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS list<double> " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return " +
-                                      "       tup.getList(1, Double.class);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getSet(2, String.class);$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE java\n" +
-                "AS $$return " +
-                "       tup.getMap(3, Integer.class, Boolean.class);$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup0 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavaUserTypeWithUse() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + KEYSPACE + '.' + type + ">)");
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            executeNet(version, "USE " + KEYSPACE);
-
-            executeNet(version,
-                       "CREATE FUNCTION f_use1( udt " + type + " ) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS " + type + " " +
-                       "LANGUAGE java " +
-                       "AS $$return " +
-                       "     udt;$$;");
-            try
-            {
-                List<Row> rowsNet = executeNet(version, "SELECT f_use1(udt) FROM %s WHERE key = 1").all();
-                Assert.assertEquals(1, rowsNet.size());
-                UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-                Assert.assertEquals("one", udtVal.getString("txt"));
-                Assert.assertEquals(1, udtVal.getInt("i"));
-            }
-            finally
-            {
-                executeNet(version, "DROP FUNCTION f_use1");
-            }
-        }
-    }
-
-    @Test
-    public void testJavaUserType() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt0 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS " + type + " " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt;$$;");
-        String fUdt1 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     udt.getString(\"txt\");$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE java " +
-                                      "AS $$return " +
-                                      "     Integer.valueOf(udt.getInt(\"i\"));$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            List<Row> rowsNet = executeNet(version, "SELECT " + fUdt0 + "(udt) FROM %s WHERE key = 1").all();
-            Assert.assertEquals(1, rowsNet.size());
-            UDTValue udtVal = rowsNet.get(0).getUDTValue(0);
-            Assert.assertEquals("one", udtVal.getString("txt"));
-            Assert.assertEquals(1, udtVal.getInt("i"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1"),
-                          row("one"));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                          row(1));
-        }
-    }
-
-    @Test
     public void testUserTypeDrop() throws Throwable
     {
         String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
@@ -1372,686 +870,22 @@ public class UFTest extends CQLTester
     }
 
     @Test
-    public void testJavaUserTypeRenameField() throws Throwable
+    public void testDuplicateArgNames() throws Throwable
     {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
+        assertInvalidMessage("duplicate argument names for given function",
+                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
+                             "RETURNS NULL ON NULL INPUT " +
+                             "RETURNS text " +
+                             "LANGUAGE javascript\n" +
+                             "AS '\"foo bar\";';");
+    }
 
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE java\n" +
-                                      "AS $$return udt.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-
-        execute("ALTER TYPE " + type + " RENAME txt TO str");
-
-        assertInvalidMessage("txt is not a field defined in this UDT",
-                             "SELECT " + fName + "(udt) FROM %s WHERE key = 1");
-
-        execute("ALTER TYPE " + type + " RENAME str TO txt");
-
-        assertRows(execute("SELECT " + fName + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-    }
-
-    @Test
-    public void testJavaUserTypeAddFieldWithReplace() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fName1replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + ") " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS double " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4replace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS " + type + " " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt;$$;");
-
-        String fName1noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "RETURNS NULL ON NULL INPUT " +
-                                              "RETURNS text " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return udt.getString(\"txt\");$$;");
-        String fName2noReplace = createFunction(KEYSPACE, type,
-                                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                                              "CALLED ON NULL INPUT " +
-                                              "RETURNS int " +
-                                              "LANGUAGE java\n" +
-                                              "AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
-        String fName3noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "CALLED ON NULL INPUT " +
-                                                "RETURNS double " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
-        String fName4noReplace = createFunction(KEYSPACE, type,
-                                                "CREATE FUNCTION %s( udt " + type + " ) " +
-                                                "RETURNS NULL ON NULL INPUT " +
-                                                "RETURNS " + type + " " +
-                                                "LANGUAGE java\n" +
-                                                "AS $$return udt;$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-
-        // add field
-
-        execute("ALTER TYPE " + type + " ADD added double");
-
-        execute("INSERT INTO %s (key, udt) VALUES (2, {txt: 'two', i:2, added: 2})");
-
-        // note: type references of functions remain at the state _before_ the type mutation
-        // means we need to recreate the functions
-
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt.getString(\"txt\");$$;",
-                              fName1replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS int " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Integer.valueOf(udt.getInt(\"i\"));$$;",
-                              fName2replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName2replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "CALLED ON NULL INPUT " +
-                              "RETURNS double " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     Double.valueOf(udt.getDouble(\"added\"));$$;",
-                              fName3replace, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName3replace)).size());
-        execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS %s " +
-                              "LANGUAGE java\n" +
-                              "AS $$return " +
-                              "     udt;$$;",
-                              fName4replace, type, type));
-        Assert.assertEquals(1, Functions.find(parseFunctionName(fName4replace)).size());
-
-        assertRows(execute("SELECT " + fName1replace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3replace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        // un-replaced functions will work since the user type has changed
-        // and the UDF has exchanged the user type reference
-
-        assertRows(execute("SELECT " + fName1noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row("two"));
-        assertRows(execute("SELECT " + fName2noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 2"),
-                   row(2d));
-        assertRows(execute("SELECT " + fName3noReplace + "(udt) FROM %s WHERE key = 1"),
-                   row(0d));
-
-        execute("DROP FUNCTION " + fName1replace);
-        execute("DROP FUNCTION " + fName2replace);
-        execute("DROP FUNCTION " + fName3replace);
-        execute("DROP FUNCTION " + fName4replace);
-        execute("DROP FUNCTION " + fName1noReplace);
-        execute("DROP FUNCTION " + fName2noReplace);
-        execute("DROP FUNCTION " + fName3noReplace);
-        execute("DROP FUNCTION " + fName4noReplace);
-    }
-
-    @Test
-    public void testJavaUTCollections() throws Throwable
-    {
-        String type = KEYSPACE + '.' + createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)lst.get(1);" +
-                              "     return udtVal.getString(\"txt\");$$;");
-        String fName2 = createFunction(KEYSPACE, "set<frozen<" + type + ">>",
-                                       "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                                       "RETURNS NULL ON NULL INPUT " +
-                                       "RETURNS text " +
-                                       "LANGUAGE java\n" +
-                                       "AS $$" +
-                                       "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
-                                       "     return udtVal.getString(\"txt\");$$;");
-        String fName3 = createFunction(KEYSPACE, "map<int, frozen<" + type + ">>",
-                              "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE java\n" +
-                              "AS $$" +
-                              "     com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)mp.get(Integer.valueOf(3));" +
-                              "     return udtVal.getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row("three", "one", "two"));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptSimpleCollections() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, lst list<double>, st set<text>, mp map<int, boolean>)");
-
-        String fName1 = createFunction(KEYSPACE_PER_TEST, "list<double>",
-                "CREATE FUNCTION %s( lst list<double> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS 'lst;';");
-        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
-                "CREATE FUNCTION %s( st set<text> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS 'st;';");
-        String fName3 = createFunction(KEYSPACE_PER_TEST, "map<int, boolean>",
-                "CREATE FUNCTION %s( mp map<int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS 'mp;';");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        execute("INSERT INTO %s (key, lst, st, mp) VALUES (1, ?, ?, ?)", list, set, map);
-
-        assertRows(execute("SELECT lst, st, mp FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        assertRows(execute("SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                   row(list, set, map));
-
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fName1 + "(lst), " + fName2 + "(st), " + fName3 + "(mp) FROM %s WHERE key = 1"),
-                          row(list, set, map));
-    }
-
-    @Test
-    public void testJavascriptTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<tuple<double, text, int, boolean>>)");
-
-        String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
-                "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, text, int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$tup;$$;");
-
-        Object t = tuple(1d, "foo", 2, true);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT tup FROM %s WHERE key = 1"),
-                   row(t));
-
-        assertRows(execute("SELECT " + fName + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-    }
-
-    @Test
-    public void testJavascriptTupleTypeCollection() throws Throwable
-    {
-        String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
-        createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
-
-        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup;$$;");
-        String fTup2 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS double " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getDouble(0);$$;");
-        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS list<double> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getList(1, java.lang.Class.forName(\"java.lang.Double\"));$$;");
-        String fTup4 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS set<text> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getSet(2, java.lang.Class.forName(\"java.lang.String\"));$$;");
-        String fTup5 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
-                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
-                "RETURNS NULL ON NULL INPUT " +
-                "RETURNS map<int, boolean> " +
-                "LANGUAGE javascript\n" +
-                "AS $$" +
-                "       tup.getMap(3, java.lang.Class.forName(\"java.lang.Integer\"), java.lang.Class.forName(\"java.lang.Boolean\"));$$;");
-
-        List<Double> list = Arrays.asList(1d, 2d, 3d);
-        Set<String> set = new TreeSet<>(Arrays.asList("one", "three", "two"));
-        Map<Integer, Boolean> map = new TreeMap<>();
-        map.put(1, true);
-        map.put(2, false);
-        map.put(3, true);
-
-        Object t = tuple(1d, list, set, map);
-
-        execute("INSERT INTO %s (key, tup) VALUES (1, ?)", t);
-
-        assertRows(execute("SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                   row(t));
-        assertRows(execute("SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                   row(1d));
-        assertRows(execute("SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                   row(list));
-        assertRows(execute("SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                   row(set));
-        assertRows(execute("SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                   row(map));
-
-        // same test - but via native protocol
-        TupleType tType = TupleType.of(DataType.cdouble(),
-                                       DataType.list(DataType.cdouble()),
-                                       DataType.set(DataType.text()),
-                                       DataType.map(DataType.cint(), DataType.cboolean()));
-        TupleValue tup = tType.newValue(1d, list, set, map);
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-        {
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup1 + "(tup) FROM %s WHERE key = 1"),
-                          row(tup));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup2 + "(tup) FROM %s WHERE key = 1"),
-                          row(1d));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup3 + "(tup) FROM %s WHERE key = 1"),
-                          row(list));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup4 + "(tup) FROM %s WHERE key = 1"),
-                          row(set));
-            assertRowsNet(version,
-                          executeNet(version, "SELECT " + fTup5 + "(tup) FROM %s WHERE key = 1"),
-                          row(map));
-        }
-    }
-
-    @Test
-    public void testJavascriptUserType() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
-
-        String fUdt1 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS " + type + " " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt;$$;");
-        String fUdt2 = createFunction(KEYSPACE, type,
-                              "CREATE FUNCTION %s( udt " + type + " ) " +
-                              "RETURNS NULL ON NULL INPUT " +
-                              "RETURNS text " +
-                              "LANGUAGE javascript\n" +
-                              "AS $$" +
-                              "     udt.getString(\"txt\");$$;");
-        String fUdt3 = createFunction(KEYSPACE, type,
-                                      "CREATE FUNCTION %s( udt " + type + " ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS int " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "     udt.getInt(\"i\");$$;");
-
-        execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
-
-        UntypedResultSet rows = execute("SELECT " + fUdt1 + "(udt) FROM %s WHERE key = 1");
-        Assert.assertEquals(1, rows.size());
-        assertRows(execute("SELECT " + fUdt2 + "(udt) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fUdt3 + "(udt) FROM %s WHERE key = 1"),
-                   row(1));
-    }
-
-    @Test
-    public void testJavascriptUTCollections() throws Throwable
-    {
-        String type = createType("CREATE TYPE %s (txt text, i int)");
-
-        createTable(String.format("CREATE TABLE %%s " +
-                                  "(key int primary key, lst list<frozen<%s>>, st set<frozen<%s>>, mp map<int, frozen<%s>>)",
-                                  type, type, type));
-
-        String fName = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
-                                      "CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS text " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS $$" +
-                                      "        lst.get(1).getString(\"txt\");$$;");
-        createFunctionOverload(fName, "set<frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( st set<frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        st.iterator().next().getString(\"txt\");$$;");
-        createFunctionOverload(fName, "map<int, frozen<" + type + ">>",
-                               "CREATE FUNCTION %s( mp map<int, frozen<" + type + ">> ) " +
-                               "RETURNS NULL ON NULL INPUT " +
-                               "RETURNS text " +
-                               "LANGUAGE javascript\n" +
-                               "AS $$" +
-                               "        mp.get(java.lang.Integer.valueOf(3)).getString(\"txt\");$$;");
-
-        execute("INSERT INTO %s (key, lst, st, mp) values (1, " +
-                // list<frozen<UDT>>
-                "[ {txt: 'one', i:1}, {txt: 'three', i:1}, {txt: 'one', i:1} ] , " +
-                // set<frozen<UDT>>
-                "{ {txt: 'one', i:1}, {txt: 'three', i:3}, {txt: 'two', i:2} }, " +
-                // map<int, frozen<UDT>>
-                "{ 1: {txt: 'one', i:1}, 2: {txt: 'one', i:3}, 3: {txt: 'two', i:2} })");
-
-        assertRows(execute("SELECT " + fName + "(lst) FROM %s WHERE key = 1"),
-                   row("three"));
-        assertRows(execute("SELECT " + fName + "(st) FROM %s WHERE key = 1"),
-                   row("one"));
-        assertRows(execute("SELECT " + fName + "(mp) FROM %s WHERE key = 1"),
-                   row("two"));
-
-        String cqlSelect = "SELECT " + fName + "(lst), " + fName + "(st), " + fName + "(mp) FROM %s WHERE key = 1";
-        assertRows(execute(cqlSelect),
-                   row("three", "one", "two"));
-
-        // same test - but via native protocol
-        for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)
-            assertRowsNet(version,
-                          executeNet(version, cqlSelect),
-                          row("three", "one", "two"));
-    }
-
-    @Test
-    public void testJavascriptFunction() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String functionBody = '\n' +
-                              "  Math.sin(val);\n";
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '" + functionBody + "';");
-
-        FunctionName fNameName = parseFunctionName(fName);
-
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
-                           fNameName.keyspace, fNameName.name),
-                   row("javascript", functionBody));
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
-        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                   row(1, 1d, Math.sin(1d)),
-                   row(2, 2d, Math.sin(2d)),
-                   row(3, 3d, Math.sin(3d))
-        );
-    }
-
-    @Test
-    public void testJavascriptBadReturnType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                                      "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                      "RETURNS NULL ON NULL INPUT " +
-                                      "RETURNS double " +
-                                      "LANGUAGE javascript\n" +
-                                      "AS '\"string\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ClassCastException
-        assertInvalidMessage("Invalid value for CQL type double", "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testJavascriptThrow() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-
-        String fName = createFunction(KEYSPACE, "double",
-                       "CREATE OR REPLACE FUNCTION %s(val double) " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS double " +
-                       "LANGUAGE javascript\n" +
-                       "AS 'throw \"fool\";';");
-
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-        // throws IRE with ScriptException
-        assertInvalidThrowMessage("fool", FunctionExecutionException.class,
-                                  "SELECT key, val, " + fName + "(val) FROM %s");
-    }
-
-    @Test
-    public void testDuplicateArgNames() throws Throwable
-    {
-        assertInvalidMessage("duplicate argument names for given function",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE javascript\n" +
-                             "AS '\"foo bar\";';");
-    }
-
-    @Test
-    public void testJavascriptCompileFailure() throws Throwable
-    {
-        assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE javascript\n" +
-                             "AS 'foo bar';");
-    }
-
-    @Test
-    public void testScriptInvalidLanguage() throws Throwable
-    {
-        assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
-                             "RETURNS NULL ON NULL INPUT " +
-                             "RETURNS double " +
-                             "LANGUAGE artificial_intelligence\n" +
-                             "AS 'question for 42?';");
-    }
-
-    @Test
-    public void testScriptReturnTypeCasting() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, val double)");
-        execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
-
-        Object[][] variations = {
-                                new Object[]    {   "true",     "boolean",  true    },
-                                new Object[]    {   "false",    "boolean",  false   },
-                                new Object[]    {   "100",      "tinyint",  (byte)100 },
-                                new Object[]    {   "100.",     "tinyint",  (byte)100 },
-                                new Object[]    {   "100",      "smallint", (short)100 },
-                                new Object[]    {   "100.",     "smallint", (short)100 },
-                                new Object[]    {   "100",      "int",      100     },
-                                new Object[]    {   "100.",     "int",      100     },
-                                new Object[]    {   "100",      "double",   100d    },
-                                new Object[]    {   "100.",     "double",   100d    },
-                                new Object[]    {   "100",      "bigint",   100L    },
-                                new Object[]    {   "100.",     "bigint",   100L    },
-                                new Object[]    {   "100",      "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "100.",     "varint",   BigInteger.valueOf(100L)    },
-                                new Object[]    {   "parseInt(\"100\");", "decimal",  BigDecimal.valueOf(100d)    },
-                                new Object[]    {   "100.",     "decimal",  BigDecimal.valueOf(100d)    },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object functionBody = variation[0];
-            Object returnType = variation[1];
-            Object expectedResult = variation[2];
-
-            String fName = createFunction(KEYSPACE, "double",
-                                          "CREATE OR REPLACE FUNCTION %s(val double) " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " +returnType + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS '" + functionBody + ";';");
-            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
-                       row(1, 1d, expectedResult));
-        }
-    }
-
-    @Test
-    public void testScriptParamReturnTypes() throws Throwable
-    {
-        UUID ruuid = UUID.randomUUID();
-        UUID tuuid = UUIDGen.getTimeUUID();
-
-        createTable("CREATE TABLE %s (key int primary key, " +
-                    "tival tinyint, sival smallint, ival int, lval bigint, fval float, dval double, vval varint, ddval decimal, " +
-                    "timval time, dtval date, tsval timestamp, uval uuid, tuval timeuuid)");
-        execute("INSERT INTO %s (key, tival, sival, ival, lval, fval, dval, vval, ddval, timval, dtval, tsval, uval, tuval) VALUES " +
-                "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 1,
-                (byte)1, (short)1, 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d), 1L, Integer.MAX_VALUE, new Date(1), ruuid, tuuid);
-
-        Object[][] variations = {
-                                new Object[] {  "tinyint",  "tival",    (byte)1,                (byte)2  },
-                                new Object[] {  "smallint", "sival",    (short)1,               (short)2  },
-                                new Object[] {  "int",      "ival",     1,                      2  },
-                                new Object[] {  "bigint",   "lval",     1L,                     2L  },
-                                new Object[] {  "float",    "fval",     1f,                     2f  },
-                                new Object[] {  "double",   "dval",     1d,                     2d  },
-                                new Object[] {  "varint",   "vval",     BigInteger.valueOf(1L), BigInteger.valueOf(2L)  },
-                                new Object[] {  "decimal",  "ddval",    BigDecimal.valueOf(1d), BigDecimal.valueOf(2d)  },
-                                new Object[] {  "time",     "timval",   1L,                     2L  },
-                                };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS " + type + ' ' +
-                           "LANGUAGE javascript " +
-                           "AS 'val+1;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-
-        variations = new Object[][] {
-                     new Object[] {  "timestamp","tsval",    new Date(1),            new Date(1)  },
-                     new Object[] {  "uuid",     "uval",     ruuid,                  ruuid  },
-                     new Object[] {  "timeuuid", "tuval",    tuuid,                  tuuid  },
-                     new Object[] {  "date",     "dtval",    Integer.MAX_VALUE,      Integer.MAX_VALUE },
-        };
-
-        for (Object[] variation : variations)
-        {
-            Object type = variation[0];
-            Object col = variation[1];
-            Object expected1 = variation[2];
-            Object expected2 = variation[3];
-            String fName = createFunction(KEYSPACE, type.toString(),
-                                          "CREATE OR REPLACE FUNCTION %s(val " + type + ") " +
-                                          "RETURNS NULL ON NULL INPUT " +
-                                          "RETURNS " + type + ' ' +
-                                          "LANGUAGE javascript " +
-                                          "AS 'val;';");
-            assertRows(execute("SELECT key, " + col + ", " + fName + '(' + col + ") FROM %s"),
-                       row(1, expected1, expected2));
-        }
-    }
-
-    static class TypesTestDef
-    {
-        final String udfType;
-        final String tableType;
-        final String columnName;
-        final Object referenceValue;
+    private static class TypesTestDef
+    {
+        final String udfType;
+        final String tableType;
+        final String columnName;
+        final Object referenceValue;
 
         String fCheckArgAndReturn;
 
@@ -2274,416 +1108,4 @@ public class UFTest extends CQLTester
             }
         }
     }
-
-    @Test
-    public void testFunctionWithFrozenSetType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<set<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "set<int>",
-                                             "CREATE FUNCTION %s (values set<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS set<int> " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenListType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<list<int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "list<int>",
-                                             "CREATE FUNCTION %s (values list<int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "list<int>",
-                                      "CREATE FUNCTION %s (values list<int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS list<int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenMapType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
-        createIndex("CREATE INDEX ON %s (FULL(b))");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS int " +
-                             "LANGUAGE java\n" +
-                             "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<map<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "map<int, int>",
-                                             "CREATE FUNCTION %s (values map<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS int " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, 0),
-                   row(1, 6),
-                   row(2, 15),
-                   row(3, 24));
-
-        functionName = createFunction(KEYSPACE,
-                                      "map<int, int>",
-                                      "CREATE FUNCTION %s (values map<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS map<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenTupleType() throws Throwable
-    {
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
-        execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<tuple<int, int>> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             "tuple<int, int>",
-                                             "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "(null, null)"),
-                   row(1, "(1, 2)"),
-                   row(2, "(4, 5)"),
-                   row(3, "(7, 8)"));
-
-        functionName = createFunction(KEYSPACE,
-                                      "tuple<int, int>",
-                                      "CREATE FUNCTION %s (values tuple<int, int>) " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS tuple<int, int> " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
-    }
-
-    @Test
-    public void testFunctionWithFrozenUDType() throws Throwable
-    {
-        String myType = createType("CREATE TYPE %s (f int)");
-        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
-        createIndex("CREATE INDEX ON %s (b)");
-
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
-        execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS text " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values.toString();';");
-
-        assertInvalidMessage("The function return type should not be frozen",
-                             "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
-                             "CALLED ON NULL INPUT " +
-                             "RETURNS frozen<" + myType + "> " +
-                             "LANGUAGE java\n" +
-                             "AS 'return values;';");
-
-        String functionName = createFunction(KEYSPACE,
-                                             myType,
-                                             "CREATE FUNCTION %s (values " + myType + ") " +
-                                             "CALLED ON NULL INPUT " +
-                                             "RETURNS text " +
-                                             "LANGUAGE java\n" +
-                                             "AS 'return values.toString();';");
-
-        assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
-                   row(0, "{f:0}"),
-                   row(1, "{f:1}"),
-                   row(2, "{f:4}"),
-                   row(3, "{f:7}"));
-
-        functionName = createFunction(KEYSPACE,
-                                      myType,
-                                      "CREATE FUNCTION %s (values " + myType + ") " +
-                                      "CALLED ON NULL INPUT " +
-                                      "RETURNS " + myType + " " +
-                                      "LANGUAGE java\n" +
-                                      "AS 'return values;';");
-
-        assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
-                   row(1));
-
-        assertInvalidMessage("The function arguments should not be frozen",
-                             "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
-    }
-
-    @Test
-    public void testEmptyString() throws Throwable
-    {
-        createTable("CREATE TABLE %s (key int primary key, sval text, aval ascii, bval blob, empty_int int)");
-        execute("INSERT INTO %s (key, sval, aval, bval, empty_int) VALUES (?, ?, ?, ?, blobAsInt(0x))", 1, "", "", ByteBuffer.allocate(0));
-
-        String fNameSRC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCC = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameSRN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameSCN = createFunction(KEYSPACE_PER_TEST, "text",
-                                         "CREATE OR REPLACE FUNCTION %s(val text) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS text " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return \"\";'");
-
-        String fNameBRC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCC = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameBRN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameBCN = createFunction(KEYSPACE_PER_TEST, "blob",
-                                         "CREATE OR REPLACE FUNCTION %s(val blob) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS blob " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return ByteBuffer.allocate(0);'");
-
-        String fNameIRC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICC = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "CALLED ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        String fNameIRN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return val;'");
-
-        String fNameICN = createFunction(KEYSPACE_PER_TEST, "int",
-                                         "CREATE OR REPLACE FUNCTION %s(val int) " +
-                                         "RETURNS NULL ON NULL INPUT " +
-                                         "RETURNS int " +
-                                         "LANGUAGE JAVA\n" +
-                                         "AS 'return 0;'");
-
-        assertRows(execute("SELECT " + fNameSRC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(sval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSRN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCC + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameSCN + "(aval) FROM %s"), row(""));
-        assertRows(execute("SELECT " + fNameBRC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBRN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCC + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameBCN + "(bval) FROM %s"), row(ByteBufferUtil.EMPTY_BYTE_BUFFER));
-        assertRows(execute("SELECT " + fNameIRC + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameIRN + "(empty_int) FROM %s"), row(new Object[]{null}));
-        assertRows(execute("SELECT " + fNameICC + "(empty_int) FROM %s"), row(0));
-        assertRows(execute("SELECT " + fNameICN + "(empty_int) FROM %s"), row(new Object[]{null}));
-    }
-
-    @Test
-    public void testAllNativeTypes() throws Throwable
-    {
-        StringBuilder sig = new StringBuilder();
-        StringBuilder args = new StringBuilder();
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            if (sig.length() > 0)
-                sig.append(',');
-            sig.append(type.toString());
-
-            if (args.length() > 0)
-                args.append(',');
-            args.append("arg").append(type.toString()).append(' ').append(type.toString());
-        }
-        createFunction(KEYSPACE, sig.toString(),
-                       "CREATE OR REPLACE FUNCTION %s(" + args + ") " +
-                       "RETURNS NULL ON NULL INPUT " +
-                       "RETURNS int " +
-                       "LANGUAGE JAVA\n" +
-                       "AS 'return 0;'");
-
-        for (CQL3Type.Native type : CQL3Type.Native.values())
-        {
-            createFunction(KEYSPACE_PER_TEST, type.toString(),
-                           "CREATE OR REPLACE FUNCTION %s(val " + type.toString() + ") " +
-                           "RETURNS NULL ON NULL INPUT " +
-                           "RETURNS int " +
-                           "LANGUAGE JAVA\n" +
-                           "AS 'return 0;'");
-        }
-    }
 }