Repository: cassandra Updated Branches: refs/heads/trunk 41a35ec74 -> b4d7f3bed
http://git-wip-us.apache.org/repos/asf/cassandra/blob/b4d7f3be/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 95bede4..ce850b7 100644 --- a/test/unit/org/apache/cassandra/cql3/UFTest.java +++ b/test/unit/org/apache/cassandra/cql3/UFTest.java @@ -19,14 +19,82 @@ package org.apache.cassandra.cql3; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Date; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; +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.messages.ResultMessage; public class UFTest extends CQLTester { + private static final String KS_FOO = "cqltest_foo"; + + @Before + public void createKsFoo() throws Throwable + { + 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+";"); + } + + @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()));'"); + + Assert.assertEquals(1, Functions.find(new FunctionName(KS_FOO, "sin")).size()); + + assertRows(execute("SELECT function_name, language FROM system.schema_functions WHERE keyspace_name=?", KS_FOO), + row("sin", "java")); + + execute("DROP KEYSPACE "+KS_FOO+";"); + + assertRows(execute("SELECT function_name, language FROM system.schema_functions WHERE keyspace_name=?", KS_FOO)); + + Assert.assertEquals(0, Functions.find(new FunctionName(KS_FOO, "sin")).size()); + } + + @Test + public void testFunctionDropPreparedStatement() throws Throwable + { + 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()));'"); + + Assert.assertEquals(1, Functions.find(new FunctionName(KS_FOO, "sin")).size()); + + ResultMessage.Prepared prepared = QueryProcessor.prepare("SELECT key, "+KS_FOO+".sin(d) FROM "+KEYSPACE+'.'+currentTable(), ClientState.forInternalCalls(), false); + Assert.assertNotNull(QueryProcessor.instance.getPrepared(prepared.statementId)); + + execute("DROP FUNCTION " + KS_FOO + ".sin(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()));'"); + + Assert.assertEquals(1, Functions.find(new FunctionName(KS_FOO, "sin")).size()); + + prepared = QueryProcessor.prepare("SELECT key, "+KS_FOO+".sin(d) FROM "+KEYSPACE+'.'+currentTable(), ClientState.forInternalCalls(), false); + Assert.assertNotNull(QueryProcessor.instance.getPrepared(prepared.statementId)); + + execute("DROP KEYSPACE " + KS_FOO + ";"); + + Assert.assertNull(QueryProcessor.instance.getPrepared(prepared.statementId)); + } + @Test public void testFunctionCreationAndDrop() throws Throwable { @@ -37,45 +105,47 @@ public class UFTest extends CQLTester execute("INSERT INTO %s(key, d) VALUES (?, ?)", 3, 3d); // simple creation - execute("CREATE FUNCTION foo::sin ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(Math.sin(input.doubleValue()));'"); + execute("CREATE FUNCTION "+KS_FOO+".sin ( 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 foo::sin ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(Math.sin(input.doubleValue()));'"); + 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 foo::sin ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(Math.sin(input.doubleValue()));'"); + execute("CREATE FUNCTION IF NOT EXISTS "+KS_FOO+".sin ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(Math.sin(input.doubleValue()));'"); // Validate that it works as expected - assertRows(execute("SELECT key, foo::sin(d) FROM %s"), + assertRows(execute("SELECT key, "+KS_FOO+".sin(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);'"); // proper replacement - execute("CREATE OR REPLACE FUNCTION foo::sin ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(42d);'"); + execute("CREATE OR REPLACE FUNCTION "+KS_FOO+".sin ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(42d);'"); // Validate the method as been replaced - assertRows(execute("SELECT key, foo::sin(d) FROM %s"), + assertRows(execute("SELECT key, "+KS_FOO+".sin(d) FROM %s"), row(1, 42.0), row(2, 42.0), row(3, 42.0) ); // same function but without namespace - execute("CREATE FUNCTION sin ( input double ) RETURNS double LANGUAGE java AS 'return Double.valueOf(Math.sin(input.doubleValue()));'"); - assertRows(execute("SELECT key, sin(d) FROM %s"), + 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"), row(1, Math.sin(1d)), row(2, Math.sin(2d)), row(3, Math.sin(3d)) ); - // Drop with and without namespace - execute("DROP FUNCTION foo::sin"); - execute("DROP FUNCTION sin"); + // Drop with and without keyspace + execute("DROP FUNCTION "+KS_FOO+".sin"); + execute("DROP FUNCTION "+KEYSPACE+".sin"); // Drop unexisting function - assertInvalid("DROP FUNCTION foo::sin"); + assertInvalid("DROP FUNCTION "+KS_FOO+".sin"); // but don't complain with "IF EXISTS" - execute("DROP FUNCTION IF EXISTS foo::sin"); + execute("DROP FUNCTION IF EXISTS "+KS_FOO+".sin"); // can't drop native functions assertInvalid("DROP FUNCTION dateof"); @@ -92,13 +162,13 @@ public class UFTest extends CQLTester execute("INSERT INTO %s(v) VALUES (?)", "aaa"); - execute("CREATE FUNCTION repeat (v text, n int) RETURNS text LANGUAGE java AS 'StringBuilder sb = new StringBuilder();\n" + + 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=repeat(?, ?)", "a", 3), row("aaa")); - assertEmpty(execute("SELECT v FROM %s WHERE v=repeat(?, ?)", "a", 2)); + 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)); } @Test @@ -108,46 +178,46 @@ public class UFTest extends CQLTester execute("INSERT INTO %s(k, v) VALUES (?, ?)", "f2", 1); - execute("CREATE FUNCTION overloaded(v varchar) RETURNS text LANGUAGE java AS 'return \"f1\";'"); - execute("CREATE OR REPLACE FUNCTION overloaded(i int) RETURNS text LANGUAGE java AS 'return \"f2\";'"); - execute("CREATE OR REPLACE FUNCTION overloaded(v1 text, v2 text) RETURNS text LANGUAGE java AS 'return \"f3\";'"); - execute("CREATE OR REPLACE FUNCTION overloaded(v ascii) RETURNS text LANGUAGE java AS 'return \"f1\";'"); + 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\";'"); // text == varchar, so this should be considered as a duplicate - assertInvalid("CREATE FUNCTION overloaded(v varchar) RETURNS text LANGUAGE java AS 'return \"f1\";'"); + assertInvalid("CREATE FUNCTION "+KEYSPACE+".overloaded(v varchar) RETURNS text LANGUAGE java AS 'return \"f1\";'"); - assertRows(execute("SELECT overloaded(k), overloaded(v), overloaded(k, k) FROM %s"), + assertRows(execute("SELECT "+KEYSPACE+".overloaded(k), "+KEYSPACE+".overloaded(v), "+KEYSPACE+".overloaded(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 = overloaded(?)", "foo"); + assertInvalid("SELECT v FROM %s WHERE k = "+KEYSPACE+".overloaded(?)", "foo"); stopForcingPreparedValues(); // but those should since we specifically cast - assertEmpty(execute("SELECT v FROM %s WHERE k = overloaded((text)?)", "foo")); - assertRows(execute("SELECT v FROM %s WHERE k = overloaded((int)?)", 3), row(1)); - assertEmpty(execute("SELECT v FROM %s WHERE k = overloaded((ascii)?)", "foo")); + 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")); // And since varchar == text, this should work too - assertEmpty(execute("SELECT v FROM %s WHERE k = overloaded((varchar)?)", "foo")); + assertEmpty(execute("SELECT v FROM %s WHERE k = "+KEYSPACE+".overloaded((varchar)?)", "foo")); // no such functions exist... - assertInvalid("DROP FUNCTION overloaded(boolean)"); - assertInvalid("DROP FUNCTION overloaded(bigint)"); + assertInvalid("DROP FUNCTION "+KEYSPACE+".overloaded(boolean)"); + assertInvalid("DROP FUNCTION "+KEYSPACE+".overloaded(bigint)"); // 'overloaded' has multiple overloads - so it has to fail (CASSANDRA-7812) - assertInvalid("DROP FUNCTION overloaded"); - execute("DROP FUNCTION overloaded(varchar)"); - assertInvalid("SELECT v FROM %s WHERE k = overloaded((text)?)", "foo"); - execute("DROP FUNCTION overloaded(text, text)"); - assertInvalid("SELECT v FROM %s WHERE k = overloaded((text)?,(text)?)", "foo", "bar"); - execute("DROP FUNCTION overloaded(ascii)"); - assertInvalid("SELECT v FROM %s WHERE k = overloaded((ascii)?)", "foo"); + 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"); // single-int-overload must still work - assertRows(execute("SELECT v FROM %s WHERE k = overloaded((int)?)", 3), row(1)); + assertRows(execute("SELECT v FROM %s WHERE k = " + KEYSPACE + ".overloaded((int)?)", 3), row(1)); // overloaded has just one overload now - so the following DROP FUNCTION is not ambigious (CASSANDRA-7812) - execute("DROP FUNCTION overloaded"); + execute("DROP FUNCTION "+KEYSPACE+".overloaded"); } @Test @@ -158,7 +228,7 @@ 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 foo::corjf ( input double ) returns double language java\n" + + execute("create function "+KS_FOO+".corjf ( 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" + @@ -170,19 +240,19 @@ public class UFTest extends CQLTester "';"); // just check created function - assertRows(execute("SELECT key, val, foo::corjf(val) FROM %s"), + assertRows(execute("SELECT key, val, "+KS_FOO+".corjf(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 foo::corjf ( input double ) returns double language java\n" + + execute("create or replace function "+KS_FOO+".corjf ( input double ) returns double language java\n" + "AS '\n" + " return input;\n" + "';"); // check if replaced function returns correct result - assertRows(execute("SELECT key, val, foo::corjf(val) FROM %s"), + assertRows(execute("SELECT key, val, "+KS_FOO+".corjf(val) FROM %s"), row(1, 1d, 1d), row(2, 2d, 2d), row(3, 3d, 3d) @@ -196,18 +266,18 @@ public class UFTest extends CQLTester String functionBody = "\n return Long.valueOf(1L);\n"; - String cql = "CREATE OR REPLACE FUNCTION jfnpt() RETURNS bigint LANGUAGE JAVA\n" + - "AS '" + functionBody + "';"; + String cql = String.format("CREATE OR REPLACE FUNCTION %s.jfnpt() RETURNS bigint LANGUAGE JAVA\n" + + "AS '%s';", KEYSPACE, functionBody); execute(cql); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE namespace='' AND name='jfnpt'"), + assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name='jfnpt'", KEYSPACE), 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, jfnpt() FROM %s"), + assertRows(execute("SELECT key, val, "+KEYSPACE+".jfnpt() FROM %s"), row(1, 1d, 1L), row(2, 2d, 1L), row(3, 3d, 1L) @@ -219,7 +289,7 @@ public class UFTest extends CQLTester { try { - execute("CREATE OR REPLACE FUNCTION jfinv() RETURNS bigint LANGUAGE JAVA\n" + + execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jfinv() RETURNS bigint LANGUAGE JAVA\n" + "AS '\n" + "foobarbaz" + "\n';"); @@ -233,7 +303,7 @@ public class UFTest extends CQLTester try { - execute("CREATE OR REPLACE FUNCTION jfinv() RETURNS bigint LANGUAGE JAVA\n" + + execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jfinv() RETURNS bigint LANGUAGE JAVA\n" + "AS '\n" + "foobarbaz;" + "\n';"); @@ -266,7 +336,7 @@ public class UFTest extends CQLTester String functionBody = "\n" + " return val;\n"; - String cql = "CREATE OR REPLACE FUNCTION jft(val double) RETURNS double LANGUAGE JAVA\n" + + String cql = "CREATE OR REPLACE FUNCTION "+KEYSPACE+".jft(val double) RETURNS double LANGUAGE JAVA\n" + "AS '" + functionBody + "';"; execute(cql); @@ -274,7 +344,7 @@ public class UFTest extends CQLTester 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, jft(val) FROM %s"); + assertInvalid("SELECT key, val, "+KEYSPACE+".jft(val) FROM %s"); } @Test @@ -291,18 +361,18 @@ public class UFTest extends CQLTester " double v = Math.sin( val.doubleValue() );\n" + " return Double.valueOf(v);\n"; - String cql = "CREATE OR REPLACE FUNCTION jft(val double) RETURNS double LANGUAGE JAVA\n" + - "AS '" + functionBody + "';"; + String cql = String.format("CREATE OR REPLACE FUNCTION %s.jft(val double) RETURNS double LANGUAGE JAVA\n" + + "AS '%s';", KEYSPACE, functionBody); execute(cql); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE namespace='' AND name='jft'"), + assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name='jft'", KEYSPACE), 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, jft(val) FROM %s"), + assertRows(execute("SELECT key, val, " + KEYSPACE + ".jft(val) FROM %s"), row(1, 1d, Math.sin(1d)), row(2, 2d, Math.sin(2d)), row(3, 3d, Math.sin(3d)) @@ -310,7 +380,103 @@ public class UFTest extends CQLTester } @Test - public void testJavaNamespaceFunction() throws Throwable + public void testFunctionInTargetKeyspace() throws Throwable + { + createTable("CREATE TABLE %s (key int primary key, val double)"); + + execute("CREATE TABLE "+KS_FOO+".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); + + 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"); + + 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"), + row(1, 1d, 1d), + row(2, 2d, 2d), + row(3, 3d, 3d) + ); + } + + @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(cql); + + 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); + + // ensure that system now() is executed + UntypedResultSet rows = execute("SELECT key, val, now() FROM " + KS_FOO + ".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"); + Assert.assertEquals(3, rows.size()); + row = rows.iterator().next(); + Assert.assertFalse(row.has(row.getColumns().get(2).name.toString())); + } + + @Test + public void testFunctionInSystemKS() throws Throwable + { + execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".dateof(val timeuuid) RETURNS timestamp LANGUAGE JAVA\n" + + "AS 'return null;';"); + + assertInvalid("CREATE OR REPLACE FUNCTION system.jnft(val double) RETURNS double LANGUAGE JAVA\n" + + "AS 'return null;';"); + assertInvalid("CREATE OR REPLACE FUNCTION system.dateof(val timeuuid) RETURNS timestamp LANGUAGE JAVA\n" + + "AS 'return null;';"); + assertInvalid("DROP FUNCTION system.now"); + + // KS for executeInternal() is system + assertInvalid("CREATE OR REPLACE FUNCTION jnft(val double) RETURNS double LANGUAGE JAVA\n" + + "AS 'return null;';"); + assertInvalid("CREATE OR REPLACE FUNCTION dateof(val timeuuid) RETURNS timestamp LANGUAGE JAVA\n" + + "AS 'return null;';"); + assertInvalid("DROP FUNCTION now"); + } + + @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); + } + + @Test + public void testFunctionAfterOnDropKeyspace() throws Throwable + { + dropKsFoo(); + + String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".jnft(val double) RETURNS double LANGUAGE JAVA\n" + + "AS 'return null;';"; + assertInvalid(cql); + } + + @Test + public void testJavaKeyspaceFunction() throws Throwable { createTable("CREATE TABLE %s (key int primary key, val double)"); @@ -323,18 +489,18 @@ public class UFTest extends CQLTester " double v = Math.sin( val.doubleValue() );\n" + " return Double.valueOf(v);\n"; - String cql = "CREATE OR REPLACE FUNCTION foo::jnft(val double) RETURNS double LANGUAGE JAVA\n" + + String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".jnft(val double) RETURNS double LANGUAGE JAVA\n" + "AS '" + functionBody + "';"; execute(cql); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE namespace='foo' AND name='jnft'"), + assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name='"+KS_FOO+"' AND function_name='jnft'"), 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, foo::jnft(val) FROM %s"), + assertRows(execute("SELECT key, val, "+KS_FOO+".jnft(val) FROM %s"), row(1, 1d, Math.sin(1d)), row(2, 2d, Math.sin(2d)), row(3, 3d, Math.sin(3d)) @@ -349,12 +515,12 @@ public class UFTest extends CQLTester String functionBody = "\n" + " throw new RuntimeException(\"oh no!\");\n"; - String cql = "CREATE OR REPLACE FUNCTION foo::jrtef(val double) RETURNS double LANGUAGE JAVA\n" + + String cql = "CREATE OR REPLACE FUNCTION "+KS_FOO+".jrtef(val double) RETURNS double LANGUAGE JAVA\n" + "AS '" + functionBody + "';"; execute(cql); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE namespace='foo' AND name='jrtef'"), + assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name='"+KS_FOO+"' AND function_name='jrtef'"), row("java", functionBody)); execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d); @@ -362,7 +528,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, foo::jrtef(val) FROM %s"); + assertInvalid("SELECT key, val, "+KS_FOO+".jrtef(val) FROM %s"); } @Test @@ -377,11 +543,11 @@ public class UFTest extends CQLTester " double v = Math.sin( input.doubleValue() );\n" + " return \"'\"+Double.valueOf(v)+'\\\'';\n"; - execute("create function foo::pgfun1 ( input double ) returns text language java\n" + + execute("create function "+KS_FOO+".pgfun1 ( input double ) returns text language java\n" + "AS $$" + functionBody + "$$;"); - execute("CREATE FUNCTION foo::pgsin ( input double ) RETURNS double LANGUAGE java AS $$return Double.valueOf(Math.sin(input.doubleValue()));$$"); + execute("CREATE FUNCTION "+KS_FOO+".pgsin ( input double ) RETURNS double LANGUAGE java AS $$return Double.valueOf(Math.sin(input.doubleValue()));$$"); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE namespace='foo' AND name='pgfun1'"), + assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name='"+KS_FOO+"' AND function_name='pgfun1'"), row("java", functionBody)); } @@ -393,12 +559,12 @@ public class UFTest extends CQLTester String functionBody = "\n" + " Math.sin(val);\n"; - String cql = "CREATE OR REPLACE FUNCTION jsft(val double) RETURNS double LANGUAGE javascript\n" + + String cql = "CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsft(val double) RETURNS double LANGUAGE javascript\n" + "AS '" + functionBody + "';"; execute(cql); - assertRows(execute("SELECT language, body FROM system.schema_functions WHERE namespace='' AND name='jsft'"), + assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name='"+KEYSPACE+"' AND function_name='jsft'"), row("javascript", functionBody)); execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d); @@ -416,7 +582,7 @@ public class UFTest extends CQLTester { createTable("CREATE TABLE %s (key int primary key, val double)"); - execute("CREATE OR REPLACE FUNCTION jsft(val double) RETURNS double LANGUAGE javascript\n" + + execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsft(val double) RETURNS double LANGUAGE javascript\n" + "AS '\"string\";';"); execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d); @@ -429,7 +595,7 @@ public class UFTest extends CQLTester { createTable("CREATE TABLE %s (key int primary key, val double)"); - execute("CREATE OR REPLACE FUNCTION jsft(val double) RETURNS double LANGUAGE javascript\n" + + execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsft(val double) RETURNS double LANGUAGE javascript\n" + "AS 'throw \"fool\";';"); execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d); @@ -440,21 +606,21 @@ public class UFTest extends CQLTester @Test public void testDuplicateArgNames() throws Throwable { - assertInvalid("CREATE OR REPLACE FUNCTION 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 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 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?';"); } @@ -464,85 +630,85 @@ 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 js(val double) RETURNS boolean LANGUAGE javascript\n" + + 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 js(val double) RETURNS boolean LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = int , return type = int - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS int LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = int , return type = double - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS int LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = double , return type = int - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS double LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = double , return type = double - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS double LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = bigint , return type = int - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS bigint LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = bigint , return type = double - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS bigint LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = varint , return type = int - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS varint LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = varint , return type = double - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS varint LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = decimal , return type = int - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS decimal LANGUAGE javascript\n" + + 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(100L))); - execute("DROP FUNCTION js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); // declared rtype = decimal , return type = double - execute("CREATE OR REPLACE FUNCTION js(val double) RETURNS decimal LANGUAGE javascript\n" + + 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 js(double)"); + execute("DROP FUNCTION "+KEYSPACE+".js(double)"); } @Test @@ -553,45 +719,45 @@ public class UFTest extends CQLTester 1, 1L, 1f, 1d, BigInteger.valueOf(1L), BigDecimal.valueOf(1d)); // type = int - execute("CREATE OR REPLACE FUNCTION jsint(val int) RETURNS int LANGUAGE javascript\n" + + 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 jsint(int)"); + execute("DROP FUNCTION "+KEYSPACE+".jsint(int)"); // bigint - execute("CREATE OR REPLACE FUNCTION jsbigint(val bigint) RETURNS bigint LANGUAGE javascript\n" + + 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 jsbigint(bigint)"); + execute("DROP FUNCTION "+KEYSPACE+".jsbigint(bigint)"); // float - execute("CREATE OR REPLACE FUNCTION jsfloat(val float) RETURNS float LANGUAGE javascript\n" + + 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 jsfloat(float)"); + execute("DROP FUNCTION "+KEYSPACE+".jsfloat(float)"); // double - execute("CREATE OR REPLACE FUNCTION jsdouble(val double) RETURNS double LANGUAGE javascript\n" + + execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsdouble(val double) RETURNS double LANGUAGE javascript\n" + "AS 'val+1;';"); assertRows(execute("SELECT key, dval, jsdouble(dval) FROM %s"), row(1, 1d, 2d)); - execute("DROP FUNCTION jsdouble(double)"); + execute("DROP FUNCTION "+KEYSPACE+".jsdouble(double)"); // varint - execute("CREATE OR REPLACE FUNCTION jsvarint(val varint) RETURNS varint LANGUAGE javascript\n" + + execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsvarint(val varint) RETURNS varint LANGUAGE javascript\n" + "AS 'val+1;';"); assertRows(execute("SELECT key, vval, jsvarint(vval) FROM %s"), row(1, BigInteger.valueOf(1L), BigInteger.valueOf(2L))); - execute("DROP FUNCTION jsvarint(varint)"); + execute("DROP FUNCTION "+KEYSPACE+".jsvarint(varint)"); // decimal - execute("CREATE OR REPLACE FUNCTION jsdecimal(val decimal) RETURNS decimal LANGUAGE javascript\n" + + execute("CREATE OR REPLACE FUNCTION "+KEYSPACE+".jsdecimal(val decimal) RETURNS decimal LANGUAGE javascript\n" + "AS 'val+1;';"); assertRows(execute("SELECT key, ddval, jsdecimal(ddval) FROM %s"), row(1, BigDecimal.valueOf(1d), BigDecimal.valueOf(2d))); - execute("DROP FUNCTION jsdecimal(decimal)"); + execute("DROP FUNCTION "+KEYSPACE+".jsdecimal(decimal)"); } }