Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions singlestoredb/http/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,23 +647,24 @@ def json_to_str(x: Any) -> Optional[str]:
type_code = types.ColumnType.get_code(data_type)
prec, scale = get_precision_scale(col['dataType'])
converter = http_converters.get(type_code, None)

if 'UNSIGNED' in data_type:
flags = 32

if data_type.endswith('BLOB') or data_type.endswith('BINARY'):
converter = functools.partial(
b64decode_converter, converter, # type: ignore
)
charset = 63 # BINARY

if type_code == 0: # DECIMAL
type_code = types.ColumnType.get_code('NEWDECIMAL')
elif type_code == 15: # VARCHAR / VARBINARY
type_code = types.ColumnType.get_code('VARSTRING')
if type_code == 246 and prec is not None: # NEWDECIMAL
prec += 1 # for sign
if scale is not None and scale > 0:
prec += 1 # for decimal

if converter is not None:
convs.append((i, None, converter))

description.append(
Description(
str(col['name']), type_code,
Expand All @@ -673,6 +674,7 @@ def json_to_str(x: Any) -> Optional[str]:
),
)
pymy_res.append(PyMyField(col['name'], flags, charset))

self._descriptions.append(description)
self._schemas.append(get_schema(self._results_type, description))

Expand Down Expand Up @@ -936,7 +938,7 @@ def next(self) -> Optional[Result]:

def __iter__(self) -> Iterable[Tuple[Any, ...]]:
"""Return result iterator."""
return iter(self._rows)
return iter(self._rows[self._row_idx:])

def __enter__(self) -> 'Cursor':
"""Enter a context."""
Expand Down
17 changes: 15 additions & 2 deletions singlestoredb/mysql/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,26 @@ def _parse_field_descriptor(self, encoding):
raise TypeError(f'unrecognized extended data type: {ext_type_code}')

def description(self):
"""Provides a 7-item tuple compatible with the Python PEP249 DB Spec."""
"""
Provides a 9-item tuple.

Standard descriptions only have 7 fields according to the Python
PEP249 DB Spec, but we need to surface information about unsigned
types and charsetnr for proper type handling.

"""
precision = self.get_column_length()
if self.type_code in (FIELD_TYPE.DECIMAL, FIELD_TYPE.NEWDECIMAL):
if precision:
precision -= 1 # for the sign
if self.scale > 0:
precision -= 1 # for the decimal point
return Description(
self.name,
self.type_code,
None, # TODO: display_length; should this be self.length?
self.get_column_length(), # 'internal_size'
self.get_column_length(), # 'precision' # TODO: why!?!?
precision, # 'precision'
self.scale,
self.flags % 2 == 0,
self.flags,
Expand Down
36 changes: 18 additions & 18 deletions singlestoredb/tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1446,7 +1446,7 @@ def test_alltypes_polars(self):
# Recent versions of polars have a problem with decimals
class FixCompare(str):
def __eq__(self, other):
return super().__eq__(other.replace('precision=None', 'precision=22'))
return super().__eq__(other.replace('precision=None', 'precision=20'))

dtypes = [
('id', 'Int32'),
Expand All @@ -1469,10 +1469,10 @@ def __eq__(self, other):
('float', 'Float32'),
('double', 'Float64'),
('real', 'Float64'),
('decimal', FixCompare('Decimal(precision=22, scale=6)')),
('dec', FixCompare('Decimal(precision=22, scale=6)')),
('fixed', FixCompare('Decimal(precision=22, scale=6)')),
('numeric', FixCompare('Decimal(precision=22, scale=6)')),
('decimal', FixCompare('Decimal(precision=20, scale=6)')),
('dec', FixCompare('Decimal(precision=20, scale=6)')),
('fixed', FixCompare('Decimal(precision=20, scale=6)')),
('numeric', FixCompare('Decimal(precision=20, scale=6)')),
('date', 'Date'),
('time', "Duration(time_unit='us')"),
('time_6', "Duration(time_unit='us')"),
Expand Down Expand Up @@ -1593,7 +1593,7 @@ def test_alltypes_no_nulls_polars(self):
# Recent versions of polars have a problem with decimals
class FixCompare(str):
def __eq__(self, other):
return super().__eq__(other.replace('precision=None', 'precision=22'))
return super().__eq__(other.replace('precision=None', 'precision=20'))

dtypes = [
('id', 'Int32'),
Expand All @@ -1616,10 +1616,10 @@ def __eq__(self, other):
('float', 'Float32'),
('double', 'Float64'),
('real', 'Float64'),
('decimal', FixCompare('Decimal(precision=22, scale=6)')),
('dec', FixCompare('Decimal(precision=22, scale=6)')),
('fixed', FixCompare('Decimal(precision=22, scale=6)')),
('numeric', FixCompare('Decimal(precision=22, scale=6)')),
('decimal', FixCompare('Decimal(precision=20, scale=6)')),
('dec', FixCompare('Decimal(precision=20, scale=6)')),
('fixed', FixCompare('Decimal(precision=20, scale=6)')),
('numeric', FixCompare('Decimal(precision=20, scale=6)')),
('date', 'Date'),
('time', "Duration(time_unit='us')"),
('time_6', "Duration(time_unit='us')"),
Expand Down Expand Up @@ -1825,10 +1825,10 @@ def test_alltypes_arrow(self):
('float', 'float'),
('double', 'double'),
('real', 'double'),
('decimal', 'decimal128(22, 6)'),
('dec', 'decimal128(22, 6)'),
('fixed', 'decimal128(22, 6)'),
('numeric', 'decimal128(22, 6)'),
('decimal', 'decimal128(20, 6)'),
('dec', 'decimal128(20, 6)'),
('fixed', 'decimal128(20, 6)'),
('numeric', 'decimal128(20, 6)'),
('date', 'date64[ms]'),
('time', 'duration[us]'),
('time_6', 'duration[us]'),
Expand Down Expand Up @@ -1964,10 +1964,10 @@ def test_alltypes_no_nulls_arrow(self):
('float', 'float'),
('double', 'double'),
('real', 'double'),
('decimal', 'decimal128(22, 6)'),
('dec', 'decimal128(22, 6)'),
('fixed', 'decimal128(22, 6)'),
('numeric', 'decimal128(22, 6)'),
('decimal', 'decimal128(20, 6)'),
('dec', 'decimal128(20, 6)'),
('fixed', 'decimal128(20, 6)'),
('numeric', 'decimal128(20, 6)'),
('date', 'date64[ms]'),
('time', 'duration[us]'),
('time_6', 'duration[us]'),
Expand Down