pypi mssql-python 1.7.1
v1.7.1

5 hours ago

Release Notes - Version 1.7.1

Enhancements

RHEL 8 / glibc 2.28 Wheel Support (#548)

What changed: Added manylinux_2_28 build targets to the Linux wheel matrix, producing wheels compatible with glibc 2.28 environments. Previously only manylinux_2_34 wheels were published, which are incompatible with RHEL 8 and similar older distributions.
Who benefits: Users on Red Hat Enterprise Linux 8, CentOS Stream 8, AlmaLinux 8, Rocky Linux 8, and any other glibc 2.28 compatible distribution.
Impact: pip install mssql-python now succeeds on RHEL 8 and glibc 2.28 systems without requiring manual wheel selection.

PR #548 | GitHub Issue #546

macOS Python 3.10 universal2 Wheel (#542)

What changed: Fixed a missing universal2 wheel for Python 3.10 on macOS. The build matrix was producing only x86_64 for Python 3.10 while all other versions received universal2 (Intel + Apple Silicon fat binary).
Who benefits: Python 3.10 users on Apple Silicon Macs (M1/M2/M3) who were previously forced to run under Rosetta 2 or install via x86_64 wheels.
Impact: Python 3.10 on macOS now installs and runs natively on Apple Silicon.

PR #542 | GitHub Issue #496

UTF-16 String Handling via simdutf (#526)

What changed: Replaced the Python-level UTF-16 encode/decode path with simdutf and std::u16string, moving the conversion into the native layer to eliminate unnecessary Python object allocation and memory copies on every string round-trip.
Who benefits: Applications that read or write Unicode string columns (NVARCHAR, NCHAR, NTEXT) at high volume; workloads that are CPU-bound on string encoding.
Impact: Reduced per-row CPU cost for Unicode string columns; measurable throughput improvement in bulk-fetch and bulk-insert workloads with large string payloads.

PR #526

execute() Hot Path Optimization (#528)

What changed: Optimized the execute() hot path with soft cursor reset (avoids full statement teardown when re-executing the same query), prepared statement caching (reuses previously compiled plans), and guarded diagnostics (defers ODBC diagnostic collection to failure paths only).
Who benefits: Applications that call execute() in a tight loop with the same or similar queries; ORM-heavy workloads; any high-frequency query pattern.
Impact: Reduced per-call overhead for repeat executions; lower CPU usage under high-frequency query workloads.

PR #528


Bug Fixes

Login Failures Raised as mssql_python Exceptions (#562)

What changed: Fixed login and connection failures being surfaced as a generic RuntimeError instead of the appropriate mssql_python exception class (e.g. OperationalError). The error mapping in the connection path now correctly routes authentication and network failures through the DB-API 2.0 exception hierarchy.
Who benefits: All applications that catch specific mssql_python exceptions on connection; error-handling code that distinguishes OperationalError from other exception types.
Impact: except mssql_python.OperationalError now catches login failures as expected; no more bare RuntimeError leaking through on connection failure.

PR #562 | GitHub Issue #532

GIL Released During All Blocking ODBC Calls (#541, #568)

What changed: Extended GIL release to cover all remaining blocking ODBC calls: SQLExecute, SQLFetch, SQLEndTran (commit/rollback), and SQLSetConnectAttr. Previously only connect/disconnect released the GIL, leaving execute, fetch, and transaction calls serializing all Python threads.
Who benefits: Multi-threaded applications using ThreadPoolExecutor, asyncio thread pools, or any concurrent query pattern; applications with long-running queries or large result sets.
Impact: All blocking ODBC I/O operations now release the GIL, enabling true Python thread concurrency during query execution and result fetching.

PR #541 | PR #568 | GitHub Issue #540

executemany RuntimeError When Decimals Change Signs (#560)

What changed: Fixed a RuntimeError in executemany triggered when decimal values changed signs across rows (e.g. a positive decimal followed by a negative one in the same column). The sign change caused an incorrect C-type size calculation in the parameter binding path.
Who benefits: Applications that use executemany to insert or update rows containing Decimal columns where values span positive and negative ranges.
Impact: executemany now correctly handles sign changes in decimal columns without error.

PR #560 | GitHub Issue #557

Inconsistent CP1252 Data in VARCHAR Columns — Windows vs Linux (#495)

What changed: Fixed a discrepancy where CP1252-encoded characters (e.g. , , smart quotes) retrieved from VARCHAR columns returned correct values on Windows but garbled bytes on Linux. The Linux fetch path now applies the same CP1252 decoding as Windows.
Who benefits: Applications running on Linux that read legacy VARCHAR columns with CP1252/Windows-1252 collations; cross-platform deployments where result consistency between Windows and Linux is required.
Impact: CP1252 characters in VARCHAR columns now return identical values on Windows and Linux.

PR #495 | GitHub Issue #468

cursor.bulkcopy() Fails on Empty String in NVARCHAR(MAX) (#559) (via mssql_py_core)

What changed: Fixed cursor.bulkcopy() raising SQL error 40197/4804 when any row in the batch contained an empty string "" destined for an NVARCHAR(MAX) or VARCHAR(MAX) column. The fix ships in mssql_py_core 0.1.4; empty strings are now treated as valid zero-length values consistent with NVARCHAR(n) behaviour.
Who benefits: Applications using cursor.bulkcopy() to insert data that may contain empty strings in MAX-length string columns.
Impact: Empty string values in NVARCHAR(MAX)/VARCHAR(MAX) columns no longer cause bulk copy failures.

PR #559 | GitHub Issue #547

Don't miss a new mssql-python release

NewReleases is sending notifications on new releases.