Skip to content

Commit 774b6b3

Browse files
Fix: Update pyodbc dependency version and remove assertion of add_output_converter
1 parent d6dc077 commit 774b6b3

File tree

3 files changed

+23
-50
lines changed

3 files changed

+23
-50
lines changed

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ classifiers = [
4040
[project.optional-dependencies]
4141
athena = ["PyAthena[Pandas]"]
4242
azuresql = ["pymssql"]
43-
azuresql-odbc = ["pyodbc"]
43+
azuresql-odbc = ["pyodbc>=5.0.0"]
4444
bigquery = [
4545
"google-cloud-bigquery[pandas]",
4646
"google-cloud-bigquery-storage"
@@ -78,7 +78,7 @@ dev = [
7878
"pydantic",
7979
"PyAthena[Pandas]",
8080
"PyGithub>=2.6.0",
81-
"pyodbc",
81+
"pyodbc>=5.0.0",
8282
"pyperf",
8383
"pyspark~=3.5.0",
8484
"pytest",
@@ -108,7 +108,7 @@ github = ["PyGithub~=2.5.0"]
108108
llm = ["langchain", "openai"]
109109
motherduck = ["duckdb>=1.2.0"]
110110
mssql = ["pymssql"]
111-
mssql-odbc = ["pyodbc"]
111+
mssql-odbc = ["pyodbc>=5.0.0"]
112112
mysql = ["pymysql"]
113113
mwaa = ["boto3"]
114114
postgres = ["psycopg2"]

sqlmesh/core/config/connection.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,28 +1630,27 @@ def connect(**kwargs: t.Any) -> t.Callable:
16301630
conn = pyodbc.connect(conn_str, autocommit=kwargs.get("autocommit", False))
16311631

16321632
# Set up output converters for MSSQL-specific data types
1633-
if hasattr(conn, "add_output_converter"):
1634-
# Handle SQL type -155 (DATETIMEOFFSET) which is not yet supported by pyodbc
1635-
# ref: https://github.com/mkleehammer/pyodbc/issues/134#issuecomment-281739794
1636-
def handle_datetimeoffset(dto_value: t.Any) -> t.Any:
1637-
from datetime import datetime, timedelta, timezone
1638-
import struct
1639-
1640-
# Unpack the DATETIMEOFFSET binary format:
1641-
# Format: <6hI2h = (year, month, day, hour, minute, second, nanoseconds, tz_hour_offset, tz_minute_offset)
1642-
tup = struct.unpack("<6hI2h", dto_value)
1643-
return datetime(
1644-
tup[0],
1645-
tup[1],
1646-
tup[2],
1647-
tup[3],
1648-
tup[4],
1649-
tup[5],
1650-
tup[6] // 1000,
1651-
timezone(timedelta(hours=tup[7], minutes=tup[8])),
1652-
)
1633+
# Handle SQL type -155 (DATETIMEOFFSET) which is not yet supported by pyodbc
1634+
# ref: https://github.com/mkleehammer/pyodbc/issues/134#issuecomment-281739794
1635+
def handle_datetimeoffset(dto_value: t.Any) -> t.Any:
1636+
from datetime import datetime, timedelta, timezone
1637+
import struct
1638+
1639+
# Unpack the DATETIMEOFFSET binary format:
1640+
# Format: <6hI2h = (year, month, day, hour, minute, second, nanoseconds, tz_hour_offset, tz_minute_offset)
1641+
tup = struct.unpack("<6hI2h", dto_value)
1642+
return datetime(
1643+
tup[0],
1644+
tup[1],
1645+
tup[2],
1646+
tup[3],
1647+
tup[4],
1648+
tup[5],
1649+
tup[6] // 1000,
1650+
timezone(timedelta(hours=tup[7], minutes=tup[8])),
1651+
)
16531652

1654-
conn.add_output_converter(-155, handle_datetimeoffset)
1653+
conn.add_output_converter(-155, handle_datetimeoffset)
16551654

16561655
return conn
16571656

tests/core/test_connection_config.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,32 +1685,6 @@ def mock_add_output_converter(sql_type, converter_func):
16851685
assert result.tzinfo == timezone(timedelta(hours=-8))
16861686

16871687

1688-
def test_mssql_pyodbc_connection_no_add_output_converter():
1689-
"""Test that connection gracefully handles pyodbc without add_output_converter."""
1690-
from unittest.mock import Mock, patch
1691-
1692-
with patch("pyodbc.connect") as mock_pyodbc_connect:
1693-
# Create a mock connection without add_output_converter
1694-
mock_connection = Mock()
1695-
# Remove the add_output_converter attribute
1696-
if hasattr(mock_connection, "add_output_converter"):
1697-
delattr(mock_connection, "add_output_converter")
1698-
mock_pyodbc_connect.return_value = mock_connection
1699-
1700-
config = MSSQLConnectionConfig(
1701-
host="localhost",
1702-
driver="pyodbc", # DATETIMEOFFSET handling is pyodbc-specific
1703-
check_import=False,
1704-
)
1705-
1706-
# This should not raise an exception
1707-
factory_with_kwargs = config._connection_factory_with_kwargs
1708-
connection = factory_with_kwargs()
1709-
1710-
# Verify we get the connection back
1711-
assert connection is mock_connection
1712-
1713-
17141688
def test_mssql_no_cursor_init_for_pymssql():
17151689
"""Test that _cursor_init is not needed for pymssql driver."""
17161690
config = MSSQLConnectionConfig(

0 commit comments

Comments
 (0)