All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- New feature: Support for macOS and Linux.
- Documentation: Added API documentation in the Wiki.
- New
token_provider=parameter onconnect()/Connectionfor Microsoft Entra ID authentication with a custom credential object. Accepts any object exposing a.get_token(scope)method (e.g. anyazure-identitycredential such asDefaultAzureCredential,AzureCliCredential,ManagedIdentityCredential). Mutually exclusive withAuthentication=in the connection string and withattrs_before[SQL_COPT_SS_ACCESS_TOKEN]. Bulk copy re-acquires a fresh token from the provider on each operation. The token scope is fixed to the Azure commercial cloud; sovereign clouds are out of scope (supply a pre-acquired token viaattrs_beforeinstead). - GH-570: New
Cursor.bulkcopy_arrow(table_name, source)method for high-performance bulk loading directly from Apache Arrow data. Accepts apyarrow.Table,RecordBatch, orRecordBatchReader, any object exposing the Arrow C Data Interface (__arrow_c_stream__/__arrow_c_array__— e.g. polars, pandas 2.2+, DuckDB, ADBC results), or an iterable of record batches. Data is streamed to the server through the Arrow C Data Interface without materializing intermediate Python row objects, and the GIL is released for the duration of the network transfer. When the source data already originates as Arrow, this avoids the Arrow→tuple conversion the classicbulkcopy()path requires (measured ~1.4x–2.7x faster end-to-end for such sources).bulkcopy()now raisesTypeErrorsteering Arrow inputs to this method. Requiresmssql-py-core0.1.5+. - Bulk copy now supports
Authentication=ActiveDirectoryServicePrincipalvia anentra_id_token_factorycallback registered on the mssql-py-core connection. The callback is invoked by mssql-tds mid-handshake (FedAuth workflow 0x02) so the tenant id can be resolved from the server-supplied STS URL. Requiresmssql-py-core0.1.5+. Partial fix for #534. - Standalone
mssql-python-odbcpackage (PRs #663, #664): the Microsoft ODBC Driver 18 for SQL Server binaries are now also published as a separate, platform-specificmssql-python-odbcpackage. When it is installed, the native driver loader resolves the driver from it; when it is absent or incomplete, mssql-python transparently falls back to its own bundledlibs/. This is a non-breaking step toward decoupling driver-binary updates from mssql-python releases; a future major version will make the dependency explicit and drop the bundled binaries.
- Connection strings and string connection parameters that contain a NUL
(
\x00) character are now rejected up front withInterfaceErrorinstead of being silently truncated at the NUL by the underlying driver. - Improved error handling in the connection module.
- GH-627 behavioral change:
NULLparameters forVARBINARY/BINARYcolumns on physical tables now succeed silently (previously raisedProgrammingErrorwhen a non-NULL parameter was bound first). For temp tables whereSQLDescribeParamcannot determine column metadata, the fallback toSQL_VARCHARstill produces the sameProgrammingErroras before; users should callcursor.setinputsizes()to work around this.
- GH-740: A Python
Decimalwhose value falls in the SQL Server MONEY / SMALLMONEY range is now bound asSQL_NUMERICwith its own precision and scale on bothexecute()paths (native detection, and the legacy path reached whensetinputsizes()covers fewer positions than parameters). Previously it was bound as a formattedVARCHARbased on the value alone, so comparing it against a smallernumeric/decimalcolumn (WHERE v = ?) made SQL Server convertvarchar→numericand raise an arithmetic overflow instead of simply not matching. Also fixes a latent binder bug the shortcut was masking: the numeric APD descriptor record number was hardcoded to1, so a numeric parameter in any position other than the first corrupted the parameter bound at position 1. Behavioral change on the wire: money-range Decimals now arrive asnumericrather thanvarchar— a bareSELECT ?returnsDecimalinstead ofstr,sql_variantstores them asnumeric, and becausenumericoutranksmoney/varcharin data-type precedence,WHERE money_or_varchar_col = ?can add aCONVERT_IMPLICITon the column side that turns an index seek into a scan.executemanyintentionally keeps its batchVARCHARstring binding (GH-503); the remaining money-range case there is tracked in #745. - GH-725: The
timeoutparameter ofconnect()/Connection(...)now correctly sets the login (connection-attempt) timeout (SQL_ATTR_LOGIN_TIMEOUT), matching pyodbc and its own docstring. Previously it was silently applied as the per-statement query timeout, soconnect(timeout=N)did not bound the connection attempt and instead aborted long-running queries. Behavioral change: the constructortimeoutno longer affectsConnection.timeout(the query timeout, still settable via the property, default0); an explicitattrs_before[SQL_ATTR_LOGIN_TIMEOUT]takes precedence over thetimeoutkwarg. Timeout values are now validated consistently at both entry points: the constructortimeoutand theConnection.timeoutsetter reject negative, non-integer, andboolvalues (previouslyConnection.timeout = True/Falsewas accepted as1/0). - GH-627: Fixed
SQLDescribeParamordinal remapping bug that causedVARBINARY/BINARYNULLbindings to fail when a non-NULL parameter was bound first. The driver now pre-resolves unknown NULL parameter types before anySQLBindParametercalls, avoiding ODBC ordinal confusion. - GH-726: The extension loader now derives the Windows architecture from
sysconfig.get_platform()(the interpreter build) instead ofplatform.machine()(the host CPU). An x64 interpreter on a Windows ARM64 machine previously looked forddbc_bindings.cpXY-arm64.pyd, missed, and took the fallback path on every import; it now resolves theamd64binary thewin_amd64wheel ships. The fallback notice is now emitted as aRuntimeWarninginstead of being printed to stdout.
- Initial release of the mssql-python driver for SQL Server.
- N/A
- N/A