Repository: cassandra
Updated Branches:
  refs/heads/trunk e13121318 -> 794d68b51


http://git-wip-us.apache.org/repos/asf/cassandra/blob/794d68b5/test/unit/org/apache/cassandra/cql3/UFTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/UFTest.java 
b/test/unit/org/apache/cassandra/cql3/UFTest.java
index 4975ca9..824719b 100644
--- a/test/unit/org/apache/cassandra/cql3/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UFTest.java
@@ -19,50 +19,51 @@ package org.apache.cassandra.cql3;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.util.Date;
+import java.util.*;
 
-import org.junit.After;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
 
+import com.datastax.driver.core.*;
 import org.apache.cassandra.cql3.functions.FunctionName;
 import org.apache.cassandra.cql3.functions.Functions;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.transport.Server;
 import org.apache.cassandra.transport.messages.ResultMessage;
 
 public class UFTest extends CQLTester
 {
-    private static final String KS_FOO = "cqltest_foo";
 
-    @Before
-    public void createKsFoo() throws Throwable
+    public static FunctionName parseFunctionName(String qualifiedName)
     {
-        execute("CREATE KEYSPACE IF NOT EXISTS "+KS_FOO+" WITH replication = 
{'class': 'SimpleStrategy', 'replication_factor': 3};");
-    }
-
-    @After
-    public void dropKsFoo() throws Throwable
-    {
-        execute("DROP KEYSPACE IF EXISTS "+KS_FOO+";");
+        int i = qualifiedName.indexOf('.');
+        return i == -1
+               ? FunctionName.nativeFunction(qualifiedName)
+               : new FunctionName(qualifiedName.substring(0, i).trim(), 
qualifiedName.substring(i+1).trim());
     }
 
     @Test
     public void testFunctionDropOnKeyspaceDrop() throws Throwable
     {
-        execute("CREATE FUNCTION " + KS_FOO + ".sin ( input double ) RETURNS 
double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+        String fSin = createFunction(KEYSPACE_PER_TEST, "double",
+                                     "CREATE FUNCTION %s ( input double ) " +
+                                     "RETURNS double " +
+                                     "LANGUAGE java " +
+                                     "AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
 
-        Assert.assertEquals(1, Functions.find(new FunctionName(KS_FOO, 
"sin")).size());
+        FunctionName fSinName = parseFunctionName(fSin);
 
-        assertRows(execute("SELECT function_name, language FROM 
system.schema_functions WHERE keyspace_name=?", KS_FOO),
-                   row("sin", "java"));
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fSin)).size());
 
-        execute("DROP KEYSPACE "+KS_FOO+";");
+        assertRows(execute("SELECT function_name, language FROM 
system.schema_functions WHERE keyspace_name=?", KEYSPACE_PER_TEST),
+                   row(fSinName.name, "java"));
 
-        assertRows(execute("SELECT function_name, language FROM 
system.schema_functions WHERE keyspace_name=?", KS_FOO));
+        dropPerTestKeyspace();
 
-        Assert.assertEquals(0, Functions.find(new FunctionName(KS_FOO, 
"sin")).size());
+        assertRows(execute("SELECT function_name, language FROM 
system.schema_functions WHERE keyspace_name=?", KEYSPACE_PER_TEST));
+
+        Assert.assertEquals(0, Functions.find(fSinName).size());
     }
 
     @Test
@@ -70,27 +71,40 @@ public class UFTest extends CQLTester
     {
         createTable("CREATE TABLE %s (key int PRIMARY KEY, d double)");
 
-        execute("CREATE FUNCTION " + KS_FOO + ".sin ( input double ) RETURNS 
double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+        String fSin = createFunction(KEYSPACE_PER_TEST, "double",
+                                     "CREATE FUNCTION %s ( input double ) " +
+                                     "RETURNS double " +
+                                     "LANGUAGE java " +
+                                     "AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+
+        FunctionName fSinName = parseFunctionName(fSin);
 
-        Assert.assertEquals(1, Functions.find(new FunctionName(KS_FOO, 
"sin")).size());
+        Assert.assertEquals(1, Functions.find(parseFunctionName(fSin)).size());
 
-        ResultMessage.Prepared prepared = QueryProcessor.prepare("SELECT key, 
"+KS_FOO+".sin(d) FROM "+KEYSPACE+'.'+currentTable(), 
ClientState.forInternalCalls(), false);
+        ResultMessage.Prepared prepared = QueryProcessor.prepare(
+                                                    String.format("SELECT key, 
%s(d) FROM %s.%s", fSin, KEYSPACE, currentTable()),
+                                                    
ClientState.forInternalCalls(), false);
         
Assert.assertNotNull(QueryProcessor.instance.getPrepared(prepared.statementId));
 
-        execute("DROP FUNCTION " + KS_FOO + ".sin(double);");
+        execute("DROP FUNCTION " + fSin + "(double);");
 
         
Assert.assertNull(QueryProcessor.instance.getPrepared(prepared.statementId));
 
         //
 
-        execute("CREATE FUNCTION " + KS_FOO + ".sin ( input double ) RETURNS 
double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+        execute("CREATE FUNCTION " + fSin + " ( input double ) " +
+                "RETURNS double " +
+                "LANGUAGE java " +
+                "AS 'return Double.valueOf(Math.sin(input.doubleValue()));'");
 
-        Assert.assertEquals(1, Functions.find(new FunctionName(KS_FOO, 
"sin")).size());
+        Assert.assertEquals(1, Functions.find(fSinName).size());
 
-        prepared = QueryProcessor.prepare("SELECT key, "+KS_FOO+".sin(d) FROM 
"+KEYSPACE+'.'+currentTable(), ClientState.forInternalCalls(), false);
+        prepared = QueryProcessor.prepare(
+                                         String.format("SELECT key, %s(d) FROM 
%s.%s", fSin, KEYSPACE, currentTable()),
+                                         ClientState.forInternalCalls(), 
false);
         
Assert.assertNotNull(QueryProcessor.instance.getPrepared(prepared.statementId));
 
-        execute("DROP KEYSPACE " + KS_FOO + ";");
+        dropPerTestKeyspace();
 
         
Assert.assertNull(QueryProcessor.instance.getPrepared(prepared.statementId));
     }
@@ -105,47 +119,55 @@ public class UFTest extends CQLTester
         execute("INSERT INTO %s(key, d) VALUES (?, ?)", 3, 3d);
 
         // simple creation
-        execute("CREATE FUNCTION "+KS_FOO+".sin ( input double ) RETURNS 
double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+        String fSin = createFunction(KEYSPACE_PER_TEST, "double",
+                                     "CREATE FUNCTION %s ( input double ) " +
+                                     "RETURNS double " +
+                                     "LANGUAGE java " +
+                                     "AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
         // check we can't recreate the same function
-        assertInvalid("CREATE FUNCTION "+KS_FOO+".sin ( input double ) RETURNS 
double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
-        // but that it doesn't complay with "IF NOT EXISTS"
-        execute("CREATE FUNCTION IF NOT EXISTS "+KS_FOO+".sin ( input double ) 
RETURNS double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+        assertInvalid("CREATE FUNCTION " + fSin + " ( input double ) RETURNS 
double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+        // but that it doesn't comply with "IF NOT EXISTS"
+        execute("CREATE FUNCTION IF NOT EXISTS " + fSin + " ( input double ) 
RETURNS double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
 
         // Validate that it works as expected
-        assertRows(execute("SELECT key, "+KS_FOO+".sin(d) FROM %s"),
+        assertRows(execute("SELECT key, " + fSin + "(d) FROM %s"),
             row(1, Math.sin(1d)),
             row(2, Math.sin(2d)),
             row(3, Math.sin(3d))
         );
 
         // Replace the method with incompatible return type
-        assertInvalid("CREATE OR REPLACE FUNCTION " + KS_FOO + ".sin ( input 
double ) RETURNS text LANGUAGE java AS 'return Double.valueOf(42d);'");
+        assertInvalid("CREATE OR REPLACE FUNCTION " + fSin + " ( input double 
) RETURNS text LANGUAGE java AS 'return Double.valueOf(42d);'");
         // proper replacement
-        execute("CREATE OR REPLACE FUNCTION "+KS_FOO+".sin ( input double ) 
RETURNS double LANGUAGE java AS 'return Double.valueOf(42d);'");
+        execute("CREATE OR REPLACE FUNCTION " + fSin + " ( input double ) 
RETURNS double LANGUAGE java AS 'return Double.valueOf(42d);'");
 
         // Validate the method as been replaced
-        assertRows(execute("SELECT key, "+KS_FOO+".sin(d) FROM %s"),
+        assertRows(execute("SELECT key, " + fSin + "(d) FROM %s"),
             row(1, 42.0),
             row(2, 42.0),
             row(3, 42.0)
         );
 
-        // same function but without namespace
-        execute("CREATE FUNCTION "+KEYSPACE+".sin ( input double ) RETURNS 
double LANGUAGE java AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
-        assertRows(execute("SELECT key, "+KEYSPACE+".sin(d) FROM %s"),
+        // same function but other keyspace
+        String fSin2 = createFunction(KEYSPACE, "double",
+                                      "CREATE FUNCTION %s ( input double ) " +
+                                      "RETURNS double " +
+                                      "LANGUAGE java " +
+                                      "AS 'return 
Double.valueOf(Math.sin(input.doubleValue()));'");
+        assertRows(execute("SELECT key, " + fSin2 + "(d) FROM %s"),
             row(1, Math.sin(1d)),
             row(2, Math.sin(2d)),
             row(3, Math.sin(3d))
         );
 
-        // Drop with and without keyspace
-        execute("DROP FUNCTION "+KS_FOO+".sin");
-        execute("DROP FUNCTION "+KEYSPACE+".sin");
+        // Drop
+        execute("DROP FUNCTION " + fSin);
+        execute("DROP FUNCTION " + fSin2);
 
         // Drop unexisting function
-        assertInvalid("DROP FUNCTION "+KS_FOO+".sin");
+        assertInvalid("DROP FUNCTION " + fSin);
         // but don't complain with "IF EXISTS"
-        execute("DROP FUNCTION IF EXISTS "+KS_FOO+".sin");
+        execute("DROP FUNCTION IF EXISTS " + fSin);
 
         // can't drop native functions
         assertInvalid("DROP FUNCTION dateof");
@@ -162,13 +184,17 @@ public class UFTest extends CQLTester
 
         execute("INSERT INTO %s(v) VALUES (?)", "aaa");
 
-        execute("CREATE FUNCTION "+KEYSPACE+".repeat (v text, n int) RETURNS 
text LANGUAGE java AS 'StringBuilder sb = new StringBuilder();\n" +
-                "        for (int i = 0; i < n.intValue(); i++)\n" +
-                "            sb.append(v);\n" +
-                "        return sb.toString();'");
-
-        assertRows(execute("SELECT v FROM %s WHERE v="+KEYSPACE+".repeat(?, 
?)", "a", 3), row("aaa"));
-        assertEmpty(execute("SELECT v FROM %s WHERE v="+KEYSPACE+".repeat(?, 
?)", "a", 2));
+        String fRepeat = createFunction(KEYSPACE_PER_TEST, "text,int",
+                                        "CREATE FUNCTION %s(v text, n int) " +
+                                        "RETURNS text " +
+                                        "LANGUAGE java " +
+                                        "AS 'StringBuilder sb = new 
StringBuilder();\n" +
+                                        "    for (int i = 0; i < n.intValue(); 
i++)\n" +
+                                        "        sb.append(v);\n" +
+                                        "    return sb.toString();'");
+
+        assertRows(execute("SELECT v FROM %s WHERE v=" + fRepeat + "(?, ?)", 
"a", 3), row("aaa"));
+        assertEmpty(execute("SELECT v FROM %s WHERE v=" + fRepeat + "(?, ?)", 
"a", 2));
     }
 
     @Test
@@ -178,46 +204,56 @@ public class UFTest extends CQLTester
 
         execute("INSERT INTO %s(k, v) VALUES (?, ?)", "f2", 1);
 
-        execute("CREATE FUNCTION "+KEYSPACE+".overloaded(v varchar) RETURNS 
text LANGUAGE java AS 'return \"f1\";'");
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".overloaded(i int) 
RETURNS text LANGUAGE java AS 'return \"f2\";'");
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".overloaded(v1 text, 
v2 text) RETURNS text LANGUAGE java AS 'return \"f3\";'");
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".overloaded(v ascii) 
RETURNS text LANGUAGE java AS 'return \"f1\";'");
+        String fOverload = createFunction(KEYSPACE_PER_TEST, "varchar",
+                                          "CREATE FUNCTION %s ( input varchar 
) " +
+                                          "RETURNS text " +
+                                          "LANGUAGE java " +
+                                          "AS 'return \"f1\";'");
+        createFunctionOverload(fOverload,
+                               "int",
+                               "CREATE OR REPLACE FUNCTION %s(i int) RETURNS 
text LANGUAGE java AS 'return \"f2\";'");
+        createFunctionOverload(fOverload,
+                               "text,text",
+                               "CREATE OR REPLACE FUNCTION %s(v1 text, v2 
text) RETURNS text LANGUAGE java AS 'return \"f3\";'");
+        createFunctionOverload(fOverload,
+                               "ascii",
+                               "CREATE OR REPLACE FUNCTION %s(v ascii) RETURNS 
text LANGUAGE java AS 'return \"f1\";'");
 
         // text == varchar, so this should be considered as a duplicate
-        assertInvalid("CREATE FUNCTION "+KEYSPACE+".overloaded(v varchar) 
RETURNS text LANGUAGE java AS 'return \"f1\";'");
+        assertInvalid("CREATE FUNCTION " + fOverload + "(v varchar) RETURNS 
text LANGUAGE java AS 'return \"f1\";'");
 
-        assertRows(execute("SELECT "+KEYSPACE+".overloaded(k), 
"+KEYSPACE+".overloaded(v), "+KEYSPACE+".overloaded(k, k) FROM %s"),
+        assertRows(execute("SELECT " + fOverload + "(k), " + fOverload + "(v), 
" + fOverload + "(k, k) FROM %s"),
             row("f1", "f2", "f3")
         );
 
         forcePreparedValues();
         // This shouldn't work if we use preparation since there no way to 
know which overload to use
-        assertInvalid("SELECT v FROM %s WHERE k = "+KEYSPACE+".overloaded(?)", 
"foo");
+        assertInvalid("SELECT v FROM %s WHERE k = " + fOverload + "(?)", 
"foo");
         stopForcingPreparedValues();
 
         // but those should since we specifically cast
-        assertEmpty(execute("SELECT v FROM %s WHERE k = 
"+KEYSPACE+".overloaded((text)?)", "foo"));
-        assertRows(execute("SELECT v FROM %s WHERE k = 
"+KEYSPACE+".overloaded((int)?)", 3), row(1));
-        assertEmpty(execute("SELECT v FROM %s WHERE k = 
"+KEYSPACE+".overloaded((ascii)?)", "foo"));
+        assertEmpty(execute("SELECT v FROM %s WHERE k = " + fOverload + 
"((text)?)", "foo"));
+        assertRows(execute("SELECT v FROM %s WHERE k = " + fOverload + 
"((int)?)", 3), row(1));
+        assertEmpty(execute("SELECT v FROM %s WHERE k = " + fOverload + 
"((ascii)?)", "foo"));
         // And since varchar == text, this should work too
-        assertEmpty(execute("SELECT v FROM %s WHERE k = 
"+KEYSPACE+".overloaded((varchar)?)", "foo"));
+        assertEmpty(execute("SELECT v FROM %s WHERE k = " + fOverload + 
"((varchar)?)", "foo"));
 
         // no such functions exist...
-        assertInvalid("DROP FUNCTION "+KEYSPACE+".overloaded(boolean)");
-        assertInvalid("DROP FUNCTION "+KEYSPACE+".overloaded(bigint)");
+        assertInvalid("DROP FUNCTION " + fOverload + "(boolean)");
+        assertInvalid("DROP FUNCTION " + fOverload + "(bigint)");
 
         // 'overloaded' has multiple overloads - so it has to fail 
(CASSANDRA-7812)
-        assertInvalid("DROP FUNCTION "+KEYSPACE+".overloaded");
-        execute("DROP FUNCTION " + KEYSPACE + ".overloaded(varchar)");
-        assertInvalid("SELECT v FROM %s WHERE k = " + KEYSPACE + 
".overloaded((text)?)", "foo");
-        execute("DROP FUNCTION " + KEYSPACE + ".overloaded(text, text)");
-        assertInvalid("SELECT v FROM %s WHERE k = " + KEYSPACE + 
".overloaded((text)?,(text)?)", "foo", "bar");
-        execute("DROP FUNCTION " + KEYSPACE + ".overloaded(ascii)");
-        assertInvalid("SELECT v FROM %s WHERE k = 
"+KEYSPACE+".overloaded((ascii)?)", "foo");
+        assertInvalid("DROP FUNCTION " + fOverload);
+        execute("DROP FUNCTION " + fOverload + "(varchar)");
+        assertInvalid("SELECT v FROM %s WHERE k = " + fOverload + "((text)?)", 
"foo");
+        execute("DROP FUNCTION " + fOverload + "(text, text)");
+        assertInvalid("SELECT v FROM %s WHERE k = " + fOverload + 
"((text)?,(text)?)", "foo", "bar");
+        execute("DROP FUNCTION " + fOverload + "(ascii)");
+        assertInvalid("SELECT v FROM %s WHERE k = " + fOverload + 
"((ascii)?)", "foo");
         // single-int-overload must still work
-        assertRows(execute("SELECT v FROM %s WHERE k = " + KEYSPACE + 
".overloaded((int)?)", 3), row(1));
+        assertRows(execute("SELECT v FROM %s WHERE k = " + fOverload + 
"((int)?)", 3), row(1));
         // overloaded has just one overload now - so the following DROP 
FUNCTION is not ambigious (CASSANDRA-7812)
-        execute("DROP FUNCTION "+KEYSPACE+".overloaded");
+        execute("DROP FUNCTION " + fOverload + "");
     }
 
     @Test
@@ -228,7 +264,9 @@ public class UFTest extends CQLTester
         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
 
-        execute("create function "+KS_FOO+".corjf ( input double ) returns 
double language java\n" +
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                "CREATE FUNCTION %s( input double ) " +
+                "RETURNS double LANGUAGE java\n" +
                 "AS '\n" +
                 "  // parameter val is of type java.lang.Double\n" +
                 "  /* return type is of type java.lang.Double */\n" +
@@ -240,19 +278,20 @@ public class UFTest extends CQLTester
                 "';");
 
         // just check created function
-        assertRows(execute("SELECT key, val, "+KS_FOO+".corjf(val) FROM %s"),
+        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))
         );
 
-        execute("create or replace function "+KS_FOO+".corjf ( input double ) 
returns double language java\n" +
+        execute("CREATE OR REPLACE FUNCTION " + fName + "( input double ) " +
+                "RETURNS double LANGUAGE java\n" +
                 "AS '\n" +
                 "  return input;\n" +
                 "';");
 
         // check if replaced function returns correct result
-        assertRows(execute("SELECT key, val, "+KS_FOO+".corjf(val) FROM %s"),
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
                    row(1, 1d, 1d),
                    row(2, 2d, 2d),
                    row(3, 3d, 3d)
@@ -266,18 +305,18 @@ public class UFTest extends CQLTester
 
         String functionBody = "\n  return Long.valueOf(1L);\n";
 
-        String cql = String.format("CREATE OR REPLACE FUNCTION %s.jfnpt() 
RETURNS bigint LANGUAGE JAVA\n" +
-                     "AS '%s';", KEYSPACE, functionBody);
-
-        execute(cql);
+        String fName = createFunction(KEYSPACE, "",
+                                      "CREATE OR REPLACE FUNCTION %s() RETURNS 
bigint LANGUAGE JAVA\n" +
+                                      "AS '" +functionBody + "';");
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions 
WHERE keyspace_name=? AND function_name='jfnpt'", KEYSPACE),
+        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, "+KEYSPACE+".jfnpt() FROM %s"),
+        assertRows(execute("SELECT key, val, " + fName + "() FROM %s"),
                    row(1, 1d, 1L),
                    row(2, 2d, 1L),
                    row(3, 3d, 1L)
@@ -289,7 +328,7 @@ public class UFTest extends CQLTester
     {
         try
         {
-            execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jfinv() RETURNS 
bigint LANGUAGE JAVA\n" +
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() 
RETURNS bigint LANGUAGE JAVA\n" +
                     "AS '\n" +
                     "foobarbaz" +
                     "\n';");
@@ -303,7 +342,7 @@ public class UFTest extends CQLTester
 
         try
         {
-            execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jfinv() RETURNS 
bigint LANGUAGE JAVA\n" +
+            execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".jfinv() 
RETURNS bigint LANGUAGE JAVA\n" +
                     "AS '\n" +
                     "foobarbaz;" +
                     "\n';");
@@ -319,13 +358,8 @@ public class UFTest extends CQLTester
     @Test
     public void testJavaFunctionInvalidReturn() throws Throwable
     {
-        String functionBody = "\n" +
-                              "  return Long.valueOf(1L);\n";
-
-        String cql = "CREATE OR REPLACE FUNCTION jfir(val double) RETURNS 
double LANGUAGE JAVA\n" +
-                     "AS '" + functionBody + "';";
-
-        assertInvalid(cql);
+        assertInvalid("CREATE OR REPLACE FUNCTION jfir(val double) RETURNS 
double LANGUAGE JAVA\n" +
+                      "AS 'return Long.valueOf(1L);';");
     }
 
     @Test
@@ -333,18 +367,15 @@ public class UFTest extends CQLTester
     {
         createTable("CREATE TABLE %s (key int primary key, val bigint)");
 
-        String functionBody = "\n" +
-                              "  return val;\n";
-
-        String cql = "CREATE OR REPLACE FUNCTION "+KEYSPACE+".jft(val double) 
RETURNS double LANGUAGE JAVA\n" +
-                     "AS '" + functionBody + "';";
-
-        execute(cql);
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION " + KEYSPACE 
+ ".jft(val double)" +
+                                      "RETURNS double LANGUAGE JAVA " +
+                                      "AS 'return 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);
-        assertInvalid("SELECT key, val, "+KEYSPACE+".jft(val) FROM %s");
+        assertInvalid("SELECT key, val, " + fName + "(val) FROM %s");
     }
 
     @Test
@@ -361,18 +392,22 @@ public class UFTest extends CQLTester
                               "  double v = Math.sin( val.doubleValue() );\n" +
                               "  return Double.valueOf(v);\n";
 
-        String cql = String.format("CREATE OR REPLACE FUNCTION %s.jft(val 
double) RETURNS double LANGUAGE JAVA\n" +
-                     "AS '%s';", KEYSPACE, functionBody);
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val 
double) " +
+                                      "RETURNS double " +
+                                      "LANGUAGE JAVA " +
+                                      "AS '" + functionBody + "';");
 
-        execute(cql);
+        FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions 
WHERE keyspace_name=? AND function_name='jft'", KEYSPACE),
+        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, " + KEYSPACE + ".jft(val) FROM 
%s"),
+        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))
@@ -384,25 +419,21 @@ public class UFTest extends CQLTester
     {
         createTable("CREATE TABLE %s (key int primary key, val double)");
 
-        execute("CREATE TABLE "+KS_FOO+".second_tab (key int primary key, val 
double)");
+        execute("CREATE TABLE " + KEYSPACE_PER_TEST + ".second_tab (key int 
primary key, val double)");
 
-        String functionBody = "\n" +
-                              "  return val;\n";
-
-        String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".jfitks(val double) 
RETURNS double LANGUAGE JAVA\n" +
-                     "AS '" + functionBody + "';";
-
-        execute(cql);
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val 
double) RETURNS double LANGUAGE JAVA " +
+                                      "AS 'return val;';");
 
         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);
-        assertInvalid("SELECT key, val, " + KEYSPACE + ".jfitks(val) FROM %s");
+        assertInvalid("SELECT key, val, " + parseFunctionName(fName).name + 
"(val) FROM %s");
 
-        execute("INSERT INTO "+KS_FOO+".second_tab (key, val) VALUES (?, ?)", 
1, 1d);
-        execute("INSERT INTO "+KS_FOO+".second_tab (key, val) VALUES (?, ?)", 
2, 2d);
-        execute("INSERT INTO "+KS_FOO+".second_tab (key, val) VALUES (?, ?)", 
3, 3d);
-        assertRows(execute("SELECT key, val, jfitks(val) FROM " + KS_FOO + 
".second_tab"),
+        execute("INSERT INTO " + KEYSPACE_PER_TEST + ".second_tab (key, val) 
VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO " + KEYSPACE_PER_TEST + ".second_tab (key, val) 
VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO " + KEYSPACE_PER_TEST + ".second_tab (key, val) 
VALUES (?, ?)", 3, 3d);
+        assertRows(execute("SELECT key, val, " + fName + "(val) FROM " + 
KEYSPACE_PER_TEST + ".second_tab"),
                    row(1, 1d, 1d),
                    row(2, 2d, 2d),
                    row(3, 3d, 3d)
@@ -412,26 +443,25 @@ public class UFTest extends CQLTester
     @Test
     public void testFunctionWithReservedName() throws Throwable
     {
-        execute("CREATE TABLE " + KS_FOO + ".second_tab (key int primary key, 
val double)");
-
-        String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".now() RETURNS 
timestamp LANGUAGE JAVA\n" +
-                     "AS 'return null;';";
+        execute("CREATE TABLE " + KEYSPACE_PER_TEST + ".second_tab (key int 
primary key, val double)");
 
-        execute(cql);
+        String fName = createFunction(KEYSPACE_PER_TEST, "",
+                                      "CREATE OR REPLACE FUNCTION %s() RETURNS 
timestamp LANGUAGE JAVA " +
+                                      "AS 'return null;';");
 
-        execute("INSERT INTO "+KS_FOO+".second_tab (key, val) VALUES (?, ?)", 
1, 1d);
-        execute("INSERT INTO "+KS_FOO+".second_tab (key, val) VALUES (?, ?)", 
2, 2d);
-        execute("INSERT INTO "+KS_FOO+".second_tab (key, val) VALUES (?, ?)", 
3, 3d);
+        execute("INSERT INTO " + KEYSPACE_PER_TEST + ".second_tab (key, val) 
VALUES (?, ?)", 1, 1d);
+        execute("INSERT INTO " + KEYSPACE_PER_TEST + ".second_tab (key, val) 
VALUES (?, ?)", 2, 2d);
+        execute("INSERT INTO " + KEYSPACE_PER_TEST + ".second_tab (key, val) 
VALUES (?, ?)", 3, 3d);
 
         // ensure that system now() is executed
-        UntypedResultSet rows = execute("SELECT key, val, now() FROM " + 
KS_FOO + ".second_tab");
+        UntypedResultSet rows = execute("SELECT key, val, now() FROM " + 
KEYSPACE_PER_TEST + ".second_tab");
         Assert.assertEquals(3, rows.size());
         UntypedResultSet.Row row = rows.iterator().next();
         Date ts = row.getTimestamp(row.getColumns().get(2).name.toString());
         Assert.assertNotNull(ts);
 
-        // ensure that KS_FOO's now() is executed
-        rows = execute("SELECT key, val, "+KS_FOO+".now() FROM " + KS_FOO + 
".second_tab");
+        // ensure that KEYSPACE_PER_TEST's now() is executed
+        rows = execute("SELECT key, val, " + fName + "() FROM " + 
KEYSPACE_PER_TEST + ".second_tab");
         Assert.assertEquals(3, rows.size());
         row = rows.iterator().next();
         Assert.assertFalse(row.has(row.getColumns().get(2).name.toString()));
@@ -460,19 +490,17 @@ public class UFTest extends CQLTester
     @Test
     public void testFunctionNonExistingKeyspace() throws Throwable
     {
-        String cql = "CREATE OR REPLACE FUNCTION 
this_ks_does_not_exist.jnft(val double) RETURNS double LANGUAGE JAVA\n" +
-                     "AS 'return null;';";
-        assertInvalid(cql);
+        assertInvalid("CREATE OR REPLACE FUNCTION 
this_ks_does_not_exist.jnft(val double) RETURNS double LANGUAGE JAVA\n" +
+                      "AS 'return null;';");
     }
 
     @Test
     public void testFunctionAfterOnDropKeyspace() throws Throwable
     {
-        dropKsFoo();
+        dropPerTestKeyspace();
 
-        String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".jnft(val double) 
RETURNS double LANGUAGE JAVA\n" +
-                     "AS 'return null;';";
-        assertInvalid(cql);
+        assertInvalid("CREATE OR REPLACE FUNCTION " + KEYSPACE_PER_TEST + 
".jnft(val double) RETURNS double LANGUAGE JAVA\n" +
+                      "AS 'return null;';");
     }
 
     @Test
@@ -489,18 +517,20 @@ public class UFTest extends CQLTester
                               "  double v = Math.sin( val.doubleValue() );\n" +
                               "  return Double.valueOf(v);\n";
 
-        String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".jnft(val double) 
RETURNS double LANGUAGE JAVA\n" +
-                     "AS '" + functionBody + "';";
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                     "CREATE OR REPLACE FUNCTION %s(val 
double) RETURNS double LANGUAGE JAVA " +
+                                     "AS '" + functionBody + "';");
 
-        execute(cql);
+        FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions 
WHERE keyspace_name='"+KS_FOO+"' AND function_name='jnft'"),
+        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, "+KS_FOO+".jnft(val) FROM %s"),
+        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))
@@ -515,12 +545,14 @@ public class UFTest extends CQLTester
         String functionBody = "\n" +
                               "  throw new RuntimeException(\"oh no!\");\n";
 
-        String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".jrtef(val double) 
RETURNS double LANGUAGE JAVA\n" +
-                     "AS '" + functionBody + "';";
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val 
double) RETURNS double LANGUAGE JAVA\n" +
+                                      "AS '" + functionBody + "';");
 
-        execute(cql);
+        FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions 
WHERE keyspace_name='"+KS_FOO+"' AND function_name='jrtef'"),
+        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);
@@ -528,7 +560,7 @@ public class UFTest extends CQLTester
         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
 
         // function throws a RuntimeException which is wrapped by 
InvalidRequestException
-        assertInvalid("SELECT key, val, "+KS_FOO+".jrtef(val) FROM %s");
+        assertInvalid("SELECT key, val, " + fName + "(val) FROM %s");
     }
 
     @Test
@@ -541,17 +573,825 @@ public class UFTest extends CQLTester
                               "    return null;\n" +
                               "  }\n" +
                               "  double v = Math.sin( input.doubleValue() 
);\n" +
-                              "  return \"'\"+Double.valueOf(v)+'\\\'';\n";
+                              "  return \"'\" + Double.valueOf(v)+'\\\'';\n";
 
-        execute("create function "+KS_FOO+".pgfun1 ( input double ) returns 
text language java\n" +
-                "AS $$" + functionBody + "$$;");
-        execute("CREATE FUNCTION "+KS_FOO+".pgsin ( input double ) RETURNS 
double LANGUAGE java AS $$return 
Double.valueOf(Math.sin(input.doubleValue()));$$");
+        String fName = createFunction(KEYSPACE_PER_TEST, "double",
+                                      "CREATE FUNCTION %s( input double ) " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$" + functionBody + "$$;");
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions 
WHERE keyspace_name='"+KS_FOO+"' AND function_name='pgfun1'"),
+        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 list<double> LANGUAGE java\n" +
+                                     "AS $$return lst;$$;");
+        String fSet = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                                     "CREATE FUNCTION %s( st set<text> ) " +
+                                     "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 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 <= 
Server.CURRENT_VERSION; version++)
+            assertRowsNet(version,
+                          executeNet(version, "SELECT " + fList + "(lst), " + 
fSet + "(st), " + fMap + "(mp) FROM %s WHERE key = 1"),
+                          row(list, set, map));
+    }
+
+    @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> ) 
" +
+                                      "RETURNS list<double> " +
+                                      "LANGUAGE java\n" +
+                                      "AS $$return coll;$$;");
+        String fSet = createFunction(KEYSPACE, "set<text>",
+                                     "CREATE FUNCTION %s( coll set<text> ) " +
+                                     "RETURNS set<text> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return coll;$$;");
+        String fMap = createFunction(KEYSPACE, "map<int, boolean>",
+                                     "CREATE FUNCTION %s( coll map<int, 
boolean> ) " +
+                                     "RETURNS map<int, boolean> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return coll;$$;");
+        String fTup = createFunction(KEYSPACE, "frozen<tuple<double, text, 
int, boolean>>",
+                                     "CREATE FUNCTION %s( val 
frozen<tuple<double, text, int, boolean>> ) " +
+                                     "RETURNS frozen<tuple<double, text, int, 
boolean>> " +
+                                     "LANGUAGE java\n" +
+                                     "AS $$return val;$$;");
+        String fUdt = createFunction(KEYSPACE, "frozen<" + type+'>',
+                                     "CREATE FUNCTION %s( val frozen<" + type 
+ "> ) " +
+                                     "RETURNS frozen<" + 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 = Server.VERSION_2; version <= 
Server.CURRENT_VERSION; 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, "frozen<tuple<double, text, 
int, boolean>>",
+                                     "CREATE FUNCTION %s( tup 
frozen<tuple<double, text, int, boolean>> ) " +
+                                     "RETURNS frozen<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 = "frozen<tuple<double, list<double>, set<text>, 
map<int, boolean>>>";
+
+        createTable("CREATE TABLE %s (key int primary key, tup " + 
tupleTypeDef + ")");
+
+        String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                "RETURNS " + tupleTypeDef + " " +
+                "LANGUAGE java\n" +
+                "AS $$return " +
+                "       tup;$$;");
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                "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 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 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 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 <= 
Server.CURRENT_VERSION; 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 <= 
Server.CURRENT_VERSION; version++)
+        {
+            executeNet(version, "USE " + KEYSPACE);
+
+            executeNet(version,
+                       "CREATE FUNCTION f_use1( udt frozen<" + type + "> ) " +
+                       "RETURNS frozen<" + 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 testJavaUserTypeOtherKeyspace() throws Throwable
+    {
+        String type = KEYSPACE + "." + createType("CREATE TYPE %s (txt text, i 
int)");
+
+        String fName = createFunction(KEYSPACE_PER_TEST, "frozen<" + type + 
">",
+                                      "CREATE FUNCTION %s( udt frozen<" + type 
+ "> ) " +
+                                      "RETURNS frozen<" + type + "> " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt;$$;");
+
+        execute("DROP FUNCTION " + fName);
+    }
+
+    @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, "frozen<" + type + ">",
+                                      "CREATE FUNCTION %s( udt frozen<" + type 
+ "> ) " +
+                                      "RETURNS frozen<" + type + "> " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt;$$;");
+        String fUdt1 = createFunction(KEYSPACE, "frozen<" + type + ">",
+                                      "CREATE FUNCTION %s( udt frozen<" + type 
+ "> ) " +
+                                      "RETURNS text " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     udt.getString(\"txt\");$$;");
+        String fUdt2 = createFunction(KEYSPACE, "frozen<" + type + ">",
+                                      "CREATE FUNCTION %s( udt frozen<" + type 
+ "> ) " +
+                                      "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 <= 
Server.CURRENT_VERSION; 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)");
+
+        createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type 
+ ">)");
+
+        String fName = createFunction(KEYSPACE, "frozen<" + type + ">",
+                                      "CREATE FUNCTION %s( udt frozen<" + type 
+ "> ) " +
+                                      "RETURNS int " +
+                                      "LANGUAGE java " +
+                                      "AS $$return " +
+                                      "     
Integer.valueOf(udt.getInt(\"i\"));$$;");
+
+        FunctionName fNameName = parseFunctionName(fName);
+
+        Assert.assertEquals(1, Functions.find(fNameName).size());
+
+        ResultMessage.Prepared prepared = 
QueryProcessor.prepare(String.format("SELECT key, %s(udt) FROM %s.%s", fName, 
KEYSPACE, currentTable()),
+                                                                 
ClientState.forInternalCalls(), false);
+        
Assert.assertNotNull(QueryProcessor.instance.getPrepared(prepared.statementId));
+
+        // UT still referenced by table
+        assertInvalid("DROP TYPE " + type);
+
+        execute("DROP TABLE %s");
+
+        // UT still referenced by UDF
+        assertInvalid("DROP TYPE " + type);
+
+        
Assert.assertNull(QueryProcessor.instance.getPrepared(prepared.statementId));
+
+        // function stays
+        Assert.assertEquals(1, Functions.find(fNameName).size());
+    }
+
+    @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, "frozen<" + type + ">",
+                                      "CREATE FUNCTION %s( udt frozen<" + type 
+ "> ) " +
+                                      "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");
+
+        assertInvalid("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, "frozen<" + type + ">",
+                                              "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                              "RETURNS text LANGUAGE java\n" +
+                                              "AS $$return 
udt.getString(\"txt\");$$;");
+        String fName2replace = createFunction(KEYSPACE, "frozen<" + type + ">",
+                                              "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                              "RETURNS int LANGUAGE java\n" +
+                                              "AS $$return 
Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3replace = createFunction(KEYSPACE, "frozen<" + type + ">",
+                                              "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                              "RETURNS double LANGUAGE java\n" 
+
+                                              "AS $$return 
Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4replace = createFunction(KEYSPACE, "frozen<" + type + ">",
+                                              "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                              "RETURNS frozen<" + type + "> 
LANGUAGE java\n" +
+                                              "AS $$return udt;$$;");
+
+        String fName1noReplace = createFunction(KEYSPACE, "frozen<" + type + 
">",
+                                              "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                              "RETURNS text LANGUAGE java\n" +
+                                              "AS $$return 
udt.getString(\"txt\");$$;");
+        String fName2noReplace = createFunction(KEYSPACE, "frozen<" + type + 
">",
+                                              "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                              "RETURNS int LANGUAGE java\n" +
+                                              "AS $$return 
Integer.valueOf(udt.getInt(\"i\"));$$;");
+        String fName3noReplace = createFunction(KEYSPACE, "frozen<" + type + 
">",
+                                                "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                                "RETURNS double LANGUAGE 
java\n" +
+                                                "AS $$return 
Double.valueOf(udt.getDouble(\"added\"));$$;");
+        String fName4noReplace = createFunction(KEYSPACE, "frozen<" + type + 
">",
+                                                "CREATE FUNCTION %s( udt 
frozen<" + type + "> ) " +
+                                                "RETURNS frozen<" + 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 frozen<%s> ) 
" +
+                              "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 frozen<%s> ) 
" +
+                              "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 frozen<%s> ) 
" +
+                              "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 frozen<%s> ) 
" +
+                              "RETURNS frozen<%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 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 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 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 <= 
Server.CURRENT_VERSION; 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 list<double> " +
+                "LANGUAGE javascript\n" +
+                "AS 'lst;';");
+        String fName2 = createFunction(KEYSPACE_PER_TEST, "set<text>",
+                "CREATE FUNCTION %s( st set<text> ) " +
+                "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 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 <= 
Server.CURRENT_VERSION; 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, "frozen<tuple<double, 
text, int, boolean>>",
+                "CREATE FUNCTION %s( tup frozen<tuple<double, text, int, 
boolean>> ) " +
+                "RETURNS frozen<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 = "frozen<tuple<double, list<double>, set<text>, 
map<int, boolean>>>";
+        createTable("CREATE TABLE %s (key int primary key, tup " + 
tupleTypeDef + ")");
+
+        String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                "RETURNS frozen<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 double LANGUAGE " +
+                "javascript\n" +
+                "AS $$" +
+                "       tup.getDouble(0);$$;");
+        String fTup3 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
+                "CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+                "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 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 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 <= 
Server.CURRENT_VERSION; 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, "frozen<" + type + ">",
+                              "CREATE FUNCTION %s( udt frozen<" + type + "> ) 
" +
+                              "RETURNS frozen<" + type + "> " +
+                              "LANGUAGE javascript\n" +
+                              "AS $$" +
+                              "     udt;$$;");
+        String fUdt2 = createFunction(KEYSPACE, "frozen<" + type + ">",
+                              "CREATE FUNCTION %s( udt frozen<" + type + "> ) 
" +
+                              "RETURNS text " +
+                              "LANGUAGE javascript\n" +
+                              "AS $$" +
+                              "     udt.getString(\"txt\");$$;");
+        String fUdt3 = createFunction(KEYSPACE, "frozen<" + type + ">",
+                              "CREATE FUNCTION %s( udt frozen<" + type + "> ) 
" +
+                              "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 text " +
+                       "LANGUAGE javascript\n" +
+                       "AS $$" +
+                       "        lst.get(1).getString(\"txt\");$$;");
+        createFunctionOverload(fName, "set<frozen<" + type + ">>",
+                               "CREATE FUNCTION %s( st set<frozen<" + type + 
">> ) " +
+                               "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 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 <= 
Server.CURRENT_VERSION; 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)");
@@ -559,18 +1399,21 @@ public class UFTest extends CQLTester
         String functionBody = "\n" +
                               "  Math.sin(val);\n";
 
-        String cql = "CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsft(val double) 
RETURNS double LANGUAGE javascript\n" +
-                     "AS '" + functionBody + "';";
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val 
double) " +
+                                      "RETURNS double LANGUAGE javascript\n" +
+                                      "AS '" + functionBody + "';");
 
-        execute(cql);
+        FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions 
WHERE keyspace_name='"+KEYSPACE+"' AND function_name='jsft'"),
+        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, jsft(val) FROM %s"),
+        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))
@@ -582,12 +1425,15 @@ public class UFTest extends CQLTester
     {
         createTable("CREATE TABLE %s (key int primary key, val double)");
 
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsft(val double) 
RETURNS double LANGUAGE javascript\n" +
-                "AS '\"string\";';");
+        String fName = createFunction(KEYSPACE, "double",
+                                      "CREATE OR REPLACE FUNCTION %s(val 
double) " +
+                                      "RETURNS double " +
+                                      "LANGUAGE javascript\n" +
+                                      "AS '\"string\";';");
 
         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
         // throws IRE with ClassCastException
-        assertInvalid("SELECT key, val, jsft(val) FROM %s");
+        assertInvalid("SELECT key, val, " + fName + "(val) FROM %s");
     }
 
     @Test
@@ -595,32 +1441,38 @@ public class UFTest extends CQLTester
     {
         createTable("CREATE TABLE %s (key int primary key, val double)");
 
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsft(val double) 
RETURNS double LANGUAGE javascript\n" +
-                "AS 'throw \"fool\";';");
+        String fName = createFunction(KEYSPACE, "double",
+                       "CREATE OR REPLACE FUNCTION %s(val double) " +
+                       "RETURNS double " +
+                       "LANGUAGE javascript\n" +
+                       "AS 'throw \"fool\";';");
 
         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
         // throws IRE with ScriptException
-        assertInvalid("SELECT key, val, jsft(val) FROM %s");
+        assertInvalid("SELECT key, val, " + fName + "(val) FROM %s");
     }
 
     @Test
     public void testDuplicateArgNames() throws Throwable
     {
-        assertInvalid("CREATE OR REPLACE FUNCTION "+KEYSPACE+".scrinv(val 
double, val text) RETURNS text LANGUAGE javascript\n" +
+        assertInvalid("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val 
double, val text) " +
+                      "RETURNS text LANGUAGE javascript\n" +
                       "AS '\"foo bar\";';");
     }
 
     @Test
     public void testJavascriptCompileFailure() throws Throwable
     {
-        assertInvalid("CREATE OR REPLACE FUNCTION "+KEYSPACE+".scrinv(val 
double) RETURNS double LANGUAGE javascript\n" +
+        assertInvalid("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val 
double) " +
+                      "RETURNS double LANGUAGE javascript\n" +
                       "AS 'foo bar';");
     }
 
     @Test
     public void testScriptInvalidLanguage() throws Throwable
     {
-        assertInvalid("CREATE OR REPLACE FUNCTION "+KEYSPACE+".scrinv(val 
double) RETURNS double LANGUAGE artificial_intelligence\n" +
+        assertInvalid("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val 
double) " +
+                      "RETURNS double LANGUAGE artificial_intelligence\n" +
                       "AS 'question for 42?';");
     }
 
@@ -630,85 +1482,36 @@ public class UFTest extends CQLTester
         createTable("CREATE TABLE %s (key int primary key, val double)");
         execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
 
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS boolean LANGUAGE javascript\n" +
-                "AS 'true;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, true));
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS boolean LANGUAGE javascript\n" +
-                "AS 'false;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, false));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = int , return type = int
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS int LANGUAGE javascript\n" +
-                "AS '100;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, 100));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = int , return type = double
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS int LANGUAGE javascript\n" +
-                "AS '100.;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, 100));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = double , return type = int
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS double LANGUAGE javascript\n" +
-                "AS '100;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, 100d));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = double , return type = double
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS double LANGUAGE javascript\n" +
-                "AS '100.;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, 100d));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = bigint , return type = int
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS bigint LANGUAGE javascript\n" +
-                "AS '100;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, 100L));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = bigint , return type = double
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS bigint LANGUAGE javascript\n" +
-                "AS '100.;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, 100L));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = varint , return type = int
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS varint LANGUAGE javascript\n" +
-                "AS '100;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, BigInteger.valueOf(100L)));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = varint , return type = double
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS varint LANGUAGE javascript\n" +
-                "AS '100.;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, BigInteger.valueOf(100L)));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = decimal , return type = int
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS decimal LANGUAGE javascript\n" +
-                "AS 'parseInt(\"100\");';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, BigDecimal.valueOf(100d)));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
-
-        // declared rtype = decimal , return type = double
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".js(val double) 
RETURNS decimal LANGUAGE javascript\n" +
-                "AS '100.;';");
-        assertRows(execute("SELECT key, val, js(val) FROM %s"),
-                   row(1, 1d, BigDecimal.valueOf(100d)));
-        execute("DROP FUNCTION "+KEYSPACE+".js(double)");
+        Object[][] variations = new Object[][]
+                                {
+                                new Object[]    {   "true",     "boolean",  
true    },
+                                new Object[]    {   "false",    "boolean",  
false   },
+                                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 " +returnType + " " +
+                                          "LANGUAGE javascript " +
+                                          "AS '" + functionBody + ";';");
+            assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"),
+                       row(1, 1d, expectedResult));
+        }
     }
 
     @Test
@@ -718,46 +1521,29 @@ public class UFTest extends CQLTester
         execute("INSERT INTO %s (key, ival, lval, fval, dval, vval, ddval) 
VALUES (?, ?, ?, ?, ?, ?, ?)", 1,
                 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d));
 
-        // type = int
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsint(val int) 
RETURNS int LANGUAGE javascript\n" +
-                "AS 'val+1;';");
-        assertRows(execute("SELECT key, ival, jsint(ival) FROM %s"),
-                   row(1, 1, 2));
-        execute("DROP FUNCTION "+KEYSPACE+".jsint(int)");
-
-        // bigint
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsbigint(val bigint) 
RETURNS bigint LANGUAGE javascript\n" +
-                "AS 'val+1;';");
-        assertRows(execute("SELECT key, lval, jsbigint(lval) FROM %s"),
-                   row(1, 1L, 2L));
-        execute("DROP FUNCTION "+KEYSPACE+".jsbigint(bigint)");
-
-        // float
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsfloat(val float) 
RETURNS float LANGUAGE javascript\n" +
-                "AS 'val+1;';");
-        assertRows(execute("SELECT key, fval, jsfloat(fval) FROM %s"),
-                   row(1, 1f, 2f));
-        execute("DROP FUNCTION "+KEYSPACE+".jsfloat(float)");
-
-        // double
-        execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsdouble(val double) 
RETURNS double LANGUAGE javascript\n" +
-                "AS 'val+1;';");
-        assertRows(ex

<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/cassandra/blob/794d68b5/tools/lib/cassandra-driver-core-2.0.5.jar
----------------------------------------------------------------------
diff --git a/tools/lib/cassandra-driver-core-2.0.5.jar 
b/tools/lib/cassandra-driver-core-2.0.5.jar
deleted file mode 100644
index 260183e..0000000
Binary files a/tools/lib/cassandra-driver-core-2.0.5.jar and /dev/null differ

Reply via email to