Skip to content

Commit 19c51a1

Browse files
committed
Support VARBINARY query parameter
1 parent b020474 commit 19c51a1

File tree

4 files changed

+26
-4
lines changed

4 files changed

+26
-4
lines changed

tests/integration/test_dbapi_integration.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,15 @@ def test_null_date_with_time_zone(trino_connection):
532532
assert rows[0][0] is None
533533

534534

535+
def test_binary_query_param(trino_connection):
536+
cur = trino_connection.cursor(experimental_python_types=True)
537+
538+
cur.execute("SELECT ?", params=(bytearray("a", "utf-8"),))
539+
rows = cur.fetchall()
540+
541+
assert rows[0][0] == bytearray("a", "utf-8")
542+
543+
535544
def test_array_query_param(trino_connection):
536545
cur = trino_connection.cursor()
537546

tests/integration/test_types_integration.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,9 @@ def test_char(trino_connection):
121121

122122
def test_varbinary(trino_connection):
123123
SqlTest(trino_connection) \
124-
.add_field(sql="X'65683F'", python='ZWg/') \
125-
.add_field(sql="X''", python='') \
126-
.add_field(sql="CAST('' AS VARBINARY)", python='') \
127-
.add_field(sql="from_utf8(CAST('😂😂😂😂😂😂' AS VARBINARY))", python='😂😂😂😂😂😂') \
124+
.add_field(sql="X'65683F'", python=b'eh?') \
125+
.add_field(sql="X''", python=b'') \
126+
.add_field(sql="CAST('' AS VARBINARY)", python=b'') \
128127
.add_field(sql="CAST(null AS VARBINARY)", python=None) \
129128
.execute()
130129

trino/client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from __future__ import annotations
3636

3737
import abc
38+
import base64
3839
import copy
3940
import functools
4041
import os
@@ -1053,6 +1054,13 @@ def map(self, value) -> Optional[datetime]:
10531054
).round_to(self.precision).to_python_type()
10541055

10551056

1057+
class BinaryValueMapper(ValueMapper[bytes]):
1058+
def map(self, value) -> Optional[bytes]:
1059+
if value is None:
1060+
return None
1061+
return base64.b64decode(value.encode("utf8"))
1062+
1063+
10561064
class ArrayValueMapper(ValueMapper[List[Optional[Any]]]):
10571065
def __init__(self, mapper: ValueMapper[Any]):
10581066
self.mapper = mapper
@@ -1138,6 +1146,8 @@ def _create_value_mapper(self, column) -> ValueMapper:
11381146
return TimeValueMapper(self._get_precision(column))
11391147
elif col_type == 'date':
11401148
return DateValueMapper()
1149+
elif col_type == 'varbinary':
1150+
return BinaryValueMapper()
11411151
else:
11421152
return NoOpValueMapper()
11431153

trino/dbapi.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
Fetch methods returns rows as a list of lists on purpose to let the caller
1818
decide to convert then to a list of tuples.
1919
"""
20+
import binascii
2021
import datetime
2122
import math
2223
import uuid
@@ -398,6 +399,9 @@ def _format_prepared_param(self, param):
398399
if isinstance(param, Decimal):
399400
return "DECIMAL '%s'" % param
400401

402+
if isinstance(param, (bytes, bytearray)):
403+
return "X'%s'" % binascii.hexlify(param).decode("utf-8")
404+
401405
raise trino.exceptions.NotSupportedError("Query parameter of type '%s' is not supported." % type(param))
402406

403407
def _deallocate_prepared_statement(self, statement_name: str) -> None:

0 commit comments

Comments
 (0)