Skip to content

Commit fab2de4

Browse files
committed
Fix: Update pyodbc dependency version and remove assertion of add_output_converter
1 parent 76542b8 commit fab2de4

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
@@ -1627,28 +1627,27 @@ def connect(**kwargs: t.Any) -> t.Callable:
16271627
conn = pyodbc.connect(conn_str, autocommit=kwargs.get("autocommit", False))
16281628

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

1651-
conn.add_output_converter(-155, handle_datetimeoffset)
1650+
conn.add_output_converter(-155, handle_datetimeoffset)
16521651

16531652
return conn
16541653

tests/core/test_connection_config.py

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

16511651

1652-
def test_mssql_pyodbc_connection_no_add_output_converter():
1653-
"""Test that connection gracefully handles pyodbc without add_output_converter."""
1654-
from unittest.mock import Mock, patch
1655-
1656-
with patch("pyodbc.connect") as mock_pyodbc_connect:
1657-
# Create a mock connection without add_output_converter
1658-
mock_connection = Mock()
1659-
# Remove the add_output_converter attribute
1660-
if hasattr(mock_connection, "add_output_converter"):
1661-
delattr(mock_connection, "add_output_converter")
1662-
mock_pyodbc_connect.return_value = mock_connection
1663-
1664-
config = MSSQLConnectionConfig(
1665-
host="localhost",
1666-
driver="pyodbc", # DATETIMEOFFSET handling is pyodbc-specific
1667-
check_import=False,
1668-
)
1669-
1670-
# This should not raise an exception
1671-
factory_with_kwargs = config._connection_factory_with_kwargs
1672-
connection = factory_with_kwargs()
1673-
1674-
# Verify we get the connection back
1675-
assert connection is mock_connection
1676-
1677-
16781652
def test_mssql_no_cursor_init_for_pymssql():
16791653
"""Test that _cursor_init is not needed for pymssql driver."""
16801654
config = MSSQLConnectionConfig(

0 commit comments

Comments
 (0)