Skip to content

FIX: Update rowcount in nextset() - #864

Open
LP Bispo (phelipelui) wants to merge 1 commit into
microsoft:mainfrom
phelipelui:fix/nextset-rowcount
Open

LP Bispo (phelipelui) wants to merge 1 commit into
microsoft:mainfrom
phelipelui:fix/nextset-rowcount

Conversation

@phelipelui

Copy link
Copy Markdown

Work Item / Issue Reference

GitHub Issue: #863


Summary

Cursor.nextset() calls SQLMoreResults and refreshes description and messages, but it leaves rowcount at the value execute() 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: a WHILE loop sends one result per INSERT, so a tool that sums rowcount over nextset() gets a stale number.

Change (mssql_python/cursor.py, nextset()). After the describe step, rowcount is set the same way execute() sets it:

  • -1 when the new result has columns; fetch*() then updates it as it already does;
  • DDBCSQLRowCount(self.hstmt) otherwise.

The SQL_NO_DATA path (nextset() returning False) is unchanged. This matches pyodbc, which calls SQLRowCount in Cursor_nextset after SQLMoreResults.

Tests (tests/test_004_cursor.py):

  • test_nextset_updates_rowcount runs a batch of INSERT (1 row), INSERT (2 rows), SELECT, UPDATE (3 rows), and DELETE (0 rows). It checks rowcount after each nextset(): 1, 2, -1, 3, 0.
  • test_nextset_rowcount_in_loop_batch runs a WHILE loop whose iterations insert 1, 2 and 3 rows. It expects per-result counts [1, 2, 3]. The counts differ on purpose, so a stale rowcount cannot 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.py is identical to main before this change.

tests/test_004_cursor.py Without the fix With the fix
New tests 2 failed (assert 1 == 2, [1, 1, 1] == [1, 2, 3]) 2 passed
Whole file 2 failed, 544 passed, 4 skipped 546 passed, 4 skipped

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

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>
Copilot AI balanced review requested due to automatic review settings October 24, 2026 00:59
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

PR Performance Report

Performance could not be assessed.

No matching performance run appeared within the 220-minute wait for 7f5f999e55ccaac099eef7780cdd15ef9cb190ff. No result is available.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 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 rowcount to -1 for 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

@phelipelui

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants