Repository: cassandra Updated Branches: refs/heads/cassandra-2.1 ea02b6900 -> 3391b99a0 refs/heads/trunk 76bd6bb8c -> b25cac40e
cqlsh: Handle collections embedded into UDTs correctly. patch by Mikhail Stepura; reviewed by Tyler Hobbs for CASSANDRA-7267 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3391b99a Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3391b99a Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3391b99a Branch: refs/heads/cassandra-2.1 Commit: 3391b99a0bd38882dbee2261ddcdca77cc634722 Parents: ea02b69 Author: Mikhail Stepura <[email protected]> Authored: Tue May 27 20:05:34 2014 -0700 Committer: Mikhail Stepura <[email protected]> Committed: Wed May 28 15:14:25 2014 -0700 ---------------------------------------------------------------------- CHANGES.txt | 1 + bin/cqlsh | 5 +++ pylib/cqlshlib/test/test_cqlsh_output.py | 30 ++++++++++++++ pylib/cqlshlib/test/test_keyspace_init.cql | 40 ++++++++++++++++++ pylib/cqlshlib/usertypes.py | 55 ++++++++++++++++++++++++- 5 files changed, 130 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/3391b99a/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index f62d5b0..fe8242b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -28,6 +28,7 @@ * Backport Thrift MultiSliceRequest (CASSANDRA-7027) * Handle overlapping MultiSlices (CASSANDRA-7279) * Fix DataOutputTest on Windows (CASSANDRA-7265) + * Embedded sets in user defined data-types are not updating (CASSANDRA-7267) Merged from 2.0: * Copy compaction options to make sure they are reloaded (CASSANDRA-7290) * Add option to do more aggressive tombstone compactions (CASSANDRA-6563) http://git-wip-us.apache.org/repos/asf/cassandra/blob/3391b99a/bin/cqlsh ---------------------------------------------------------------------- diff --git a/bin/cqlsh b/bin/cqlsh index 1397f85..914d175 100755 --- a/bin/cqlsh +++ b/bin/cqlsh @@ -119,6 +119,7 @@ from cqlshlib.displaying import (RED, BLUE, ANSI_RESET, COLUMN_NAME_COLORS, from cqlshlib.formatting import format_by_type from cqlshlib.util import trim_if_present from cqlshlib.tracing import print_trace_session +from cqlshlib.usertypes import deserialize_safe_collection, deserialize_safe_map HISTORY_DIR = os.path.expanduser(os.path.join('~', '.cassandra')) CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc') @@ -521,6 +522,10 @@ class Shell(cmd.Cmd): #Python driver returns BLOBs as string, but we expect them as buffer() cassandra.cqltypes.BytesType.deserialize = staticmethod(cassandra.cqltypes.BytesType.validate) cassandra.cqltypes.CassandraType.support_empty_values = True + # see CASSANDRA-7267 + cassandra.cqltypes._SimpleParameterizedType.deserialize_safe = classmethod(deserialize_safe_collection) + # see CASSANDRA-7267 + cassandra.cqltypes.MapType.deserialize_safe = classmethod(deserialize_safe_map) self.empty_lines = 0 self.statement_error = False self.single_statement = single_statement http://git-wip-us.apache.org/repos/asf/cassandra/blob/3391b99a/pylib/cqlshlib/test/test_cqlsh_output.py ---------------------------------------------------------------------- diff --git a/pylib/cqlshlib/test/test_cqlsh_output.py b/pylib/cqlshlib/test/test_cqlsh_output.py index d91b4f3..6689e4b 100644 --- a/pylib/cqlshlib/test/test_cqlsh_output.py +++ b/pylib/cqlshlib/test/test_cqlsh_output.py @@ -854,4 +854,34 @@ class TestCqlshOutput(BaseTestCase): (2 rows) nnnnnnnn """), + ), cqlver=cqlsh.DEFAULT_CQLVER) + + def test_user_types_with_collections(self): + self.assertCqlverQueriesGiveColoredOutput(( + ("select info from songs;", r""" + info + MMMM + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + + {founded: '1970-01-02 20:24:54-0800', members: {'Adrian Smith', 'Bruce Dickinson', 'Dave Murray', 'Janick Gers', 'Nicko McBrain', 'Steve Harris'}, description: 'Pure evil metal'} + BYYYYYYYBBGGGGGGGGGGGGGGGGGGGGGGGGGGBBYYYYYYYBBBYYYYYYYYYYYYYYBBYYYYYYYYYYYYYYYYYBBYYYYYYYYYYYYYBBYYYYYYYYYYYYYBBYYYYYYYYYYYYYYYBBYYYYYYYYYYYYYYBBBYYYYYYYYYYYBBYYYYYYYYYYYYYYYYYB + + + (1 rows) + nnnnnnnn + """), + ), cqlver=cqlsh.DEFAULT_CQLVER) + self.assertCqlverQueriesGiveColoredOutput(( + ("select tags from songs;", r""" + tags + MMMM + ------------------------------------------------- + + {tags: {'genre': 'metal', 'origin': 'england'}} + BYYYYBBBYYYYYYYBBYYYYYYYBBYYYYYYYYBBYYYYYYYYYBB + + + (1 rows) + nnnnnnnn + """), ), cqlver=cqlsh.DEFAULT_CQLVER) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cassandra/blob/3391b99a/pylib/cqlshlib/test/test_keyspace_init.cql ---------------------------------------------------------------------- diff --git a/pylib/cqlshlib/test/test_keyspace_init.cql b/pylib/cqlshlib/test/test_keyspace_init.cql index 2c3d81d..98932bc 100644 --- a/pylib/cqlshlib/test/test_keyspace_init.cql +++ b/pylib/cqlshlib/test/test_keyspace_init.cql @@ -231,3 +231,43 @@ values ('vpupkin', {city: 'Chigirinsk', address: null, zip: '676722'}}, {{country: '+7', number: null}, {country: null, number: '03'}}); + +CREATE TYPE band_info_type ( + founded timestamp, + members set<text>, + description text +); + +CREATE TYPE tags ( + tags map<text, text> +); + +CREATE TABLE songs ( + title text PRIMARY KEY, + band text, + info band_info_type, + tags tags +); + +insert into songs (title, band, info, tags) +values ( + 'The trooper', + 'Iron Maiden', + { + founded:188694000, + members: { + 'Bruce Dickinson', + 'Dave Murray', + 'Adrian Smith', + 'Janick Gers', + 'Steve Harris', + 'Nicko McBrain' + }, + description: 'Pure evil metal' + }, + { + tags: { + 'genre':'metal', + 'origin':'england' + } + }); http://git-wip-us.apache.org/repos/asf/cassandra/blob/3391b99a/pylib/cqlshlib/usertypes.py ---------------------------------------------------------------------- diff --git a/pylib/cqlshlib/usertypes.py b/pylib/cqlshlib/usertypes.py index 577a465..78a7fb0 100644 --- a/pylib/cqlshlib/usertypes.py +++ b/pylib/cqlshlib/usertypes.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from cassandra.marshal import int32_unpack +from cassandra.marshal import int32_unpack, uint16_unpack from cassandra.cqltypes import CompositeType import collections from formatting import formatter_for, format_value_utype @@ -60,5 +60,58 @@ class UserType(CompositeType): return Result(*result) +def deserialize_safe_collection(cls, byts): + """ + Temporary work around for CASSANDRA-7267 + """ + subtype, = cls.subtypes + unpack = uint16_unpack + length = 2 + numelements = unpack(byts[:length]) + if numelements == 0 and len(byts) > 2 : + unpack = int32_unpack + length = 4 + numelements = unpack(byts[:length]) + p = length + result = [] + for n in xrange(numelements): + itemlen = unpack(byts[p:p + length]) + p += length + item = byts[p:p + itemlen] + p += itemlen + result.append(subtype.from_binary(item)) + return cls.adapter(result) +try: + from collections import OrderedDict +except ImportError: # Python <2.7 + from cassandra.util import OrderedDict +def deserialize_safe_map(cls, byts): + """ + Temporary work around for CASSANDRA-7267 + """ + subkeytype, subvaltype = cls.subtypes + unpack = uint16_unpack + length = 2 + numelements = unpack(byts[:length]) + if numelements == 0 and len(byts) > 2: + unpack = int32_unpack + length = 4 + numelements = unpack(byts[:length]) + + p = length + themap = OrderedDict() + for n in xrange(numelements): + key_len = unpack(byts[p:p + length]) + p += length + keybytes = byts[p:p + key_len] + p += key_len + val_len = unpack(byts[p:p + length]) + p += length + valbytes = byts[p:p + val_len] + p += val_len + key = subkeytype.from_binary(keybytes) + val = subvaltype.from_binary(valbytes) + themap[key] = val + return themap
