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 2015/05/15 19:37:11 UTC
[3/5] cassandra git commit: Better support of null for UDF
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1937bed9/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 c9779b9..78c6dd9 100644
--- a/test/unit/org/apache/cassandra/cql3/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UFTest.java
@@ -46,6 +46,7 @@ public class UFTest extends CQLTester
String f = createFunction(KEYSPACE,
"double, double",
"CREATE OR REPLACE FUNCTION %s(state double, val double) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE javascript " +
"AS '\"string\";';");
@@ -57,6 +58,7 @@ public class UFTest extends CQLTester
createFunctionOverload(f,
"double, double",
"CREATE OR REPLACE FUNCTION %s(state int, val int) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE javascript " +
"AS '\"string\";';");
@@ -66,6 +68,7 @@ public class UFTest extends CQLTester
"int", "int");
schemaChange("CREATE OR REPLACE FUNCTION " + f + "(state int, val int) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE javascript " +
"AS '\"string\";';");
@@ -86,6 +89,7 @@ public class UFTest extends CQLTester
{
String fSin = createFunction(KEYSPACE_PER_TEST, "double",
"CREATE FUNCTION %s ( input double ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java " +
"AS 'return Double.valueOf(Math.sin(input.doubleValue()));'");
@@ -111,6 +115,7 @@ public class UFTest extends CQLTester
String fSin = createFunction(KEYSPACE_PER_TEST, "double",
"CREATE FUNCTION %s ( input double ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java " +
"AS 'return Double.valueOf(Math.sin(input.doubleValue()));'");
@@ -150,9 +155,10 @@ public class UFTest extends CQLTester
Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedInsert2.statementId));
execute("CREATE FUNCTION " + fSin + " ( input double ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java " +
- "AS 'return Double.valueOf(Math.sin(input.doubleValue()));'");
+ "AS 'return Double.valueOf(Math.sin(input));'");
Assert.assertEquals(1, Functions.find(fSinName).size());
@@ -220,7 +226,7 @@ public class UFTest extends CQLTester
createTable("CREATE TABLE %s (" +
" key int PRIMARY KEY," +
- " val " + collectionType + ")");
+ " val " + collectionType + ')');
ResultMessage.Prepared prepared = QueryProcessor.prepare(
String.format("INSERT INTO %s.%s (key, val) VALUES (?, %s)",
@@ -265,6 +271,7 @@ public class UFTest extends CQLTester
// provide a DelayedValue are removed from the cache in QueryProcessor
String function = createFunction(KEYSPACE_PER_TEST, "double",
"CREATE FUNCTION %s ( input double ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE javascript " +
"AS 'input'");
@@ -304,13 +311,22 @@ public class UFTest extends CQLTester
// simple creation
String fSin = createFunction(KEYSPACE_PER_TEST, "double",
"CREATE FUNCTION %s ( input double ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java " +
"AS 'return Math.sin(input);'");
// check we can't recreate the same function
- assertInvalidMessage("already exists", "CREATE FUNCTION " + fSin + " ( input double ) RETURNS double LANGUAGE java AS 'return Math.sin(input);'");
+ assertInvalidMessage("already exists",
+ "CREATE FUNCTION " + fSin + " ( input double ) " +
+ "CALLED ON NULL INPUT " +
+ "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 Math.sin(input);'");
+ execute("CREATE FUNCTION IF NOT EXISTS " + fSin + " ( input double ) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE java AS 'return Double.valueOf(Math.sin(input.doubleValue()));'");
// Validate that it works as expected
assertRows(execute("SELECT key, " + fSin + "(d) FROM %s"),
@@ -321,9 +337,16 @@ public class UFTest extends CQLTester
// Replace the method with incompatible return type
assertInvalidMessage("the new return type text is not compatible with the return type double of existing function",
- "CREATE OR REPLACE FUNCTION " + fSin + " ( input double ) RETURNS text LANGUAGE java AS 'return Double.valueOf(42d);'");
+ "CREATE OR REPLACE FUNCTION " + fSin + " ( input double ) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java AS 'return Double.valueOf(42d);'");
+
// proper replacement
- execute("CREATE OR REPLACE FUNCTION " + fSin + " ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(42d);'");
+ execute("CREATE OR REPLACE FUNCTION " + fSin + " ( input double ) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE java AS 'return Double.valueOf(42d);'");
// Validate the method as been replaced
assertRows(execute("SELECT key, " + fSin + "(d) FROM %s"),
@@ -335,6 +358,7 @@ public class UFTest extends CQLTester
// same function but other keyspace
String fSin2 = createFunction(KEYSPACE, "double",
"CREATE FUNCTION %s ( input double ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java " +
"AS 'return Math.sin(input);'");
@@ -370,6 +394,7 @@ public class UFTest extends CQLTester
String fRepeat = createFunction(KEYSPACE_PER_TEST, "text,int",
"CREATE FUNCTION %s(v text, n int) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java " +
"AS 'StringBuilder sb = new StringBuilder();\n" +
@@ -390,22 +415,38 @@ public class UFTest extends CQLTester
String fOverload = createFunction(KEYSPACE_PER_TEST, "varchar",
"CREATE FUNCTION %s ( input varchar ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java " +
"AS 'return \"f1\";'");
createFunctionOverload(fOverload,
"int",
- "CREATE OR REPLACE FUNCTION %s(i int) RETURNS text LANGUAGE java AS 'return \"f2\";'");
+ "CREATE OR REPLACE FUNCTION %s(i int) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "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\";'");
+ "CREATE OR REPLACE FUNCTION %s(v1 text, v2 text) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java " +
+ "AS 'return \"f3\";'");
createFunctionOverload(fOverload,
"ascii",
- "CREATE OR REPLACE FUNCTION %s(v ascii) RETURNS text LANGUAGE java AS 'return \"f1\";'");
+ "CREATE OR REPLACE FUNCTION %s(v ascii) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java " +
+ "AS 'return \"f1\";'");
// text == varchar, so this should be considered as a duplicate
assertInvalidMessage("already exists",
- "CREATE FUNCTION " + fOverload + "(v varchar) RETURNS text LANGUAGE java AS 'return \"f1\";'");
+ "CREATE FUNCTION " + fOverload + "(v varchar) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java AS 'return \"f1\";'");
assertRows(execute("SELECT " + fOverload + "(k), " + fOverload + "(v), " + fOverload + "(k, k) FROM %s"),
row("f1", "f2", "f3")
@@ -451,7 +492,9 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE_PER_TEST, "double",
"CREATE FUNCTION %s( input double ) " +
- "RETURNS double LANGUAGE java\n" +
+ "CALLED ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE java " +
"AS '\n" +
" // parameter val is of type java.lang.Double\n" +
" /* return type is of type java.lang.Double */\n" +
@@ -469,7 +512,9 @@ public class UFTest extends CQLTester
);
execute("CREATE OR REPLACE FUNCTION " + fName + "( input double ) " +
- "RETURNS double LANGUAGE java\n" +
+ "CALLED ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE java\n" +
"AS '\n" +
" return input;\n" +
"';");
@@ -490,7 +535,10 @@ public class UFTest extends CQLTester
String functionBody = "\n return 1L;\n";
String fName = createFunction(KEYSPACE, "",
- "CREATE OR REPLACE FUNCTION %s() RETURNS bigint LANGUAGE JAVA\n" +
+ "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=?",
@@ -512,7 +560,10 @@ 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 NULL ON NULL INPUT " +
+ "RETURNS bigint " +
+ "LANGUAGE JAVA\n" +
"AS '\n" +
"foobarbaz" +
"\n';");
@@ -526,7 +577,10 @@ 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 NULL ON NULL INPUT " +
+ "RETURNS bigint " +
+ "LANGUAGE JAVA\n" +
"AS '\n" +
"foobarbaz;" +
"\n';");
@@ -543,7 +597,10 @@ public class UFTest extends CQLTester
public void testJavaFunctionInvalidReturn() throws Throwable
{
assertInvalidMessage("system keyspace is not user-modifiable",
- "CREATE OR REPLACE FUNCTION jfir(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION jfir(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS 'return 1L;';");
}
@@ -554,8 +611,10 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "double",
"CREATE OR REPLACE FUNCTION %s(val double)" +
- "RETURNS double LANGUAGE JAVA " +
- "AS 'return val;';");
+ "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);
@@ -579,6 +638,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "double",
"CREATE OR REPLACE FUNCTION %s(val double) " +
+ "CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE JAVA " +
"AS '" + functionBody + "';");
@@ -607,8 +667,11 @@ public class UFTest extends CQLTester
execute("CREATE TABLE " + KEYSPACE_PER_TEST + ".second_tab (key int primary key, val double)");
String fName = createFunction(KEYSPACE_PER_TEST, "double",
- "CREATE OR REPLACE FUNCTION %s(val double) RETURNS double LANGUAGE JAVA " +
- "AS 'return val;';");
+ "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, 1d);
execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
@@ -632,7 +695,10 @@ public class UFTest extends CQLTester
execute("CREATE TABLE " + KEYSPACE_PER_TEST + ".second_tab (key int primary key, val double)");
String fName = createFunction(KEYSPACE_PER_TEST, "",
- "CREATE OR REPLACE FUNCTION %s() RETURNS timestamp LANGUAGE JAVA " +
+ "CREATE OR REPLACE FUNCTION %s() " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS timestamp " +
+ "LANGUAGE JAVA " +
"AS 'return null;';");
execute("INSERT INTO " + KEYSPACE_PER_TEST + ".second_tab (key, val) VALUES (?, ?)", 1, 1d);
@@ -656,24 +722,39 @@ public class UFTest extends CQLTester
@Test
public void testFunctionInSystemKS() throws Throwable
{
- execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".dateof(val timeuuid) RETURNS timestamp LANGUAGE JAVA\n" +
+ execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".dateof(val timeuuid) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS timestamp " +
+ "LANGUAGE JAVA\n" +
"AS 'return null;';");
assertInvalidMessage("system keyspace is not user-modifiable",
- "CREATE OR REPLACE FUNCTION system.jnft(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION system.jnft(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS 'return null;';");
assertInvalidMessage("system keyspace is not user-modifiable",
- "CREATE OR REPLACE FUNCTION system.dateof(val timeuuid) RETURNS timestamp LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION system.dateof(val timeuuid) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS timestamp " +
+ "LANGUAGE JAVA\n" +
"AS 'return null;';");
assertInvalidMessage("system keyspace is not user-modifiable",
"DROP FUNCTION system.now");
// KS for executeInternal() is system
assertInvalidMessage("system keyspace is not user-modifiable",
- "CREATE OR REPLACE FUNCTION jnft(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION jnft(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS 'return null;';");
assertInvalidMessage("system keyspace is not user-modifiable",
- "CREATE OR REPLACE FUNCTION dateof(val timeuuid) RETURNS timestamp LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION dateof(val timeuuid) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS timestamp " +
+ "LANGUAGE JAVA\n" +
"AS 'return null;';");
assertInvalidMessage("system keyspace is not user-modifiable",
"DROP FUNCTION now");
@@ -683,7 +764,10 @@ public class UFTest extends CQLTester
public void testFunctionNonExistingKeyspace() throws Throwable
{
assertInvalidMessage("to non existing keyspace",
- "CREATE OR REPLACE FUNCTION this_ks_does_not_exist.jnft(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION this_ks_does_not_exist.jnft(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS 'return null;';");
}
@@ -693,7 +777,10 @@ public class UFTest extends CQLTester
dropPerTestKeyspace();
assertInvalidMessage("to non existing keyspace",
- "CREATE OR REPLACE FUNCTION " + KEYSPACE_PER_TEST + ".jnft(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE_PER_TEST + ".jnft(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS 'return null;';");
}
@@ -711,7 +798,10 @@ public class UFTest extends CQLTester
" return Math.sin( val );\n";
String fName = createFunction(KEYSPACE_PER_TEST, "double",
- "CREATE OR REPLACE FUNCTION %s(val double) RETURNS double LANGUAGE JAVA " +
+ "CREATE OR REPLACE FUNCTION %s(val double) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA " +
"AS '" + functionBody + "';");
FunctionName fNameName = parseFunctionName(fName);
@@ -739,7 +829,10 @@ public class UFTest extends CQLTester
" throw new RuntimeException(\"oh no!\");\n";
String fName = createFunction(KEYSPACE_PER_TEST, "double",
- "CREATE OR REPLACE FUNCTION %s(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION %s(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS '" + functionBody + "';");
FunctionName fNameName = parseFunctionName(fName);
@@ -770,6 +863,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE_PER_TEST, "double",
"CREATE FUNCTION %s( input double ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java\n" +
"AS $$" + functionBody + "$$;");
@@ -788,15 +882,21 @@ public class UFTest extends CQLTester
String fList = createFunction(KEYSPACE_PER_TEST, "list<double>",
"CREATE FUNCTION %s( lst list<double> ) " +
- "RETURNS list<double> LANGUAGE java\n" +
+ "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 set<text> LANGUAGE java\n" +
+ "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 map<int, boolean> LANGUAGE java\n" +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS map<int, boolean> " +
+ "LANGUAGE java\n" +
"AS $$return mp;$$;");
List<Double> list = Arrays.asList(1d, 2d, 3d);
@@ -828,26 +928,31 @@ public class UFTest extends CQLTester
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, "frozen<tuple<double, text, int, boolean>>",
"CREATE FUNCTION %s( val frozen<tuple<double, text, int, boolean>> ) " +
+ "CALLED ON NULL INPUT " +
"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 + "> ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS frozen<" + type + "> " +
"LANGUAGE java\n" +
"AS $$return val;$$;");
@@ -929,6 +1034,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "frozen<tuple<double, text, int, boolean>>",
"CREATE FUNCTION %s( tup frozen<tuple<double, text, int, boolean>> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS frozen<tuple<double, text, int, boolean>> " +
"LANGUAGE java\n" +
"AS $$return tup;$$;");
@@ -953,30 +1059,35 @@ public class UFTest extends CQLTester
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 list<double> " +
- "LANGUAGE java\n" +
- "AS $$return " +
- " tup.getList(1, Double.class);$$;");
+ "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 " +
@@ -1042,6 +1153,7 @@ public class UFTest extends CQLTester
executeNet(version,
"CREATE FUNCTION f_use1( udt frozen<" + type + "> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS frozen<" + type + "> " +
"LANGUAGE java " +
"AS $$return " +
@@ -1068,6 +1180,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE_PER_TEST, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS frozen<" + type + "> " +
"LANGUAGE java " +
"AS $$return " +
@@ -1085,18 +1198,21 @@ public class UFTest extends CQLTester
String fUdt0 = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS frozen<" + type + "> " +
"LANGUAGE java " +
"AS $$return " +
" udt;$$;");
String fUdt1 = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java " +
"AS $$return " +
" udt.getString(\"txt\");$$;");
String fUdt2 = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java " +
"AS $$return " +
@@ -1136,6 +1252,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ "CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java " +
"AS $$return " +
@@ -1172,7 +1289,9 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
- "RETURNS text LANGUAGE java\n" +
+ "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})");
@@ -1200,36 +1319,52 @@ public class UFTest extends CQLTester
String fName1replace = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
- "RETURNS text LANGUAGE java\n" +
+ "RETURNS NULL ON NULL INPUT " +
+ "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" +
+ "CALLED ON NULL INPUT " +
+ "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" +
+ "CALLED ON NULL INPUT " +
+ "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" +
+ "RETURNS NULL ON NULL INPUT " +
+ "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" +
+ "RETURNS NULL ON NULL INPUT " +
+ "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" +
+ "CALLED ON NULL INPUT " +
+ "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" +
+ "CALLED ON NULL INPUT " +
+ "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" +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS frozen<" + type + "> " +
+ "LANGUAGE java\n" +
"AS $$return udt;$$;");
execute("INSERT INTO %s (key, udt) VALUES (1, {txt: 'one', i:1})");
@@ -1249,25 +1384,33 @@ public class UFTest extends CQLTester
// means we need to recreate the functions
execute(String.format("CREATE OR REPLACE FUNCTION %s( udt frozen<%s> ) " +
- "RETURNS text LANGUAGE java\n" +
+ "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 frozen<%s> ) " +
- "RETURNS int LANGUAGE java\n" +
+ "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 frozen<%s> ) " +
- "RETURNS double LANGUAGE java\n" +
+ "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 frozen<%s> ) " +
- "RETURNS frozen<%s> LANGUAGE java\n" +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS frozen<%s> " +
+ "LANGUAGE java\n" +
"AS $$return " +
" udt;$$;",
fName4replace, type, type));
@@ -1315,19 +1458,25 @@ public class UFTest extends CQLTester
String fName1 = createFunction(KEYSPACE, "list<frozen<" + type + ">>",
"CREATE FUNCTION %s( lst list<frozen<" + type + ">> ) " +
- "RETURNS text LANGUAGE java\n" +
+ "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 text LANGUAGE java\n" +
- "AS $$" +
- " com.datastax.driver.core.UDTValue udtVal = (com.datastax.driver.core.UDTValue)st.iterator().next();" +
- " return udtVal.getString(\"txt\");$$;");
+ "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 text LANGUAGE java\n" +
+ "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\");$$;");
@@ -1353,16 +1502,19 @@ public class UFTest extends CQLTester
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;';");
@@ -1395,6 +1547,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE_PER_TEST, "frozen<tuple<double, text, int, boolean>>",
"CREATE FUNCTION %s( tup frozen<tuple<double, text, int, boolean>> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS frozen<tuple<double, text, int, boolean>> " +
"LANGUAGE javascript\n" +
"AS $$tup;$$;");
@@ -1418,30 +1571,35 @@ public class UFTest extends CQLTester
String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
"CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
+ "RETURNS NULL ON NULL INPUT " +
"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" +
+ "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 $$" +
@@ -1504,22 +1662,25 @@ public class UFTest extends CQLTester
String fUdt1 = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS frozen<" + type + "> " +
"LANGUAGE javascript\n" +
"AS $$" +
" udt;$$;");
String fUdt2 = createFunction(KEYSPACE, "frozen<" + type + '>',
"CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ "RETURNS NULL ON NULL INPUT " +
"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\");$$;");
+ "CREATE FUNCTION %s( udt frozen<" + 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})");
@@ -1541,19 +1702,22 @@ public class UFTest extends CQLTester
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\");$$;");
+ "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 $$" +
@@ -1595,7 +1759,9 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "double",
"CREATE OR REPLACE FUNCTION %s(val double) " +
- "RETURNS double LANGUAGE javascript\n" +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE javascript\n" +
"AS '" + functionBody + "';");
FunctionName fNameName = parseFunctionName(fName);
@@ -1621,6 +1787,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "double",
"CREATE OR REPLACE FUNCTION %s(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE javascript\n" +
"AS '\"string\";';");
@@ -1637,6 +1804,7 @@ public class UFTest extends CQLTester
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\";';");
@@ -1652,7 +1820,9 @@ public class UFTest extends CQLTester
{
assertInvalidMessage("duplicate argument names for given function",
"CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double, val text) " +
- "RETURNS text LANGUAGE javascript\n" +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE javascript\n" +
"AS '\"foo bar\";';");
}
@@ -1661,7 +1831,9 @@ public class UFTest extends CQLTester
{
assertInvalidMessage("Failed to compile function 'cql_test_keyspace.scrinv'",
"CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
- "RETURNS double LANGUAGE javascript\n" +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE javascript\n" +
"AS 'foo bar';");
}
@@ -1670,7 +1842,9 @@ public class UFTest extends CQLTester
{
assertInvalidMessage("Invalid language 'artificial_intelligence' for function 'cql_test_keyspace.scrinv'",
"CREATE OR REPLACE FUNCTION " + KEYSPACE + ".scrinv(val double) " +
- "RETURNS double LANGUAGE artificial_intelligence\n" +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE artificial_intelligence\n" +
"AS 'question for 42?';");
}
@@ -1703,6 +1877,7 @@ public class UFTest extends CQLTester
String fName = createFunction(KEYSPACE, "double",
"CREATE OR REPLACE FUNCTION %s(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
"RETURNS " +returnType + ' ' +
"LANGUAGE javascript " +
"AS '" + functionBody + ";';");
@@ -1735,6 +1910,7 @@ public class UFTest extends CQLTester
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;';");
@@ -1744,18 +1920,212 @@ public class UFTest extends CQLTester
}
@Test
+ public void testNullOnReturnsNullOnNullInput() throws Throwable
+ {
+ String type = createType("CREATE TYPE %s (txt text, i int)");
+ createTable("CREATE TABLE %s (key int PRIMARY KEY, i int, b bigint, f float, d double, x boolean, t text, u frozen<"+type+">, tup frozen<tuple<int, text>>)");
+
+ execute("INSERT INTO %s (key, i, b, f, d, x, t, u, tup) VALUES (1, null, null, null, null, null, null, null, null)");
+
+ String fI = createFunction(KEYSPACE,
+ "int",
+ "CREATE OR REPLACE FUNCTION %s(val int) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fB = createFunction(KEYSPACE,
+ "bigint",
+ "CREATE OR REPLACE FUNCTION %s(val bigint) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fF = createFunction(KEYSPACE,
+ "float",
+ "CREATE OR REPLACE FUNCTION %s(val float) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fD = createFunction(KEYSPACE,
+ "double",
+ "CREATE OR REPLACE FUNCTION %s(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fX = createFunction(KEYSPACE,
+ "boolean",
+ "CREATE OR REPLACE FUNCTION %s(val boolean) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fT = createFunction(KEYSPACE,
+ "text",
+ "CREATE OR REPLACE FUNCTION %s(val text) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fU = createFunction(KEYSPACE,
+ "frozen<" + type + '>',
+ "CREATE OR REPLACE FUNCTION %s(val frozen<" + type + ">) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fTup = createFunction(KEYSPACE,
+ "frozen<tuple<int, text>>",
+ "CREATE OR REPLACE FUNCTION %s(val frozen<tuple<int, text>>) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+
+ assertRows(execute("SELECT " + fI + "(i) FROM %s WHERE key=1"), row(new Object[]{null}));
+ assertRows(execute("SELECT " + fB + "(b) FROM %s WHERE key=1"), row(new Object[]{null}));
+ assertRows(execute("SELECT " + fF + "(f) FROM %s WHERE key=1"), row(new Object[]{null}));
+ assertRows(execute("SELECT " + fD + "(d) FROM %s WHERE key=1"), row(new Object[]{null}));
+ assertRows(execute("SELECT " + fX + "(x) FROM %s WHERE key=1"), row(new Object[]{null}));
+ assertRows(execute("SELECT " + fT + "(t) FROM %s WHERE key=1"), row(new Object[]{null}));
+ assertRows(execute("SELECT " + fU + "(u) FROM %s WHERE key=1"), row(new Object[]{null}));
+ assertRows(execute("SELECT " + fTup + "(tup) FROM %s WHERE key=1"), row(new Object[]{null}));
+ }
+
+ @Test
+ public void testReplaceAllowNulls() throws Throwable
+ {
+ String fNulls = createFunction(KEYSPACE,
+ "int",
+ "CREATE OR REPLACE FUNCTION %s(val int) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fNoNulls = createFunction(KEYSPACE,
+ "int",
+ "CREATE OR REPLACE FUNCTION %s(val int) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+
+ assertInvalid("CREATE OR REPLACE FUNCTION " + fNulls + "(val int) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ assertInvalid("CREATE OR REPLACE FUNCTION " + fNoNulls + "(val int) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+
+ execute("CREATE OR REPLACE FUNCTION " + fNulls + "(val int) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ execute("CREATE OR REPLACE FUNCTION " + fNoNulls + "(val int) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ }
+
+ @Test
+ public void testNullOnCalledOnNullInput() throws Throwable
+ {
+ String type = createType("CREATE TYPE %s (txt text, i int)");
+ createTable("CREATE TABLE %s (key int PRIMARY KEY, i int, b bigint, f float, d double, x boolean, t text, u frozen<"+type+">, tup frozen<tuple<int, text>>)");
+
+ execute("INSERT INTO %s (key, i, b, f, d, x, t, u, tup) VALUES (1, null, null, null, null, null, null, null, null)");
+
+ String fI = createFunction(KEYSPACE,
+ "int",
+ "CREATE OR REPLACE FUNCTION %s(val int) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fB = createFunction(KEYSPACE,
+ "bigint",
+ "CREATE OR REPLACE FUNCTION %s(val bigint) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fF = createFunction(KEYSPACE,
+ "float",
+ "CREATE OR REPLACE FUNCTION %s(val float) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fD = createFunction(KEYSPACE,
+ "double",
+ "CREATE OR REPLACE FUNCTION %s(val double) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fX = createFunction(KEYSPACE,
+ "boolean",
+ "CREATE OR REPLACE FUNCTION %s(val boolean) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fT = createFunction(KEYSPACE,
+ "text",
+ "CREATE OR REPLACE FUNCTION %s(val text) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fU = createFunction(KEYSPACE,
+ "frozen<" + type + '>',
+ "CREATE OR REPLACE FUNCTION %s(val frozen<" + type + ">) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+ String fTup = createFunction(KEYSPACE,
+ "frozen<tuple<int, text>>",
+ "CREATE OR REPLACE FUNCTION %s(val frozen<tuple<int, text>>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return \"foo bar\";';");
+
+ assertRows(execute("SELECT " + fI + "(i) FROM %s WHERE key=1"), row("foo bar"));
+ assertRows(execute("SELECT " + fB + "(b) FROM %s WHERE key=1"), row("foo bar"));
+ assertRows(execute("SELECT " + fF + "(f) FROM %s WHERE key=1"), row("foo bar"));
+ assertRows(execute("SELECT " + fD + "(d) FROM %s WHERE key=1"), row("foo bar"));
+ assertRows(execute("SELECT " + fX + "(x) FROM %s WHERE key=1"), row("foo bar"));
+ assertRows(execute("SELECT " + fT + "(t) FROM %s WHERE key=1"), row("foo bar"));
+ assertRows(execute("SELECT " + fU + "(u) FROM %s WHERE key=1"), row("foo bar"));
+ assertRows(execute("SELECT " + fTup + "(tup) FROM %s WHERE key=1"), row("foo bar"));
+ }
+
+ @Test
public void testBrokenFunction() throws Throwable
{
createTable("CREATE TABLE %s (key int primary key, dval double)");
execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
String fName = createFunction(KEYSPACE_PER_TEST, "double",
- "CREATE OR REPLACE FUNCTION %s(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION %s(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS 'throw new RuntimeException();';");
UDFunction f = (UDFunction) Functions.find(parseFunctionName(fName)).get(0);
- Functions.replaceFunction(UDFunction.createBrokenFunction(f.name(), f.argNames(), f.argTypes(), f.returnType(),
+ Functions.replaceFunction(UDFunction.createBrokenFunction(f.name(), f.argNames(), f.argTypes(), f.returnType(), true,
"java", f.body(), new InvalidRequestException("foo bar is broken")));
assertInvalidThrowMessage("foo bar is broken", InvalidRequestException.class,
@@ -1770,7 +2140,10 @@ public class UFTest extends CQLTester
execute("INSERT INTO %s (key, dval) VALUES (?, ?)", 1, 1d);
String fName = createFunction(KEYSPACE_PER_TEST, "double",
- "CREATE OR REPLACE FUNCTION %s(val double) RETURNS double LANGUAGE JAVA\n" +
+ "CREATE OR REPLACE FUNCTION %s(val double) " +
+ "RETURNS NULL ON NULL INPUT " +
+ "RETURNS double " +
+ "LANGUAGE JAVA\n" +
"AS 'throw new RuntimeException()';");
for (int version = Server.VERSION_2; version <= maxProtocolVersion; version++)