From 6f2c308a346713549c7264c1b82a529ac660e5c4 Mon Sep 17 00:00:00 2001 From: Shubham Padkonde Date: Fri, 25 Sep 2026 15:31:14 +0000 Subject: [PATCH] Escape bytes parameters as strings, not as ARRAY of ints With inline parameters, ParamEscaper.escape_item checked for Sequence before bytes. Since bytes is a Sequence, a bytes value was escaped element by element (b"hi" became ARRAY(104,105)), and the bytes handling in escape_string, which decodes UTF-8 for older SQLAlchemy, was never reached. Route bytes to escape_string. Signed-off-by: Shubham Padkonde --- src/databricks/sql/utils.py | 3 ++- tests/unit/test_param_escaper.py | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/databricks/sql/utils.py b/src/databricks/sql/utils.py index 0914bb168..c61886da9 100644 --- a/src/databricks/sql/utils.py +++ b/src/databricks/sql/utils.py @@ -603,7 +603,8 @@ def escape_item(self, item): return "NULL" elif isinstance(item, (int, float)): return self.escape_number(item) - elif isinstance(item, str): + elif isinstance(item, (str, bytes)): + # bytes are a Sequence too, but escape_string decodes them as a string return self.escape_string(item) elif isinstance(item, datetime.datetime): return self.escape_datetime(item, self._DATETIME_FORMAT) diff --git a/tests/unit/test_param_escaper.py b/tests/unit/test_param_escaper.py index 9b6b9c246..d35133f63 100644 --- a/tests/unit/test_param_escaper.py +++ b/tests/unit/test_param_escaper.py @@ -119,6 +119,14 @@ def test_escape_date(self): OUTPUT = "'1991-08-03'" assert pe.escape_datetime(INPUT, FORMAT) == OUTPUT + def test_escape_item_bytes_as_string(self): + """bytes are escaped like the equivalent str, not as an ARRAY of ints""" + assert pe.escape_item(b"golly bob howdy") == "'golly bob howdy'" + assert pe.escape_item("golly bob howdy".encode("utf-8")) == pe.escape_item( + "golly bob howdy" + ) + assert pe.escape_item([b"his", b"name"]) == "ARRAY('his','name')" + def test_escape_sequence_integer(self): assert pe.escape_sequence([1, 2, 3, 4]) == "ARRAY(1,2,3,4)"