You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ty...@apache.org on 2015/05/28 19:16:45 UTC
cassandra git commit: Disallow frozen<> types in functions
Repository: cassandra
Updated Branches:
refs/heads/cassandra-2.2 14b98665b -> 1de8e39ed
Disallow frozen<> types in functions
Patch by Benjamin Lerer; reviewed by Tyler Hobbs for CASSANDRA-9441
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/1de8e39e
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1de8e39e
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1de8e39e
Branch: refs/heads/cassandra-2.2
Commit: 1de8e39ed5a00795ea16111931ca081024b4f325
Parents: 14b9866
Author: blerer <be...@datastax.com>
Authored: Thu May 28 12:16:03 2015 -0500
Committer: Tyler Hobbs <ty...@gmail.com>
Committed: Thu May 28 12:16:03 2015 -0500
----------------------------------------------------------------------
CHANGES.txt | 2 +
.../org/apache/cassandra/cql3/CQL3Type.java | 15 +
.../cql3/functions/AbstractFunction.java | 19 +
.../cassandra/cql3/functions/Function.java | 7 +-
.../cassandra/cql3/functions/FunctionCall.java | 2 +-
.../cassandra/cql3/selection/Selector.java | 17 +-
.../statements/CreateAggregateStatement.java | 18 +-
.../statements/CreateFunctionStatement.java | 19 +-
.../cql3/statements/DropAggregateStatement.java | 16 +-
.../cql3/statements/DropFunctionStatement.java | 12 +-
.../cassandra/db/marshal/AbstractType.java | 5 +
.../apache/cassandra/cql3/AggregationTest.java | 263 +++++++++++-
.../cassandra/cql3/UFIdentificationTest.java | 2 +-
test/unit/org/apache/cassandra/cql3/UFTest.java | 412 +++++++++++++++----
14 files changed, 713 insertions(+), 96 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index ad2845f..618f063 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,6 @@
2.2
+ * Disallow frozen<> types in function arguments and return types for
+ clarity (CASSANDRA-9411)
* Static Analysis to warn on unsafe use of Autocloseable instances (CASSANDRA-9431)
* Update commitlog archiving examples now that commitlog segments are
not recycled (CASSANDRA-9350)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/CQL3Type.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/CQL3Type.java b/src/java/org/apache/cassandra/cql3/CQL3Type.java
index e3ece93..290f4cb 100644
--- a/src/java/org/apache/cassandra/cql3/CQL3Type.java
+++ b/src/java/org/apache/cassandra/cql3/CQL3Type.java
@@ -315,6 +315,16 @@ public interface CQL3Type
return false;
}
+ public boolean isFrozen()
+ {
+ return this.frozen;
+ }
+
+ public boolean canBeNonFrozen()
+ {
+ return true;
+ }
+
public boolean isCounter()
{
return false;
@@ -494,6 +504,11 @@ public interface CQL3Type
frozen = true;
}
+ public boolean canBeNonFrozen()
+ {
+ return false;
+ }
+
public CQL3Type prepare(String keyspace) throws InvalidRequestException
{
if (name.hasKeyspace())
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java b/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
index 1f5349e..b77f4d5 100644
--- a/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
+++ b/src/java/org/apache/cassandra/cql3/functions/AbstractFunction.java
@@ -22,6 +22,8 @@ import java.util.List;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
+import org.apache.cassandra.cql3.AssignmentTestable;
+import org.apache.cassandra.cql3.ColumnSpecification;
import org.apache.cassandra.db.marshal.AbstractType;
/**
@@ -83,6 +85,23 @@ public abstract class AbstractFunction implements Function
return Objects.hashCode(name, argTypes, returnType);
}
+ public final AssignmentTestable.TestResult testAssignment(String keyspace, ColumnSpecification receiver)
+ {
+ // We should ignore the fact that the receiver type is frozen in our comparison as functions do not support
+ // frozen types for return type
+ AbstractType<?> returnType = returnType();
+ if (receiver.type.isFrozenCollection())
+ returnType = returnType.freeze();
+
+ if (receiver.type.equals(returnType))
+ return AssignmentTestable.TestResult.EXACT_MATCH;
+
+ if (receiver.type.isValueCompatibleWith(returnType))
+ return AssignmentTestable.TestResult.WEAKLY_ASSIGNABLE;
+
+ return AssignmentTestable.TestResult.NOT_ASSIGNABLE;
+ }
+
@Override
public String toString()
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/functions/Function.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/Function.java b/src/java/org/apache/cassandra/cql3/functions/Function.java
index 56119f7..ed6e2a7 100644
--- a/src/java/org/apache/cassandra/cql3/functions/Function.java
+++ b/src/java/org/apache/cassandra/cql3/functions/Function.java
@@ -19,11 +19,12 @@ package org.apache.cassandra.cql3.functions;
import java.util.List;
+import org.apache.cassandra.cql3.AssignmentTestable;
import org.apache.cassandra.db.marshal.AbstractType;
import org.github.jamm.Unmetered;
@Unmetered
-public interface Function
+public interface Function extends AssignmentTestable
{
public FunctionName name();
public List<AbstractType<?>> argTypes();
@@ -43,7 +44,7 @@ public interface Function
*/
public boolean isAggregate();
- Iterable<Function> getFunctions();
+ public Iterable<Function> getFunctions();
- boolean hasReferenceTo(Function function);
+ public boolean hasReferenceTo(Function function);
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java b/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
index 689da5a..4f53c98 100644
--- a/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
+++ b/src/java/org/apache/cassandra/cql3/functions/FunctionCall.java
@@ -133,7 +133,7 @@ public class FunctionCall extends Term.NonTerminal
// Functions.get() will complain if no function "name" type check with the provided arguments.
// We still have to validate that the return type matches however
- if (!receiver.type.isValueCompatibleWith(scalarFun.returnType()))
+ if (!scalarFun.testAssignment(keyspace, receiver).isAssignable())
throw new InvalidRequestException(String.format("Type error: cannot assign result of function %s (type %s) to %s (type %s)",
scalarFun.name(), scalarFun.returnType().asCQL3Type(),
receiver.name, receiver.type.asCQL3Type()));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/selection/Selector.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/selection/Selector.java b/src/java/org/apache/cassandra/cql3/selection/Selector.java
index 2d345de..747dc60 100644
--- a/src/java/org/apache/cassandra/cql3/selection/Selector.java
+++ b/src/java/org/apache/cassandra/cql3/selection/Selector.java
@@ -160,13 +160,20 @@ public abstract class Selector implements AssignmentTestable
*/
public abstract void reset();
- public AssignmentTestable.TestResult testAssignment(String keyspace, ColumnSpecification receiver)
+ public final AssignmentTestable.TestResult testAssignment(String keyspace, ColumnSpecification receiver)
{
- if (receiver.type.equals(getType()))
+ // We should ignore the fact that the output type is frozen in our comparison as functions do not support
+ // frozen types for arguments
+ AbstractType<?> receiverType = receiver.type;
+ if (getType().isFrozenCollection())
+ receiverType = receiverType.freeze();
+
+ if (receiverType.equals(getType()))
return AssignmentTestable.TestResult.EXACT_MATCH;
- else if (receiver.type.isValueCompatibleWith(getType()))
+
+ if (receiverType.isValueCompatibleWith(getType()))
return AssignmentTestable.TestResult.WEAKLY_ASSIGNABLE;
- else
- return AssignmentTestable.TestResult.NOT_ASSIGNABLE;
+
+ return AssignmentTestable.TestResult.NOT_ASSIGNABLE;
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java
index 7682184..ae793a3 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateAggregateStatement.java
@@ -83,9 +83,9 @@ public final class CreateAggregateStatement extends SchemaAlteringStatement
{
argTypes = new ArrayList<>(argRawTypes.size());
for (CQL3Type.Raw rawType : argRawTypes)
- argTypes.add(rawType.prepare(functionName.keyspace).getType());
+ argTypes.add(prepareType("arguments", rawType));
- AbstractType<?> stateType = stateTypeRaw.prepare(functionName.keyspace).getType();
+ AbstractType<?> stateType = prepareType("state type", stateTypeRaw);
Function f = Functions.find(stateFunc, stateArguments(stateType, argTypes));
if (!(f instanceof ScalarFunction))
throw new InvalidRequestException("State function " + stateFuncSig(stateFunc, stateTypeRaw, argRawTypes) + " does not exist or is not a scalar function");
@@ -117,6 +117,20 @@ public final class CreateAggregateStatement extends SchemaAlteringStatement
return super.prepare();
}
+ private AbstractType<?> prepareType(String typeName, CQL3Type.Raw rawType)
+ {
+ if (rawType.isFrozen())
+ throw new InvalidRequestException(String.format("The function %s should not be frozen; remove the frozen<> modifier", typeName));
+
+ // UDT are not supported non frozen but we do not allow the frozen keyword for argument. So for the moment we
+ // freeze them here
+ if (!rawType.canBeNonFrozen())
+ rawType.freeze();
+
+ AbstractType<?> type = rawType.prepare(functionName.keyspace).getType();
+ return type;
+ }
+
public void prepareKeyspace(ClientState state) throws InvalidRequestException
{
if (!functionName.hasKeyspace() && state.getRawKeyspace() != null)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java
index a2a440b..9e9d544 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateFunctionStatement.java
@@ -26,6 +26,7 @@ import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.cql3.ColumnIdentifier;
+import org.apache.cassandra.cql3.Operation.RawUpdate;
import org.apache.cassandra.cql3.functions.*;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.exceptions.*;
@@ -85,9 +86,9 @@ public final class CreateFunctionStatement extends SchemaAlteringStatement
argTypes = new ArrayList<>(argRawTypes.size());
for (CQL3Type.Raw rawType : argRawTypes)
- argTypes.add(rawType.prepare(functionName.keyspace).getType());
+ argTypes.add(prepareType("arguments", rawType));
- returnType = rawReturnType.prepare(functionName.keyspace).getType();
+ returnType = prepareType("return type", rawReturnType);
return super.prepare();
}
@@ -174,4 +175,18 @@ public final class CreateFunctionStatement extends SchemaAlteringStatement
return true;
}
+
+ private AbstractType<?> prepareType(String typeName, CQL3Type.Raw rawType)
+ {
+ if (rawType.isFrozen())
+ throw new InvalidRequestException(String.format("The function %s should not be frozen; remove the frozen<> modifier", typeName));
+
+ // UDT are not supported non frozen but we do not allow the frozen keyword for argument. So for the moment we
+ // freeze them here
+ if (!rawType.canBeNonFrozen())
+ rawType.freeze();
+
+ AbstractType<?> type = rawType.prepare(functionName.keyspace).getType();
+ return type;
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/statements/DropAggregateStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/DropAggregateStatement.java b/src/java/org/apache/cassandra/cql3/statements/DropAggregateStatement.java
index 97ec196..2d5ea70 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DropAggregateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DropAggregateStatement.java
@@ -96,7 +96,7 @@ public final class DropAggregateStatement extends SchemaAlteringStatement
List<AbstractType<?>> argTypes = new ArrayList<>(argRawTypes.size());
for (CQL3Type.Raw rawType : argRawTypes)
- argTypes.add(rawType.prepare(functionName.keyspace).getType());
+ argTypes.add(prepareType("arguments", rawType));
Function old;
if (argsPresent)
@@ -139,4 +139,18 @@ public final class DropAggregateStatement extends SchemaAlteringStatement
return true;
}
+
+ private AbstractType<?> prepareType(String typeName, CQL3Type.Raw rawType)
+ {
+ if (rawType.isFrozen())
+ throw new InvalidRequestException(String.format("The function %s should not be frozen; remove the frozen<> modifier", typeName));
+
+ // UDT are not supported non frozen but we do not allow the frozen keyword for argument. So for the moment we
+ // freeze them here
+ if (!rawType.canBeNonFrozen())
+ rawType.freeze();
+
+ AbstractType<?> type = rawType.prepare(functionName.keyspace).getType();
+ return type;
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/cql3/statements/DropFunctionStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/DropFunctionStatement.java b/src/java/org/apache/cassandra/cql3/statements/DropFunctionStatement.java
index 0f9e74c..edd8a65 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DropFunctionStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DropFunctionStatement.java
@@ -64,7 +64,17 @@ public final class DropFunctionStatement extends SchemaAlteringStatement
{
argTypes = new ArrayList<>(argRawTypes.size());
for (CQL3Type.Raw rawType : argRawTypes)
- argTypes.add(rawType.prepare(typeKeyspace(rawType)).getType());
+ {
+ if (rawType.isFrozen())
+ throw new InvalidRequestException("The function arguments should not be frozen; remove the frozen<> modifier");
+
+ // UDT are not supported non frozen but we do not allow the frozen keyword for argument. So for the moment we
+ // freeze them here
+ if (!rawType.canBeNonFrozen())
+ rawType.freeze();
+
+ argTypes.add(rawType.prepare(functionName.keyspace).getType());
+ }
return super.prepare();
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/src/java/org/apache/cassandra/db/marshal/AbstractType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractType.java b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
index 6f37929..6602414 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
@@ -150,6 +150,11 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
return false;
}
+ public boolean isFrozenCollection()
+ {
+ return isCollection() && !isMultiCell();
+ }
+
public static AbstractType<?> parseDefaultParameters(AbstractType<?> baseType, TypeParser parser) throws SyntaxException
{
Map<String, String> parameters = parser.getKeyValueParameters();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/test/unit/org/apache/cassandra/cql3/AggregationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/AggregationTest.java b/test/unit/org/apache/cassandra/cql3/AggregationTest.java
index f1a0b94..af775e6 100644
--- a/test/unit/org/apache/cassandra/cql3/AggregationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/AggregationTest.java
@@ -667,10 +667,10 @@ public class AggregationTest extends CQLTester
// double as finaltype
String fState = createFunction(KEYSPACE,
- "frozen<tuple<bigint, int>>, int",
- "CREATE FUNCTION %s(a frozen<tuple<bigint, int>>, b int) " +
+ "tuple<bigint, int>, int",
+ "CREATE FUNCTION %s(a tuple<bigint, int>, b int) " +
"CALLED ON NULL INPUT " +
- "RETURNS frozen<tuple<bigint, int>> " +
+ "RETURNS tuple<bigint, int> " +
"LANGUAGE java " +
"AS '" +
"a.setLong(0, a.getLong(0) + b.intValue());" +
@@ -679,8 +679,8 @@ public class AggregationTest extends CQLTester
"'");
String fFinal = createFunction(KEYSPACE,
- "frozen<tuple<bigint, int>>",
- "CREATE FUNCTION %s(a frozen<tuple<bigint, int>>) " +
+ "tuple<bigint, int>",
+ "CREATE FUNCTION %s(a tuple<bigint, int>) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java " +
@@ -694,7 +694,7 @@ public class AggregationTest extends CQLTester
"int",
"CREATE AGGREGATE %s(int) " +
"SFUNC " + shortFunctionName(fState) + " " +
- "STYPE frozen<tuple<bigint, int>> "+
+ "STYPE tuple<bigint, int> "+
"FINALFUNC " + shortFunctionName(fFinal) + " " +
"INITCOND (0, 0)");
@@ -1092,7 +1092,7 @@ public class AggregationTest extends CQLTester
KEYSPACE_PER_TEST, KEYSPACE),
"CREATE AGGREGATE " + KEYSPACE_PER_TEST + ".test_wrong_ks(int) " +
"SFUNC " + shortFunctionName(fState) + ' ' +
- "STYPE frozen<" + type + "> " +
+ "STYPE " + type + " " +
"FINALFUNC " + shortFunctionName(fFinal) + ' ' +
"INITCOND 1");
@@ -1100,7 +1100,7 @@ public class AggregationTest extends CQLTester
KEYSPACE_PER_TEST, KEYSPACE),
"CREATE AGGREGATE " + KEYSPACE_PER_TEST + ".test_wrong_ks(int) " +
"SFUNC " + fStateWrong + ' ' +
- "STYPE frozen<" + type + "> " +
+ "STYPE " + type + " " +
"FINALFUNC " + shortFunctionName(fFinal) + ' ' +
"INITCOND 1");
@@ -1108,7 +1108,7 @@ public class AggregationTest extends CQLTester
KEYSPACE_PER_TEST, KEYSPACE),
"CREATE AGGREGATE " + KEYSPACE_PER_TEST + ".test_wrong_ks(int) " +
"SFUNC " + shortFunctionName(fState) + ' ' +
- "STYPE frozen<" + type + "> " +
+ "STYPE " + type + " " +
"FINALFUNC " + fFinalWrong + ' ' +
"INITCOND 1");
}
@@ -1133,4 +1133,249 @@ public class AggregationTest extends CQLTester
"INITCOND 'foobar'");
}
+ @Test
+ public void testFunctionWithFrozenSetType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+ createIndex("CREATE INDEX ON %s (FULL(b))");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+
+ String fState = createFunction(KEYSPACE,
+ "set<int>",
+ "CREATE FUNCTION %s (state set<int>, values set<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS set<int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String fFinal = createFunction(KEYSPACE,
+ "set<int>",
+ "CREATE FUNCTION %s(state set<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS set<int> " +
+ "LANGUAGE java " +
+ "AS 'return state;'");
+
+ assertInvalidMessage("The function state type should not be frozen",
+ "CREATE AGGREGATE %s(set<int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE frozen<set<int>> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ String aggregation = createAggregate(KEYSPACE,
+ "set<int>",
+ "CREATE AGGREGATE %s(set<int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE set<int> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ assertRows(execute("SELECT " + aggregation + "(b) FROM %s"),
+ row(set(7, 8, 9)));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP AGGREGATE %s (frozen<set<int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenListType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+ createIndex("CREATE INDEX ON %s (FULL(b))");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+
+ String fState = createFunction(KEYSPACE,
+ "list<int>",
+ "CREATE FUNCTION %s (state list<int>, values list<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS list<int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String fFinal = createFunction(KEYSPACE,
+ "list<int>",
+ "CREATE FUNCTION %s(state list<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS list<int> " +
+ "LANGUAGE java " +
+ "AS 'return state;'");
+
+ assertInvalidMessage("The function state type should not be frozen",
+ "CREATE AGGREGATE %s(list<int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE frozen<list<int>> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ String aggregation = createAggregate(KEYSPACE,
+ "list<int>",
+ "CREATE AGGREGATE %s(list<int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE list<int> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ assertRows(execute("SELECT " + aggregation + "(b) FROM %s"),
+ row(list(7, 8, 9)));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP AGGREGATE %s (frozen<list<int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenMapType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+ createIndex("CREATE INDEX ON %s (FULL(b))");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 2, 3, 4));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 5, 6, 7));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 8, 9, 10));
+
+ String fState = createFunction(KEYSPACE,
+ "map<int, int>",
+ "CREATE FUNCTION %s (state map<int, int>, values map<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS map<int, int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String fFinal = createFunction(KEYSPACE,
+ "map<int, int>",
+ "CREATE FUNCTION %s(state map<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS map<int, int> " +
+ "LANGUAGE java " +
+ "AS 'return state;'");
+
+ assertInvalidMessage("The function state type should not be frozen",
+ "CREATE AGGREGATE %s(map<int, int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE frozen<map<int, int>> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ String aggregation = createAggregate(KEYSPACE,
+ "map<int, int>",
+ "CREATE AGGREGATE %s(map<int, int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE map<int, int> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ assertRows(execute("SELECT " + aggregation + "(b) FROM %s"),
+ row(map(7, 8, 9, 10)));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP AGGREGATE %s (frozen<map<int, int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenTupleType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+ createIndex("CREATE INDEX ON %s (b)");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+
+ String fState = createFunction(KEYSPACE,
+ "tuple<int, int>",
+ "CREATE FUNCTION %s (state tuple<int, int>, values tuple<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS tuple<int, int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String fFinal = createFunction(KEYSPACE,
+ "tuple<int, int>",
+ "CREATE FUNCTION %s(state tuple<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS tuple<int, int> " +
+ "LANGUAGE java " +
+ "AS 'return state;'");
+
+ assertInvalidMessage("The function state type should not be frozen",
+ "CREATE AGGREGATE %s(tuple<int, int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE frozen<tuple<int, int>> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ String aggregation = createAggregate(KEYSPACE,
+ "tuple<int, int>",
+ "CREATE AGGREGATE %s(tuple<int, int>) " +
+ "SFUNC " + fState + " " +
+ "STYPE tuple<int, int> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ assertRows(execute("SELECT " + aggregation + "(b) FROM %s"),
+ row(tuple(7, 8)));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP AGGREGATE %s (frozen<tuple<int, int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenUDFType() throws Throwable
+ {
+ String myType = createType("CREATE TYPE %s (f int)");
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+ createIndex("CREATE INDEX ON %s (b)");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 1);
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 2);
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+
+ String fState = createFunction(KEYSPACE,
+ "tuple<int, int>",
+ "CREATE FUNCTION %s (state " + myType + ", values " + myType + ") " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS " + myType + " " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String fFinal = createFunction(KEYSPACE,
+ myType,
+ "CREATE FUNCTION %s(state " + myType + ") " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS " + myType + " " +
+ "LANGUAGE java " +
+ "AS 'return state;'");
+
+ assertInvalidMessage("The function state type should not be frozen",
+ "CREATE AGGREGATE %s(" + myType + ") " +
+ "SFUNC " + fState + " " +
+ "STYPE frozen<" + myType + "> " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ String aggregation = createAggregate(KEYSPACE,
+ myType,
+ "CREATE AGGREGATE %s(" + myType + ") " +
+ "SFUNC " + fState + " " +
+ "STYPE " + myType + " " +
+ "FINALFUNC " + fFinal + " " +
+ "INITCOND null");
+
+ assertRows(execute("SELECT " + aggregation + "(b).f FROM %s"),
+ row(7));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP AGGREGATE %s (frozen<" + myType + ">);");
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java b/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
index 7cac252..703bd9a 100644
--- a/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UFIdentificationTest.java
@@ -87,7 +87,7 @@ public class UFIdentificationTest extends CQLTester
sFunc = createEchoFunction("set<int>");
mFunc = createEchoFunction("map<int, int>");
uFunc = createEchoFunction("timeuuid");
- udtFunc = createEchoFunction("frozen<" + userType + ">");
+ udtFunc = createEchoFunction(userType);
}
@Test
http://git-wip-us.apache.org/repos/asf/cassandra/blob/1de8e39e/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 79d63a9..9db5049 100644
--- a/test/unit/org/apache/cassandra/cql3/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UFTest.java
@@ -16,7 +16,6 @@
* limitations under the License.
*/
package org.apache.cassandra.cql3;
-
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
@@ -928,13 +927,13 @@ public class UFTest extends CQLTester
KEYSPACE_PER_TEST, KEYSPACE),
"CREATE FUNCTION " + KEYSPACE_PER_TEST + ".test_wrong_ks( val int ) " +
"CALLED ON NULL INPUT " +
- "RETURNS frozen<" + type + "> " +
+ "RETURNS " + type + " " +
"LANGUAGE java\n" +
"AS $$return val;$$;");
assertInvalidMessage(String.format("Statement on keyspace %s cannot refer to a user type in keyspace %s; user types can only be used in the keyspace they are defined in",
KEYSPACE_PER_TEST, KEYSPACE),
- "CREATE FUNCTION " + KEYSPACE_PER_TEST + ".test_wrong_ks( val frozen<" + type + "> ) " +
+ "CREATE FUNCTION " + KEYSPACE_PER_TEST + ".test_wrong_ks( val " + type + " ) " +
"CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java\n" +
@@ -967,16 +966,16 @@ public class UFTest extends CQLTester
"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>> ) " +
+ String fTup = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+ "CREATE FUNCTION %s( val tuple<double, text, int, boolean> ) " +
"CALLED ON NULL INPUT " +
- "RETURNS frozen<tuple<double, text, int, boolean>> " +
+ "RETURNS tuple<double, text, int, boolean> " +
"LANGUAGE java\n" +
"AS $$return val;$$;");
- String fUdt = createFunction(KEYSPACE, "frozen<" + type+'>',
- "CREATE FUNCTION %s( val frozen<" + type + "> ) " +
+ String fUdt = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( val " + type + " ) " +
"CALLED ON NULL INPUT " +
- "RETURNS frozen<" + type + "> " +
+ "RETURNS " + type + " " +
"LANGUAGE java\n" +
"AS $$return val;$$;");
List<Double> list = Arrays.asList(1d, 2d, 3d);
@@ -1055,10 +1054,10 @@ public class UFTest extends CQLTester
{
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>> ) " +
+ String fName = createFunction(KEYSPACE, "tuple<double, text, int, boolean>",
+ "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<tuple<double, text, int, boolean>> " +
+ "RETURNS tuple<double, text, int, boolean> " +
"LANGUAGE java\n" +
"AS $$return tup;$$;");
@@ -1076,9 +1075,9 @@ public class UFTest extends CQLTester
@Test
public void testJavaTupleTypeCollection() throws Throwable
{
- String tupleTypeDef = "frozen<tuple<double, list<double>, set<text>, map<int, boolean>>>";
+ String tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
- createTable("CREATE TABLE %s (key int primary key, tup " + tupleTypeDef + ')');
+ createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
String fTup0 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
"CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
@@ -1175,9 +1174,9 @@ public class UFTest extends CQLTester
executeNet(version, "USE " + KEYSPACE);
executeNet(version,
- "CREATE FUNCTION f_use1( udt frozen<" + type + "> ) " +
+ "CREATE FUNCTION f_use1( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<" + type + "> " +
+ "RETURNS " + type + " " +
"LANGUAGE java " +
"AS $$return " +
" udt;$$;");
@@ -1203,22 +1202,22 @@ public class UFTest extends CQLTester
createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- String fUdt0 = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fUdt0 = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<" + type + "> " +
+ "RETURNS " + type + " " +
"LANGUAGE java " +
"AS $$return " +
" udt;$$;");
- String fUdt1 = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fUdt1 = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + ") " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java " +
"AS $$return " +
" udt.getString(\"txt\");$$;");
- String fUdt2 = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fUdt2 = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + ") " +
"CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java " +
@@ -1257,8 +1256,8 @@ public class UFTest extends CQLTester
createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- String fName = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java " +
@@ -1294,8 +1293,8 @@ public class UFTest extends CQLTester
createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- String fName = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java\n" +
@@ -1324,53 +1323,53 @@ public class UFTest extends CQLTester
createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- String fName1replace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName1replace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + ") " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java\n" +
"AS $$return udt.getString(\"txt\");$$;");
- String fName2replace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName2replace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java\n" +
"AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
- String fName3replace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName3replace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java\n" +
"AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
- String fName4replace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName4replace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<" + type + "> " +
+ "RETURNS " + type + " " +
"LANGUAGE java\n" +
"AS $$return udt;$$;");
- String fName1noReplace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName1noReplace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java\n" +
"AS $$return udt.getString(\"txt\");$$;");
- String fName2noReplace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName2noReplace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java\n" +
"AS $$return Integer.valueOf(udt.getInt(\"i\"));$$;");
- String fName3noReplace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName3noReplace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java\n" +
"AS $$return Double.valueOf(udt.getDouble(\"added\"));$$;");
- String fName4noReplace = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fName4noReplace = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<" + type + "> " +
+ "RETURNS " + type + " " +
"LANGUAGE java\n" +
"AS $$return udt;$$;");
@@ -1390,7 +1389,7 @@ public class UFTest extends CQLTester
// 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> ) " +
+ execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java\n" +
@@ -1398,7 +1397,7 @@ public class UFTest extends CQLTester
" udt.getString(\"txt\");$$;",
fName1replace, type));
Assert.assertEquals(1, Functions.find(parseFunctionName(fName1replace)).size());
- execute(String.format("CREATE OR REPLACE FUNCTION %s( udt frozen<%s> ) " +
+ execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
"CALLED ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE java\n" +
@@ -1406,7 +1405,7 @@ public class UFTest extends CQLTester
" 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> ) " +
+ execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
"CALLED ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE java\n" +
@@ -1414,9 +1413,9 @@ public class UFTest extends CQLTester
" 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> ) " +
+ execute(String.format("CREATE OR REPLACE FUNCTION %s( udt %s ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<%s> " +
+ "RETURNS %s " +
"LANGUAGE java\n" +
"AS $$return " +
" udt;$$;",
@@ -1552,10 +1551,10 @@ public class UFTest extends CQLTester
{
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>> ) " +
+ String fName = createFunction(KEYSPACE_PER_TEST, "tuple<double, text, int, boolean>",
+ "CREATE FUNCTION %s( tup tuple<double, text, int, boolean> ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<tuple<double, text, int, boolean>> " +
+ "RETURNS tuple<double, text, int, boolean> " +
"LANGUAGE javascript\n" +
"AS $$tup;$$;");
@@ -1573,13 +1572,13 @@ public class UFTest extends CQLTester
@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 tupleTypeDef = "tuple<double, list<double>, set<text>, map<int, boolean>>";
+ createTable("CREATE TABLE %s (key int primary key, tup frozen<" + tupleTypeDef + ">)");
String fTup1 = createFunction(KEYSPACE_PER_TEST, tupleTypeDef,
"CREATE FUNCTION %s( tup " + tupleTypeDef + " ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<tuple<double, list<double>, set<text>, map<int, boolean>>> " +
+ "RETURNS tuple<double, list<double>, set<text>, map<int, boolean>> " +
"LANGUAGE javascript\n" +
"AS $$" +
" tup;$$;");
@@ -1667,22 +1666,22 @@ public class UFTest extends CQLTester
createTable("CREATE TABLE %s (key int primary key, udt frozen<" + type + ">)");
- String fUdt1 = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fUdt1 = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
- "RETURNS frozen<" + type + "> " +
+ "RETURNS " + type + " " +
"LANGUAGE javascript\n" +
"AS $$" +
" udt;$$;");
- String fUdt2 = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fUdt2 = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE javascript\n" +
"AS $$" +
" udt.getString(\"txt\");$$;");
- String fUdt3 = createFunction(KEYSPACE, "frozen<" + type + '>',
- "CREATE FUNCTION %s( udt frozen<" + type + "> ) " +
+ String fUdt3 = createFunction(KEYSPACE, type,
+ "CREATE FUNCTION %s( udt " + type + " ) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS int " +
"LANGUAGE javascript\n" +
@@ -1977,15 +1976,15 @@ public class UFTest extends CQLTester
"LANGUAGE java\n" +
"AS 'return \"foo bar\";';");
String fU = createFunction(KEYSPACE,
- "frozen<" + type + '>',
- "CREATE OR REPLACE FUNCTION %s(val frozen<" + type + ">) " +
+ type,
+ "CREATE OR REPLACE FUNCTION %s(val " + 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>>) " +
+ "tuple<int, text>",
+ "CREATE OR REPLACE FUNCTION %s(val tuple<int, text>) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java\n" +
@@ -2093,15 +2092,15 @@ public class UFTest extends CQLTester
"LANGUAGE java\n" +
"AS 'return \"foo bar\";';");
String fU = createFunction(KEYSPACE,
- "frozen<" + type + '>',
- "CREATE OR REPLACE FUNCTION %s(val frozen<" + type + ">) " +
+ type,
+ "CREATE OR REPLACE FUNCTION %s(val " + 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>>) " +
+ "tuple<int, text>",
+ "CREATE OR REPLACE FUNCTION %s(val tuple<int, text>) " +
"CALLED ON NULL INPUT " +
"RETURNS text " +
"LANGUAGE java\n" +
@@ -2160,4 +2159,275 @@ public class UFTest extends CQLTester
executeNet(version, "SELECT " + fName + "(dval) FROM %s WHERE key = 1"));
}
}
+
+ @Test
+ public void testFunctionWithFrozenSetType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<set<int>>)");
+ createIndex("CREATE INDEX ON %s (FULL(b))");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, set());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, set(1, 2, 3));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, set(4, 5, 6));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, set(7, 8, 9));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenSetArg(values frozen<set<int>>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS int " +
+ "LANGUAGE java\n" +
+ "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+ assertInvalidMessage("The function return type should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values set<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS frozen<set<int>> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String functionName = createFunction(KEYSPACE,
+ "set<int>",
+ "CREATE FUNCTION %s (values set<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS int " +
+ "LANGUAGE java\n" +
+ "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+ assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+ row(0, 0),
+ row(1, 6),
+ row(2, 15),
+ row(3, 24));
+
+ functionName = createFunction(KEYSPACE,
+ "set<int>",
+ "CREATE FUNCTION %s (values set<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS set<int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+ row(1));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP FUNCTION " + functionName + "(frozen<set<int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenListType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<list<int>>)");
+ createIndex("CREATE INDEX ON %s (FULL(b))");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, list());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, list(1, 2, 3));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, list(4, 5, 6));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, list(7, 8, 9));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<list<int>>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS int " +
+ "LANGUAGE java\n" +
+ "AS 'int sum = 0; for (Object value : values) {sum += value;} return sum;';");
+
+ assertInvalidMessage("The function return type should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values list<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS frozen<list<int>> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String functionName = createFunction(KEYSPACE,
+ "list<int>",
+ "CREATE FUNCTION %s (values list<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS int " +
+ "LANGUAGE java\n" +
+ "AS 'int sum = 0; for (Object value : values) {sum += ((Integer) value);} return sum;';");
+
+ assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+ row(0, 0),
+ row(1, 6),
+ row(2, 15),
+ row(3, 24));
+
+ functionName = createFunction(KEYSPACE,
+ "list<int>",
+ "CREATE FUNCTION %s (values list<int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS list<int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", set(1, 2, 3)),
+ row(1));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP FUNCTION " + functionName + "(frozen<list<int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenMapType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<map<int, int>>)");
+ createIndex("CREATE INDEX ON %s (FULL(b))");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, map());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, map(1, 1, 2, 2, 3, 3));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, map(4, 4, 5, 5, 6, 6));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, map(7, 7, 8, 8, 9, 9));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<map<int, int>>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS int " +
+ "LANGUAGE java\n" +
+ "AS 'int sum = 0; for (Object value : values.values()) {sum += value;} return sum;';");
+
+ assertInvalidMessage("The function return type should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values map<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS frozen<map<int, int>> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String functionName = createFunction(KEYSPACE,
+ "map<int, int>",
+ "CREATE FUNCTION %s (values map<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS int " +
+ "LANGUAGE java\n" +
+ "AS 'int sum = 0; for (Object value : values.values()) {sum += ((Integer) value);} return sum;';");
+
+ assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+ row(0, 0),
+ row(1, 6),
+ row(2, 15),
+ row(3, 24));
+
+ functionName = createFunction(KEYSPACE,
+ "map<int, int>",
+ "CREATE FUNCTION %s (values map<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS map<int, int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", map(1, 1, 2, 2, 3, 3)),
+ row(1));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP FUNCTION " + functionName + "(frozen<map<int, int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenTupleType() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<tuple<int, int>>)");
+ createIndex("CREATE INDEX ON %s (b)");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 0, tuple());
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 1, tuple(1, 2));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 2, tuple(4, 5));
+ execute("INSERT INTO %s (a, b) VALUES (?, ?)", 3, tuple(7, 8));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<tuple<int, int>>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return values.toString();';");
+
+ assertInvalidMessage("The function return type should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values tuple<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS frozen<tuple<int, int>> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String functionName = createFunction(KEYSPACE,
+ "tuple<int, int>",
+ "CREATE FUNCTION %s (values tuple<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return values.toString();';");
+
+ assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+ row(0, "(null, null)"),
+ row(1, "(1, 2)"),
+ row(2, "(4, 5)"),
+ row(3, "(7, 8)"));
+
+ functionName = createFunction(KEYSPACE,
+ "tuple<int, int>",
+ "CREATE FUNCTION %s (values tuple<int, int>) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS tuple<int, int> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "(?)", tuple(1, 2)),
+ row(1));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP FUNCTION " + functionName + "(frozen<tuple<int, int>>);");
+ }
+
+ @Test
+ public void testFunctionWithFrozenUDType() throws Throwable
+ {
+ String myType = createType("CREATE TYPE %s (f int)");
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType + ">)");
+ createIndex("CREATE INDEX ON %s (b)");
+
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 0, 0);
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 1, 1);
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 2, 4);
+ execute("INSERT INTO %s (a, b) VALUES (?, {f : ?})", 3, 7);
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".withFrozenArg(values frozen<" + myType + ">) " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return values.toString();';");
+
+ assertInvalidMessage("The function return type should not be frozen",
+ "CREATE OR REPLACE FUNCTION " + KEYSPACE + ".frozenReturnType(values " + myType + ") " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS frozen<" + myType + "> " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ String functionName = createFunction(KEYSPACE,
+ myType,
+ "CREATE FUNCTION %s (values " + myType + ") " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS text " +
+ "LANGUAGE java\n" +
+ "AS 'return values.toString();';");
+
+ assertRows(execute("SELECT a, " + functionName + "(b) FROM %s"),
+ row(0, "{f:0}"),
+ row(1, "{f:1}"),
+ row(2, "{f:4}"),
+ row(3, "{f:7}"));
+
+ functionName = createFunction(KEYSPACE,
+ myType,
+ "CREATE FUNCTION %s (values " + myType + ") " +
+ "CALLED ON NULL INPUT " +
+ "RETURNS " + myType + " " +
+ "LANGUAGE java\n" +
+ "AS 'return values;';");
+
+ assertRows(execute("SELECT a FROM %s WHERE b = " + functionName + "({f: ?})", 1),
+ row(1));
+
+ assertInvalidMessage("The function arguments should not be frozen",
+ "DROP FUNCTION " + functionName + "(frozen<" + myType + ">);");
+ }
}