Repository navigation
fix: keep the last streamed result set readable after nextset - #560
Merged
Merged
Conversation
When a streamed response carried several result sets, nextset() read and dropped the remaining rows of the current set before it found out whether another set followed. On the last set it returned False with those rows already gone, so walking to the last set with `while cursor.nextset()` and then fetching returned nothing. Buffered results kept them. nextset() now keeps the rows it reads past and serves them if no next set follows; they are dropped once the next set starts. Rows of a statement that fails while they are skipped are dropped too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gm42
approved these changes
Oct 28, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
fstr
approved these changes
Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Since #557,
execute_streamcan return several result sets in one response,and
nextset()walks through them. To find out whether another set follows,nextset()has to read past the remaining rows of the current set. It threwthose rows away as it went. On the last set this meant
nextset()returnedFalsewith the rows already gone, so the common "skip to the last resultset, then fetch" loop got nothing back.
executewas not affected: bufferedresults keep the current set when
nextset()returnsFalse.Fix
nextset()now keeps the rows it reads past. If no next set follows, theystay readable from where reading stopped. Once a next set starts, they are
dropped as before.
dropped as well, so a failed statement's partial rows can't be fetched
afterwards.
row_countis unchanged: it still covers every row of the set, fetched orskipped.
nextset()docstrings onboth cursors now describe what happens when there is no next set.
Trade-off: skipping a result set that hasn't been read now holds its
remaining rows in memory until the next set starts. There is no way around
this: the only way to know whether another set follows is to read past
every remaining row, so
nextset()must either keep them or lose them.Test plan
Unit tests for the sync and async streaming row sets:
nextset()returnsFalse, with 0 to 3rows already fetched across several DATA records
nextset()at the end neither loses nor counts rows twicenextset()cannot be fetchedCursor tests (sync and async) for
execute_stream+while nextset()+fetchall(). Two existing mock-basedtest_recovery_after_errortests hadtheir setup adjusted to a state the real stream can reach; none were removed.
🤖 Generated with Claude Code
Note
Medium Risk
Changes core streaming cursor iteration and multi-result-set navigation; behavior shift is intentional but could affect callers relying on rows being discarded after nextset.
Overview
Fixes
execute_stream+while nextset()+fetchall()on the final result set: streamingnextset()used to read ahead to see if another set exists and threw away those rows, so the last set often came back empty even though bufferedexecutekept them.Streaming row sets (sync and async) now buffer rows read during
nextset()in_skipped_records. If no next set exists, iteration continues from that buffer; if a next set starts (or the statement errors), those rows are cleared as before.row_countstill counts skipped rows. Cursornextset()docstrings describe the new behavior.Trade-off: skipping an unread result set may hold its remaining rows in memory until the next set begins.
Reviewed by Cursor Bugbot for commit f331710. Bugbot is set up for automated code reviews on this repo. Configure here.