diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 13608041..5d58723b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,6 +11,10 @@ Features * Detect triggers and include them in CQL queries generated to recreate the schema (github-189) +Other +----- +* Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857 + 2.1.0 ===== August 7, 2014 diff --git a/cassandra/cqltypes.py b/cassandra/cqltypes.py index 4b7022d6..05d86744 100644 --- a/cassandra/cqltypes.py +++ b/cassandra/cqltypes.py @@ -824,6 +824,11 @@ class TupleType(_ParameterizedType): buf.write(int32_pack(-1)) return buf.getvalue() + @classmethod + def cql_parameterized_type(cls): + subtypes_string = ', '.join(sub.cql_parameterized_type() for sub in cls.subtypes) + return 'frozen>' % (subtypes_string,) + class UserType(TupleType): typename = "'org.apache.cassandra.db.marshal.UserType'" @@ -863,7 +868,7 @@ class UserType(TupleType): @classmethod def cql_parameterized_type(cls): - return cls.typename + return "frozen<%s>" % (cls.typename,) @classmethod def deserialize_safe(cls, byts, protocol_version): diff --git a/tests/integration/standard/test_metadata.py b/tests/integration/standard/test_metadata.py index eb729a59..72bb8477 100644 --- a/tests/integration/standard/test_metadata.py +++ b/tests/integration/standard/test_metadata.py @@ -355,13 +355,13 @@ class TestCodeCoverage(unittest.TestCase): """) session.execute(""" CREATE TYPE export_udts.address ( - street_address street, - zip_code zip) + street_address frozen, + zip_code frozen) """) session.execute(""" CREATE TABLE export_udts.users ( user text PRIMARY KEY, - addresses map) + addresses map>) """) expected_string = """CREATE KEYSPACE export_udts WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} AND durable_writes = true; @@ -377,13 +377,13 @@ CREATE TYPE export_udts.zip ( ); CREATE TYPE export_udts.address ( - street_address street, - zip_code zip + street_address frozen, + zip_code frozen ); CREATE TABLE export_udts.users ( user text PRIMARY KEY, - addresses map + addresses map> ) WITH bloom_filter_fp_chance = 0.01 AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}' AND comment = '' @@ -404,7 +404,7 @@ CREATE TABLE export_udts.users ( expected_string = """CREATE TABLE export_udts.users ( user text PRIMARY KEY, - addresses map + addresses map> ) WITH bloom_filter_fp_chance = 0.01 AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}' AND comment = '' diff --git a/tests/integration/standard/test_udts.py b/tests/integration/standard/test_udts.py index 29c44536..ae5ce5ed 100644 --- a/tests/integration/standard/test_udts.py +++ b/tests/integration/standard/test_udts.py @@ -48,7 +48,7 @@ class TypeTests(unittest.TestCase): """) s.set_keyspace("udt_test_unprepared_registered") s.execute("CREATE TYPE user (age int, name text)") - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") User = namedtuple('user', ('age', 'name')) c.register_user_type("udt_test_unprepared_registered", "user", User) @@ -68,7 +68,7 @@ class TypeTests(unittest.TestCase): """) s.set_keyspace("udt_test_unprepared_registered2") s.execute("CREATE TYPE user (state text, is_cool boolean)") - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") User = namedtuple('user', ('state', 'is_cool')) c.register_user_type("udt_test_unprepared_registered2", "user", User) @@ -96,7 +96,7 @@ class TypeTests(unittest.TestCase): """) s.set_keyspace("udt_test_register_before_connecting") s.execute("CREATE TYPE user (age int, name text)") - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") s.execute(""" CREATE KEYSPACE udt_test_register_before_connecting2 @@ -104,7 +104,7 @@ class TypeTests(unittest.TestCase): """) s.set_keyspace("udt_test_register_before_connecting2") s.execute("CREATE TYPE user (state text, is_cool boolean)") - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") # now that types are defined, shutdown and re-create Cluster c.shutdown() @@ -145,7 +145,7 @@ class TypeTests(unittest.TestCase): """) s.set_keyspace("udt_test_prepared_unregistered") s.execute("CREATE TYPE user (age int, name text)") - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") User = namedtuple('user', ('age', 'name')) insert = s.prepare("INSERT INTO mytable (a, b) VALUES (?, ?)") @@ -165,7 +165,7 @@ class TypeTests(unittest.TestCase): """) s.set_keyspace("udt_test_prepared_unregistered2") s.execute("CREATE TYPE user (state text, is_cool boolean)") - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") User = namedtuple('user', ('state', 'is_cool')) insert = s.prepare("INSERT INTO mytable (a, b) VALUES (?, ?)") @@ -193,7 +193,7 @@ class TypeTests(unittest.TestCase): User = namedtuple('user', ('age', 'name')) c.register_user_type("udt_test_prepared_registered", "user", User) - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") insert = s.prepare("INSERT INTO mytable (a, b) VALUES (?, ?)") s.execute(insert, (0, User(42, 'bob'))) @@ -216,7 +216,7 @@ class TypeTests(unittest.TestCase): User = namedtuple('user', ('state', 'is_cool')) c.register_user_type("udt_test_prepared_registered2", "user", User) - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") insert = s.prepare("INSERT INTO mytable (a, b) VALUES (?, ?)") s.execute(insert, (0, User('Texas', True))) @@ -247,7 +247,7 @@ class TypeTests(unittest.TestCase): User = namedtuple('user', ('a', 'b', 'c', 'd')) c.register_user_type("test_udts_with_nulls", "user", User) - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b user)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") insert = s.prepare("INSERT INTO mytable (a, b) VALUES (0, ?)") s.execute(insert, [User(None, None, None, None)]) @@ -293,7 +293,7 @@ class TypeTests(unittest.TestCase): # no need for all nested types, only a spot checked few and the largest one s.execute("CREATE TABLE mytable (" "k int PRIMARY KEY, " - "v lengthy_udt)") + "v frozen)") # create and register the seed udt type udt = namedtuple('lengthy_udt', tuple(['v_{}'.format(i) for i in range(MAX_TEST_LENGTH)])) @@ -347,17 +347,17 @@ class TypeTests(unittest.TestCase): # create the nested udts for i in range(MAX_NESTING_DEPTH): - s.execute("CREATE TYPE depth_{} (value depth_{})".format(i + 1, i)) + s.execute("CREATE TYPE depth_{} (value frozen)".format(i + 1, i)) # create a table with multiple sizes of nested udts # no need for all nested types, only a spot checked few and the largest one s.execute("CREATE TABLE mytable (" "k int PRIMARY KEY, " - "v_0 depth_0, " - "v_1 depth_1, " - "v_2 depth_2, " - "v_3 depth_3, " - "v_{0} depth_{0})".format(MAX_NESTING_DEPTH)) + "v_0 frozen, " + "v_1 frozen, " + "v_2 frozen, " + "v_3 frozen, " + "v_{0} frozen)".format(MAX_NESTING_DEPTH)) # create the udt container udts = [] @@ -409,17 +409,17 @@ class TypeTests(unittest.TestCase): # create the nested udts for i in range(MAX_NESTING_DEPTH): - s.execute("CREATE TYPE depth_{} (value depth_{})".format(i + 1, i)) + s.execute("CREATE TYPE depth_{} (value frozen)".format(i + 1, i)) # create a table with multiple sizes of nested udts # no need for all nested types, only a spot checked few and the largest one s.execute("CREATE TABLE mytable (" "k int PRIMARY KEY, " - "v_0 depth_0, " - "v_1 depth_1, " - "v_2 depth_2, " - "v_3 depth_3, " - "v_{0} depth_{0})".format(MAX_NESTING_DEPTH)) + "v_0 frozen, " + "v_1 frozen, " + "v_2 frozen, " + "v_3 frozen, " + "v_{0} frozen)".format(MAX_NESTING_DEPTH)) # create the udt container udts = [] @@ -475,17 +475,17 @@ class TypeTests(unittest.TestCase): # create the nested udts for i in range(MAX_NESTING_DEPTH): - s.execute("CREATE TYPE depth_{} (value depth_{})".format(i + 1, i)) + s.execute("CREATE TYPE depth_{} (value frozen)".format(i + 1, i)) # create a table with multiple sizes of nested udts # no need for all nested types, only a spot checked few and the largest one s.execute("CREATE TABLE mytable (" "k int PRIMARY KEY, " - "v_0 depth_0, " - "v_1 depth_1, " - "v_2 depth_2, " - "v_3 depth_3, " - "v_{0} depth_{0})".format(MAX_NESTING_DEPTH)) + "v_0 frozen, " + "v_1 frozen, " + "v_2 frozen, " + "v_3 frozen, " + "v_{0} frozen)".format(MAX_NESTING_DEPTH)) # create the udt container udts = [] @@ -545,7 +545,7 @@ class TypeTests(unittest.TestCase): """.format(', '.join(alpha_type_list)) ) - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b alldatatypes)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") # register UDT alphabet_list = [] @@ -576,6 +576,7 @@ class TypeTests(unittest.TestCase): """ Test for inserting various types of DATA_TYPE_NON_PRIMITIVE into UDT's """ + raise unittest.SkipTest("Collections are not allowed in UDTs") c = Cluster(protocol_version=PROTOCOL_VERSION) s = c.connect() @@ -604,7 +605,7 @@ class TypeTests(unittest.TestCase): """.format(', '.join(alpha_type_list)) ) - s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b alldatatypes)") + s.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen)") # register UDT alphabet_list = [] diff --git a/tests/unit/test_metadata.py b/tests/unit/test_metadata.py index 95c8841e..6c35a620 100644 --- a/tests/unit/test_metadata.py +++ b/tests/unit/test_metadata.py @@ -302,12 +302,12 @@ class TestUserTypes(unittest.TestCase): def test_as_cql_query(self): field_types = [IntegerType, AsciiType, TupleType.apply_parameters([IntegerType, AsciiType])] udt = UserType("ks1", "mytype", ["a", "b", "c"], field_types) - self.assertEqual("CREATE TYPE ks1.mytype (a varint, b ascii, c tuple);", udt.as_cql_query(formatted=False)) + self.assertEqual("CREATE TYPE ks1.mytype (a varint, b ascii, c frozen>);", udt.as_cql_query(formatted=False)) self.assertEqual("""CREATE TYPE ks1.mytype ( a varint, b ascii, - c tuple + c frozen> );""", udt.as_cql_query(formatted=True)) def test_as_cql_query_name_escaping(self):