-
Notifications
You must be signed in to change notification settings - Fork 24
Description
There seems to be some built in coercion occurring when fetching UNIQUEIDENTIFIER results, which is fine, however it seems to take place inconsistently, only when the rows were fetched using fetchone(). When using fetchall() or fetchmany(), the values seem to be bytes using little-endian.
from mssql_python import connect
import uuid
conn_str = "UID=scott;PWD=tiger^5HHH;Server=mssql2022;Database=test;Encrypt=No"
conn = connect(conn_str)
cursor = conn.cursor()
cursor.execute("""DROP TABLE IF EXISTS t1""")
cursor.execute(
"""
CREATE TABLE t1 (
id UNIQUEIDENTIFIER NULL,
data VARCHAR(50) NULL
)
"""
)
for i, uuid_value in enumerate(
[
uuid.UUID("110e2700-9d34-44e9-ba0e-bd74401a54a4"),
uuid.UUID("68be2224-543e-4868-914a-a65f06047593"),
]
):
cursor.execute(
"INSERT INTO t1 (id, data) VALUES (?, ?)",
(str(uuid_value), f"value {i}"),
)
cursor.execute("SELECT id FROM t1 WHERE data = ?", (f"value {i}",))
row = cursor.fetchone()
print(
f"For fetchone() of UUID {uuid_value}, "
f"we get from the driver: {row[0]}"
)
cursor.execute("SELECT id FROM t1 WHERE data = ?", (f"value {i}",))
row = cursor.fetchall()
print(
f"For fetchall() of UUID {uuid_value}, "
f"we get from the driver: {row[0][0]}; "
f"this translates to {uuid.UUID(bytes_le=row[0][0])}"
)
cursor.execute("SELECT id FROM t1 WHERE data = ?", (f"value {i}",))
row = cursor.fetchmany()
print(
f"For fetchmany() of UUID {uuid_value}, "
f"we get from the driver: {row[0][0]}; "
f"this translates to {uuid.UUID(bytes_le=row[0][0])}"
)
output we get shows that we get a binary value for fetchall(), fetchmany(), which apparently converts back using UUID(bytes_le)
:
For fetchone() of UUID 110e2700-9d34-44e9-ba0e-bd74401a54a4, we get from the driver: 110e2700-9d34-44e9-ba0e-bd74401a54a4
For fetchall() of UUID 110e2700-9d34-44e9-ba0e-bd74401a54a4, we get from the driver: b"\x00'\x0e\x114\x9d\xe9D\xba\x0e\xbdt@\x1aT\xa4"; this translates to 110e2700-9d34-44e9-ba0e-bd74401a54a4
For fetchmany() of UUID 110e2700-9d34-44e9-ba0e-bd74401a54a4, we get from the driver: b"\x00'\x0e\x114\x9d\xe9D\xba\x0e\xbdt@\x1aT\xa4"; this translates to 110e2700-9d34-44e9-ba0e-bd74401a54a4
For fetchone() of UUID 68be2224-543e-4868-914a-a65f06047593, we get from the driver: 68be2224-543e-4868-914a-a65f06047593
For fetchall() of UUID 68be2224-543e-4868-914a-a65f06047593, we get from the driver: b'$"\xbeh>ThH\x91J\xa6_\x06\x04u\x93'; this translates to 68be2224-543e-4868-914a-a65f06047593
For fetchmany() of UUID 68be2224-543e-4868-914a-a65f06047593, we get from the driver: b'$"\xbeh>ThH\x91J\xa6_\x06\x04u\x93'; this translates to 68be2224-543e-4868-914a-a65f06047593
Expected behavior
fetchone(), fetchmany(), fetchall() should each return rows in the identical format for a particular value. string is probably best. (many drivers also deliver native Python UUID objects, or offer an option to do so. I dont need that but just something to keep in mind).
Further technical details
Python version: 3.13.5
SQL Server version: (e.g. SQL Server 2022) SQL Server 2022
Operating system: (e.g. Windows Server 2022, Ubuntu 24.04, macOS 14.7.1, Docker container) Fedora running a Fedora 40 container
Additional context
Note this is for development of a SQLAlchemy driver for mssql-python. I'm impressed that at least several hundred tests are running without issue so far. New drivers typically have at least half a dozen bugs though I am getting a lot of passing so far, so that's good.