mirror of https://github.com/apache/cassandra
cqlsh: Handle collections embedded into UDTs correctly.
patch by Mikhail Stepura; reviewed by Tyler Hobbs for CASSANDRA-7267
This commit is contained in:
parent
ea02b69001
commit
3391b99a0b
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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'
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue