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 + ">);");
+    }
 }