Repository navigation
FIX: Update rowcount in nextset() - #864
Conversation
nextset() moved to the next result with SQLMoreResults and refreshed description and messages, but left rowcount with the value execute() set for the first statement. The affected-row count of later statements in a batch (e.g. each INSERT of a T-SQL WHILE loop) could not be read. nextset() now sets rowcount like execute(): -1 for a result set, the SQLRowCount of the statement otherwise. This matches pyodbc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
PR Performance Report✅ No regression detectedNo consistent slowdowns detected across all 2 environments. 0 IMPROVEMENTS 0 SLOWDOWNS 2/2 ENVIRONMENTS Coverage: 2 of 2 environments completed. Advisory result; does not block merging. Performance diagnosticsPhase times are inclusive diagnostics and must not be added together. They identify where measured time changed, not why it changed. No affected phases or call-count changes were recorded. All database tasks and timingsUnix / SQL Server 2022
Unix / SQL Server 2025
Build and measurement detailsPR head:
A consistent change requires more than 20% median paired movement, at least 1 ms between the median runtimes, and at least 80% of pairs exceeding the relative threshold in the same direction. A slowdown without enough pair agreement is reported as inconsistent. The displayed change is the median of paired before-and-after ratios. It is not recalculated from the two displayed median runtimes. Both revisions use profiling-enabled builds on the same agent and database, with alternating order and discarded warmups. Results are diagnostic and do not represent production-wheel latency. Raw samples and logs are attached to the ADO run as |
There was a problem hiding this comment.
🔵 Needs a closer look
Reported integration results use published-wheel bindings; SQL Server validation against the current native build still needs human confirmation.
No open issues 🎉
What changed in this PR
Addresses #863 by refreshing the synchronous cursor’s rowcount when nextset() advances, aligning it with execute() behavior.
Changes:
- Reports affected-row counts for non-query results and resets
rowcountto-1for result sets. - Adds regression tests for mixed-statement batches and loops with differing insert counts.
- Documents the fix in the changelog; asynchronous cursors remain unchanged.
| File | Description |
|---|---|
| tests/test_004_cursor.py | Tests per-result row counts in mixed batches and loops. |
| mssql_python/cursor.py | Refreshes rowcount after advancing to a new result. |
| CHANGELOG.md | Records the fix for #863. |
Review effort: Balanced
|
@microsoft-github-policy-service agree |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Jahnvi Thakkar (jahnvi480)
left a comment
There was a problem hiding this comment.
LGTM!
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Work Item / Issue Reference
Summary
Cursor.nextset()callsSQLMoreResultsand refreshesdescriptionandmessages, but it leavesrowcountat the valueexecute()set for the first statement. In a multi-statement batch, the affected-row count of every later INSERT/UPDATE/DELETE was lost. This hits hardest with T-SQL control flow: aWHILEloop sends one result per INSERT, so a tool that sumsrowcountovernextset()gets a stale number.Change (
mssql_python/cursor.py,nextset()). After the describe step,rowcountis set the same wayexecute()sets it:-1when the new result has columns;fetch*()then updates it as it already does;DDBCSQLRowCount(self.hstmt)otherwise.The
SQL_NO_DATApath (nextset()returningFalse) is unchanged. This matches pyodbc, which callsSQLRowCountinCursor_nextsetafterSQLMoreResults.Tests (
tests/test_004_cursor.py):test_nextset_updates_rowcountruns a batch of INSERT (1 row), INSERT (2 rows), SELECT, UPDATE (3 rows), and DELETE (0 rows). It checksrowcountafter eachnextset():1, 2, -1, 3, 0.test_nextset_rowcount_in_loop_batchruns aWHILEloop whose iterations insert 1, 2 and 3 rows. It expects per-result counts[1, 2, 3]. The counts differ on purpose, so a stalerowcountcannot reach the right total by accident.CHANGELOG: entry under Unreleased → Fixed.
Verification. I ran against SQL Server 2022 (16.0.4305.5) on Python 3.12, Debian 12, with the native bindings from the published 1.16.0 wheel, whose
cursor.pyis identical tomainbefore this change.tests/test_004_cursor.pyassert 1 == 2,[1, 1, 1] == [1, 2, 3])The only failures without the fix are the two new tests, and no other test changes result. Black 26.5.1, the version pinned in
.pre-commit-config.yaml, reports both files unchanged.Out of scope:
AsyncCursor.nextset()goes through py-core and was not changed or checked.🤖 Generated with Claude Code