Skip to content

Commit 09a5ef6

Browse files
committed
fix(mssql-python): Allow login_attempts kwarg and handle odbc_property overrides.
Signed-off-by: walanguzzi <walanguzzi@outlook.com>
1 parent eb9ae3f commit 09a5ef6

2 files changed

Lines changed: 31 additions & 6 deletions

File tree

sqlmesh/core/config/connection.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,7 @@ class MSSQLConnectionConfig(ConnectionConfig):
15191519
database: t.Optional[str] = ""
15201520
timeout: t.Optional[int] = 0
15211521
login_timeout: t.Optional[int] = 60
1522+
login_attempts: t.Optional[int] = 1
15221523
charset: t.Optional[str] = "UTF-8"
15231524
appname: t.Optional[str] = None
15241525
port: t.Optional[int] = 1433
@@ -1610,6 +1611,7 @@ def _connection_kwargs_keys(self) -> t.Set[str]:
16101611
"trust_server_certificate",
16111612
"encrypt",
16121613
"odbc_properties",
1614+
"login_attempts",
16131615
}
16141616
)
16151617
# Remove pymssql-specific parameters
@@ -1648,8 +1650,9 @@ def connect_mssql_python(**kwargs: t.Any) -> t.Callable:
16481650
authentication = kwargs.pop("authentication", None)
16491651
trust_server_certificate = kwargs.pop("trust_server_certificate", False)
16501652
encrypt = kwargs.pop("encrypt", True)
1653+
timeout = kwargs.pop("timeout", 0)
16511654
login_timeout = kwargs.pop("login_timeout", 59)
1652-
login_attempts = kwargs.pop("login_attempts", 1) # TODO: document
1655+
login_attempts = kwargs.pop("login_attempts", 1)
16531656

16541657
# Build connection string
16551658
conn_str_parts = [
@@ -1664,6 +1667,11 @@ def connect_mssql_python(**kwargs: t.Any) -> t.Callable:
16641667
if trust_server_certificate:
16651668
conn_str_parts.append("TrustServerCertificate=yes")
16661669

1670+
# `Connection Timeout=` is not a valid option so we leverage `ConnectRetry*`.
1671+
# See the following:
1672+
# - https://github.com/microsoft/mssql-python/issues/339
1673+
# - https://github.com/microsoft/mssql-python/wiki/Connection-to-SQL-Database
1674+
# - https://github.com/microsoft/mssql-python/wiki/Connection#timeout
16671675
conn_str_parts.append(f"ConnectRetryCount={login_attempts}")
16681676
conn_str_parts.append(f"ConnectRetryInterval={min(int(login_timeout), 60)}")
16691677

@@ -1687,6 +1695,8 @@ def connect_mssql_python(**kwargs: t.Any) -> t.Callable:
16871695
"pwd",
16881696
"encrypt",
16891697
"trustservercertificate",
1698+
"connectretrycount",
1699+
"connectretryinterval",
16901700
"connection timeout",
16911701
):
16921702
continue
@@ -1700,7 +1710,11 @@ def connect_mssql_python(**kwargs: t.Any) -> t.Callable:
17001710
# Create the connection
17011711
conn_str = ";".join(conn_str_parts)
17021712

1703-
conn = mssql_python.connect(conn_str, autocommit=kwargs.get("autocommit", False))
1713+
conn = mssql_python.connect(
1714+
conn_str,
1715+
autocommit=kwargs.get("autocommit", False),
1716+
timeout=timeout,
1717+
)
17041718

17051719
# TODO: Remove this output converter as DATETIMEOFFSET
17061720
# should be handled natively by `mssql-python`.

tests/core/test_connection_config.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,7 @@ def test_mssql_connection_kwargs_keys():
16711671
"host",
16721672
"timeout",
16731673
"login_timeout",
1674+
"login_attempts",
16741675
"charset",
16751676
"appname",
16761677
"port",
@@ -1862,10 +1863,16 @@ def test_mssql_mssql_python_connection_string_with_odbc_properties():
18621863
odbc_properties={
18631864
"Authentication": "ActiveDirectoryServicePrincipal",
18641865
"ClientCertificate": "/path/to/cert.pem",
1865-
"TrustServerCertificate": "NO", # This should be ignored since we set it explicitly
1866+
# These should be ignored since we set them explicitly:
1867+
"TrustServerCertificate": "NO",
1868+
"ConnectRetryCount": 3,
1869+
"ConnectRetryInterval": 15,
18661870
},
1867-
trust_server_certificate=True, # This should take precedence
18681871
check_import=False,
1872+
# These should take precedence:
1873+
trust_server_certificate=True,
1874+
login_timeout=10,
1875+
login_attempts=2,
18691876
)
18701877

18711878
# Get the connection factory with kwargs and call it
@@ -1880,11 +1887,15 @@ def test_mssql_mssql_python_connection_string_with_odbc_properties():
18801887
assert "Authentication=ActiveDirectoryServicePrincipal" in conn_str
18811888
assert "ClientCertificate=/path/to/cert.pem" in conn_str
18821889

1883-
# Verify that explicit trust_server_certificate takes precedence
1890+
# Verify that explicit kwargs take precedence over odbc_properties
18841891
assert "TrustServerCertificate=yes" in conn_str
1892+
assert "ConnectRetryCount=2" in conn_str
1893+
assert "ConnectRetryInterval=10" in conn_str
18851894

1886-
# Should not have the conflicting property from odbc_properties
1895+
# Should not have conflicting properties from odbc_properties
18871896
assert conn_str.count("TrustServerCertificate") == 1
1897+
assert conn_str.count("ConnectRetryCount") == 1
1898+
assert conn_str.count("ConnectRetryInterval") == 1
18881899

18891900

18901901
@pytest.mark.xfail(not SUPPORTS_MSSQL_PYTHON_DRIVER, reason="mssql-python driver not supported")

0 commit comments

Comments
 (0)