You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by br...@apache.org on 2014/09/02 19:48:57 UTC

[2/8] git commit: Ability to freeze UDT

Ability to freeze UDT

patch by slebresne; reviewed by iamaleksey for CASSANDRA-7857


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/02be0ded
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/02be0ded
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/02be0ded

Branch: refs/heads/trunk
Commit: 02be0dedd9773f1f2f7ce19dfeca82eed5456ca1
Parents: 92a254a
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Tue Sep 2 10:41:48 2014 +0200
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Tue Sep 2 10:41:48 2014 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../org/apache/cassandra/cql3/CQL3Type.java     | 44 ++++++++++++++++++++
 src/java/org/apache/cassandra/cql3/Cql.g        |  9 ++++
 .../org/apache/cassandra/cql3/CQLTester.java    |  5 +--
 .../apache/cassandra/cql3/TupleTypeTest.java    | 16 ++++---
 .../apache/cassandra/cql3/UserTypesTest.java    | 15 ++++---
 6 files changed, 76 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/02be0ded/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 477a332..b33bec4 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.1.0-rc7
+ * Add frozen keyword and require UDT to be frozen (CASSANDRA-7857)
  * Track added sstable size correctly (CASSANDRA-7239)
  * (cqlsh) Fix case insensitivity (CASSANDRA-7834)
  * Fix failure to stream ranges when moving (CASSANDRA-7836)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02be0ded/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 a26a903..1589d6a 100644
--- a/src/java/org/apache/cassandra/cql3/CQL3Type.java
+++ b/src/java/org/apache/cassandra/cql3/CQL3Type.java
@@ -284,6 +284,8 @@ public interface CQL3Type
     // actual type used, so Raw is a "not yet prepared" CQL3Type.
     public abstract class Raw
     {
+        protected boolean frozen;
+
         public boolean isCollection()
         {
             return false;
@@ -294,6 +296,12 @@ public interface CQL3Type
             return false;
         }
 
+        public Raw freeze()
+        {
+            frozen = true;
+            return this;
+        }
+
         public abstract CQL3Type prepare(String keyspace) throws InvalidRequestException;
 
         public static Raw from(CQL3Type type)
@@ -345,6 +353,16 @@ public interface CQL3Type
             return new RawTuple(ts);
         }
 
+        public static Raw frozen(CQL3Type.Raw t) throws InvalidRequestException
+        {
+            if (t instanceof RawUT)
+                return ((RawUT)t).freeze();
+            if (t instanceof RawTuple)
+                return ((RawTuple)t).freeze();
+
+            throw new InvalidRequestException("frozen<> is only currently only allowed on User-Defined and tuple types");
+        }
+
         private static class RawType extends Raw
         {
             private CQL3Type type;
@@ -384,6 +402,13 @@ public interface CQL3Type
                 this.values = values;
             }
 
+            public Raw freeze()
+            {
+                keys.freeze();
+                values.freeze();
+                return super.freeze();
+            }
+
             public boolean isCollection()
             {
                 return true;
@@ -445,9 +470,17 @@ public interface CQL3Type
                 if (type == null)
                     throw new InvalidRequestException("Unknown type " + name);
 
+                if (!frozen)
+                    throw new InvalidRequestException("Non-frozen User-Defined types are not supported, please use frozen<>");
+
                 return new UserDefined(name.toString(), type);
             }
 
+            public boolean isUDT()
+            {
+                return true;
+            }
+
             @Override
             public String toString()
             {
@@ -464,6 +497,13 @@ public interface CQL3Type
                 this.types = types;
             }
 
+            public Raw freeze()
+            {
+                for (CQL3Type.Raw t : types)
+                    t.freeze();
+                return super.freeze();
+            }
+
             public boolean isCollection()
             {
                 return false;
@@ -474,6 +514,10 @@ public interface CQL3Type
                 List<AbstractType<?>> ts = new ArrayList<>(types.size());
                 for (CQL3Type.Raw t : types)
                     ts.add(t.prepare(keyspace).getType());
+
+                if (!frozen)
+                    throw new InvalidRequestException("Non-frozen tuples are not supported, please use frozen<>");
+
                 return new Tuple(new TupleType(ts));
             }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02be0ded/src/java/org/apache/cassandra/cql3/Cql.g
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g
index 1ff6ab2..6247a03 100644
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@ -1071,6 +1071,14 @@ comparatorType returns [CQL3Type.Raw t]
     | c=collection_type { $t = c; }
     | tt=tuple_type     { $t = tt; }
     | id=userTypeName   { $t = CQL3Type.Raw.userType(id); }
+    | K_FROZEN '<' f=comparatorType '>'
+      {
+        try {
+            $t = CQL3Type.Raw.frozen(f);
+        } catch (InvalidRequestException e) {
+            addRecognitionError(e.getMessage());
+        }
+      }
     | s=STRING_LITERAL
       {
         try {
@@ -1277,6 +1285,7 @@ K_TUPLE:       T U P L E;
 
 K_TRIGGER:     T R I G G E R;
 K_STATIC:      S T A T I C;
+K_FROZEN:      F R O Z E N;
 
 // Case-insensitive alpha characters
 fragment A: ('a'|'A');

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02be0ded/test/unit/org/apache/cassandra/cql3/CQLTester.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java
index c412fe3..d56b5df 100644
--- a/test/unit/org/apache/cassandra/cql3/CQLTester.java
+++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java
@@ -204,12 +204,9 @@ public abstract class CQLTester
 
     protected UntypedResultSet execute(String query, Object... values) throws Throwable
     {
-        if (currentTable == null)
-            throw new RuntimeException("You must create a table first with createTable");
-
         try
         {
-            query = String.format(query, KEYSPACE + "." + currentTable);
+            query = currentTable == null ? query : String.format(query, KEYSPACE + "." + currentTable);
 
             UntypedResultSet rs;
             if (USE_PREPARED_VALUES)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02be0ded/test/unit/org/apache/cassandra/cql3/TupleTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/TupleTypeTest.java b/test/unit/org/apache/cassandra/cql3/TupleTypeTest.java
index 84512a5..4ce24f8 100644
--- a/test/unit/org/apache/cassandra/cql3/TupleTypeTest.java
+++ b/test/unit/org/apache/cassandra/cql3/TupleTypeTest.java
@@ -24,7 +24,7 @@ public class TupleTypeTest extends CQLTester
     @Test
     public void testTuplePutAndGet() throws Throwable
     {
-        createTable("CREATE TABLE %s (k int PRIMARY KEY, t tuple<int, text, double>)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, t frozen<tuple<int, text, double>>)");
 
         execute("INSERT INTO %s (k, t) VALUES (?, ?)", 0, tuple(3, "foo", 3.4));
         execute("INSERT INTO %s (k, t) VALUES (?, ?)", 1, tuple(8, "bar", 0.2));
@@ -49,7 +49,7 @@ public class TupleTypeTest extends CQLTester
     @Test
     public void testNestedTuple() throws Throwable
     {
-        createTable("CREATE TABLE %s (k int PRIMARY KEY, t tuple<int, tuple<text, double>>)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, t frozen<tuple<int, tuple<text, double>>>)");
 
         execute("INSERT INTO %s (k, t) VALUES (?, ?)", 0, tuple(3, tuple("foo", 3.4)));
         execute("INSERT INTO %s (k, t) VALUES (?, ?)", 1, tuple(8, tuple("bar", 0.2)));
@@ -62,7 +62,7 @@ public class TupleTypeTest extends CQLTester
     @Test
     public void testTupleInPartitionKey() throws Throwable
     {
-        createTable("CREATE TABLE %s (t tuple<int, text> PRIMARY KEY)");
+        createTable("CREATE TABLE %s (t frozen<tuple<int, text>> PRIMARY KEY)");
 
         execute("INSERT INTO %s (t) VALUES (?)", tuple(3, "foo"));
         assertAllRows(row(tuple(3, "foo")));
@@ -71,7 +71,7 @@ public class TupleTypeTest extends CQLTester
     @Test
     public void testTupleInClusteringKey() throws Throwable
     {
-        createTable("CREATE TABLE %s (k int, t tuple<int, text>, PRIMARY KEY (k, t))");
+        createTable("CREATE TABLE %s (k int, t frozen<tuple<int, text>>, PRIMARY KEY (k, t))");
 
         execute("INSERT INTO %s (k, t) VALUES (?, ?)", 0, tuple(5, "bar"));
         execute("INSERT INTO %s (k, t) VALUES (?, ?)", 0, tuple(3, "foo"));
@@ -89,9 +89,15 @@ public class TupleTypeTest extends CQLTester
     @Test
     public void testInvalidQueries() throws Throwable
     {
-        createTable("CREATE TABLE %s (k int PRIMARY KEY, t tuple<int, text, double>)");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, t frozen<tuple<int, text, double>>)");
 
         assertInvalid("INSERT INTO %s (k, t) VALUES (0, ())");
         assertInvalid("INSERT INTO %s (k, t) VALUES (0, (2, 'foo', 3.1, 'bar'))");
     }
+
+    @Test
+    public void testNonFrozenTuple() throws Throwable
+    {
+        assertInvalid("CREATE TABLE wrong (k int PRIMARY KEY, v tuple<int, text>)");
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02be0ded/test/unit/org/apache/cassandra/cql3/UserTypesTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/UserTypesTest.java b/test/unit/org/apache/cassandra/cql3/UserTypesTest.java
index c7f1851..ca84102 100644
--- a/test/unit/org/apache/cassandra/cql3/UserTypesTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UserTypesTest.java
@@ -25,32 +25,37 @@ public class UserTypesTest extends CQLTester
     public void testInvalidField() throws Throwable
     {
         String myType = createType("CREATE TYPE %s (f int)");
-        createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + myType + ")");
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, v frozen<" + myType + ">)");
 
         // 's' is not a field of myType
         assertInvalid("INSERT INTO %s (k, v) VALUES (?, {s : ?})", 0, 1);
     }
 
-
     @Test
     public void testFor7684() throws Throwable
     {
         String myType = createType("CREATE TYPE %s (x double)");
-        createTable("CREATE TABLE %s (k int, v " + myType + ", b boolean static, PRIMARY KEY (k, v))");
+        createTable("CREATE TABLE %s (k int, v frozen<" + myType + ">, b boolean static, PRIMARY KEY (k, v))");
 
         execute("INSERT INTO %s(k, v) VALUES (?, {x:?})", 1, -104.99251);
         execute("UPDATE %s SET b = ? WHERE k = ?", true, 1);
 
-        System.out.println("-- First query");
         assertRows(execute("SELECT v.x FROM %s WHERE k = ? AND v = {x:?}", 1, -104.99251),
             row(-104.99251)
         );
 
         flush();
 
-        System.out.println("-- 2nd query");
         assertRows(execute("SELECT v.x FROM %s WHERE k = ? AND v = {x:?}", 1, -104.99251),
             row(-104.99251)
         );
     }
+
+    @Test
+    public void testNonFrozenUDT() throws Throwable
+    {
+        // Using a UDT without frozen shouldn't work
+        String myType = createType("CREATE TYPE %s (f int)");
+        assertInvalid("CREATE TABLE wrong (k int PRIMARY KEY, v " + myType + ")");
+    }
 }