From 27760e57fc00b3152dcb6a3c73c63bff46f82f0b Mon Sep 17 00:00:00 2001 From: Amir Fathi Date: Fri, 28 Aug 2026 02:49:21 +0000 Subject: [PATCH] fix(wren): connect MSSqlConnector with autocommit so statements are not left in an open transaction pyodbc defaults to autocommit=False, and mssql.py never called .commit() or set .autocommit, so every statement on the process-cached connection ran inside one transaction that was never closed. Mirrors canner.py, mysql.py, and redshift.py, which already turn autocommit on. Fixes #2704. --- core/wren/src/wren/connector/mssql.py | 4 +++- core/wren/tests/unit/test_mssql_connection.py | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/core/wren/src/wren/connector/mssql.py b/core/wren/src/wren/connector/mssql.py index 2dc38c79a4..0f87cea886 100644 --- a/core/wren/src/wren/connector/mssql.py +++ b/core/wren/src/wren/connector/mssql.py @@ -469,7 +469,9 @@ def _connect_mssql_pyodbc( for key, value in connect_kwargs.items(): connection_parts.append(f"{key}={_escape_odbc_value(str(value))}") - connection = pyodbc.connect(";".join(connection_parts)) + # pyodbc defaults to autocommit=False, which would leave this cached, + # long-lived connection in one never-committed transaction. + connection = pyodbc.connect(";".join(connection_parts), autocommit=True) _register_mssql_output_converters(connection) if statement_timeout is not None: diff --git a/core/wren/tests/unit/test_mssql_connection.py b/core/wren/tests/unit/test_mssql_connection.py index 083967caf2..7869dd76b3 100644 --- a/core/wren/tests/unit/test_mssql_connection.py +++ b/core/wren/tests/unit/test_mssql_connection.py @@ -228,6 +228,27 @@ def test_mssql_both_credentials_emits_uid_and_pwd() -> None: assert "Trusted_Connection" not in parts +def test_mssql_connects_with_autocommit() -> None: + """pyodbc defaults to autocommit=False, so every statement on this + long-lived, process-cached connection would otherwise run inside a + transaction that is never committed. Mirrors the other connectors + (redshift.py, canner.py, mysql.py) that already turn autocommit on.""" + fake = _FakePyodbc() + with patch("wren.connector.mssql.pyodbc", fake): + _connect_mssql_pyodbc( + host="h", + port="1433", + database="db", + user="alice", + password="secret", + driver="ODBC Driver 18 for SQL Server", + ) + + fake.connect.assert_called_once() + _args, kwargs = fake.connect.call_args + assert kwargs.get("autocommit") is True + + # --------------------------------------------------------------------------- # 3. statement_timeout validated before connect() # ---------------------------------------------------------------------------