Uh oh!
There was an error while loading. Please reload this page.
PERF: Optimize execute() hot path: soft reset, prepare caching, and guarded diagnostics - #528
Conversation
📊 Code Coverage Report
Diff CoverageDiff: main...HEAD, staged and unstaged changes
Summary
mssql_python/cursor.pyLines 759-771 759ifself.hstmt:
760ret=ddbc_bindings.DDBCSQLResetStmt(self.hstmt)
761try:
762check_error(ddbc_sql_const.SQL_HANDLE_STMT.value, self.hstmt, ret)
! 763exceptException:
764logger.warning("_soft_reset_cursor failed; falling back to full reset")
! 765self._reset_cursor()
! 766self.last_executed_stmt=""
! 767return768self._clear_rownumber()
769770defclose(self) ->None:
771 """Lines 1384-1392 1384ifreset_cursor:
1385ifself.hstmt:
1386self._soft_reset_cursor()
1387else:
! 1388self._reset_cursor()
1389else:
1390# Close just the ODBC cursor (not the statement handle) so the1391# prepared plan can be reused. SQLFreeStmt(SQL_CLOSE) releases1392# the cursor associated with hstmt without destroying themssql_python/pybind/ddbc_bindings.cppLines 1379-1394 1379 }
13801381SQLRETURNSQLResetStmt_wrap(SqlHandlePtr statementHandle) {
1382if (!statementHandle || !statementHandle->get()) {
! 1383returnSQL_INVALID_HANDLE;
! 1384 }
1385if (statementHandle->isImplicitlyFreed()) {
! 1386returnSQL_INVALID_HANDLE;
! 1387 }
1388if (!SQLFreeStmt_ptr) {
! 1389DriverLoader::getInstance().loadDriver();
! 1390 }
1391SQLHANDLE hStmt = statementHandle->get();
13921393SQLRETURN rc;
1394 {📋 Files Needing Attention📉 Files with overall lowest coverage (click to expand)mssql_python.pybind.logger_bridge.cpp: 59.2%
mssql_python.pybind.ddbc_bindings.h: 67.9%
mssql_python.row.py: 70.5%
mssql_python.pybind.logger_bridge.hpp: 70.8%
mssql_python.pybind.ddbc_bindings.cpp: 74.6%
mssql_python.pybind.connection.connection.cpp: 75.8%
mssql_python.__init__.py: 77.3%
mssql_python.ddbc_bindings.py: 79.6%
mssql_python.pybind.connection.connection_pool.cpp: 79.6%
mssql_python.connection.py: 85.3%🔗 Quick Links
|
ab57bb8 to
6703b85CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
2ee0f68 to
c113a03Compare970ce4d to
0604fc5CompareThere was a problem hiding this comment.
Pull request overview
This PR adds a lightweight statement “reset” primitive to the pybind ODBC layer and uses it in Cursor.execute() to reduce overhead on the execute hot path (avoid full HSTMT reallocation, skip redundant parameter-style conversion on re-execution, and reduce diagnostic-record collection work).
Changes:
- Add
DDBCSQLResetStmtpybind export to close the cursor + reset parameter bindings without freeing the HSTMT. - Update
Cursor.execute()to use_soft_reset_cursor()and introduce simple prepare caching + reduced conversion/log/diagnostic overhead. - Adjust the perf benchmark script to strip
Driver=from the connection string formssql-pythonwhen present.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
mssql_python/pybind/ddbc_bindings.cpp | Adds SQLResetStmt_wrap and exports DDBCSQLResetStmt to Python. |
mssql_python/cursor.py | Uses soft reset + prepare caching and optimizes parameter conversion/logging/diagnostics in execute(). |
benchmarks/perf-benchmarking.py | Normalizes conn string for mssql-python by removing Driver= when present. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
612c063 to
c529bc9CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
c529bc9 to
536cde1Compare- Add _soft_reset_cursor: SQL_CLOSE + SQL_RESET_PARAMS instead of full HSTMT free/realloc on each execute() call - Add DDBCSQLResetStmt C++ wrapper exposing lightweight reset via pybind11 - Skip SQLPrepare when re-executing the same SQL (prepare caching) - Skip detect_and_convert_parameters on repeated same-SQL calls - Guard DDBCSQLGetAllDiagRecords behind SQL_SUCCESS_WITH_INFO check - Guard per-parameter debug logging behind logger.isEnabledFor(DEBUG) - Fix benchmark script to strip Driver= from mssql-python connection string
536cde1 to
88329a0CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
### Work Item / Issue Reference > [AB#45159](https://sqlclientdrivers.visualstudio.com/mssql-python/_sprints/taskboard/mssql-python%20Team/mssql-python/Rubidium/May%202026?workitem=45159) ------------------------------------------------------------------- ### Summary **Enhancements** - #548 — manylinux_2_28 build targets for RHEL 8 / glibc 2.28 - #542 — macOS universal2 wheel for Python 3.10 - #526 — UTF-16 string handling via simdutf - #528 — Optimized execute() hot path - #567 — Azure Linux installation docs **Bug Fixes** - #562 — Login failures now raise mssql_python exception instead of RuntimeError - #568 — GIL released during blocking SQLSetConnectAttr calls - #541 — GIL released during blocking ODBC statement/fetch/transaction calls - #560 — executemany RuntimeError when decimals change signs - #495 — Inconsistent CP1252 VARCHAR retrieval Windows vs Linux - #559 — BulkCopy empty string in NVARCHAR(MAX)/VARCHAR(MAX) (via mssql_py_core 0.1.4)
Work Item / Issue Reference
Summary
This pull request introduces performance benchmarking infrastructure improvements and optimizations to the
mssql_pythondriver, as well as documentation and workflow updates to support a newPERF:pull request prefix. The most significant changes are grouped below.Driver Performance Optimizations:
_soft_reset_cursorincursor.pyto reuse prepared statement handles, avoiding unnecessary SQLPrepare calls when executing the same SQL repeatedly. This improves performance for repeated statement execution. [1][2][3][4]DDBCSQLResetStmtbinding in the C++ layer to support the lightweight reset operation, and exposed it to Python. [1][2]