Skip to content

Commit 6d1af98

Browse files
author
Mark Florisson
committed
Support empty string values in NumpyProtocolHandler
1 parent 0f14135 commit 6d1af98

3 files changed

Lines changed: 19 additions & 3 deletions

File tree

cassandra/deserializers.pyx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,17 @@ cdef class Deserializer:
4444

4545
cdef class DesBytesType(Deserializer):
4646
cdef deserialize(self, Buffer *buf, int protocol_version):
47+
if buf.size == 0:
48+
return ""
4749
return to_bytes(buf)
4850

4951
# this is to facilitate cqlsh integration, which requires bytearrays for BytesType
5052
# It is switched in by simply overwriting DesBytesType:
5153
# deserializers.DesBytesType = deserializers.DesBytesTypeByteArray
5254
cdef class DesBytesTypeByteArray(Deserializer):
5355
cdef deserialize(self, Buffer *buf, int protocol_version):
56+
if buf.size == 0:
57+
return bytearray()
5458
return bytearray(buf.ptr[:buf.size])
5559

5660
# TODO: Use libmpdec: http://www.bytereef.org/mpdecimal/index.html
@@ -84,6 +88,8 @@ cdef class DesByteType(Deserializer):
8488

8589
cdef class DesAsciiType(Deserializer):
8690
cdef deserialize(self, Buffer *buf, int protocol_version):
91+
if buf.size == 0:
92+
return ""
8793
if PY2:
8894
return to_bytes(buf)
8995
return to_bytes(buf).decode('ascii')
@@ -169,6 +175,8 @@ cdef class DesTimeType(Deserializer):
169175

170176
cdef class DesUTF8Type(Deserializer):
171177
cdef deserialize(self, Buffer *buf, int protocol_version):
178+
if buf.size == 0:
179+
return ""
172180
cdef val = to_bytes(buf)
173181
return val.decode('utf8')
174182

cassandra/numpy_parser.pyx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ ctypedef struct ArrDesc:
5252
Py_uintptr_t buf_ptr
5353
int stride # should be large enough as we allocate contiguous arrays
5454
int is_object
55+
int empty_binary_ok
5556

5657
arrDescDtype = np.dtype(
5758
[ ('buf_ptr', np.uintp)
5859
, ('stride', np.dtype('i'))
5960
, ('is_object', np.dtype('i'))
60-
])
61+
, ('empty_binary_ok', np.dtype('i'))
62+
], align=True)
6163

6264
_cqltype_to_numpy = {
6365
cqltypes.LongType: np.dtype('>i8'),
@@ -117,6 +119,7 @@ def make_arrays(ParseDesc desc, array_size):
117119
array_descs[i]['buf_ptr'] = arr.ctypes.data
118120
array_descs[i]['stride'] = arr.strides[0]
119121
array_descs[i]['is_object'] = coltype not in _cqltype_to_numpy
122+
array_descs[i]['empty_binary_ok'] = coltype.empty_binary_ok
120123
arrays.append(arr)
121124

122125
return array_descs, arrays
@@ -145,8 +148,9 @@ cdef inline int unpack_row(
145148
get_buf(reader, &buf)
146149
arr = arrays[i]
147150

148-
if buf.size == 0:
151+
if buf.size < 0 or (buf.size == 0 and not arr.empty_binary_ok):
149152
raise ValueError("Cannot handle NULL value")
153+
150154
if arr.is_object:
151155
deserializer = desc.deserializers[i]
152156
val = from_binary(deserializer, &buf, desc.protocol_version)

tests/integration/standard/utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ def get_all_primitive_params(key):
4545
"""
4646
params = [key]
4747
for datatype in PRIMITIVE_DATATYPES:
48-
params.append(get_sample(datatype))
48+
# Also test for empty strings
49+
if key == 1 and datatype == 'ascii':
50+
params.append('')
51+
else:
52+
params.append(get_sample(datatype))
4953
return params
5054

5155

0 commit comments

Comments
 (0)