Fix regression: missing intermediate update counts in multi-statement PreparedStatement execution#2941
Open
Ananya2 wants to merge 6 commits into
Open
Fix regression: missing intermediate update counts in multi-statement PreparedStatement execution#2941Ananya2 wants to merge 6 commits into
Ananya2 wants to merge 6 commits into
Conversation
… PreparedStatement execution
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a regression in PreparedStatement.execute() result traversal for compound SQL batches by preventing legitimate intermediate INSERT update counts from being discarded when lastUpdateCount=false, while preserving trigger-noise filtering and generated-keys behavior.
Changes:
- Adds an overridable hook to control whether intermediate INSERT
DONEINPROCtokens are consumed duringexecute()processing. - Implements
PreparedStatement-specific behavior gated bylastUpdateCountand generated-keys requests. - Adds a regression test covering compound PreparedStatement execution with
lastUpdateCount=false.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java |
Adds shouldConsumeInsertDoneToken() hook and uses it to decide whether to skip intermediate INSERT DONEINPROC counts. |
src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java |
Overrides the hook to respect lastUpdateCount and always consume when generated keys are requested. |
src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java |
Adds regression test for compound PreparedStatement execution with lastUpdateCount=false. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2941 +/- ##
============================================
- Coverage 60.96% 60.82% -0.14%
+ Complexity 5011 4976 -35
============================================
Files 151 151
Lines 35221 35226 +5
Branches 5900 5901 +1
============================================
- Hits 21471 21427 -44
- Misses 10925 10931 +6
- Partials 2825 2868 +43 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…ERT (#2940) and added comprehensive test coverage
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.
Background
PR #2554 fixed an issue where Statement.execute() for INSERT was not consuming the explicit TDS_DONE token containing the update count. This caused getUpdateCount() and getMoreResults() to report incorrect results. The fix consumed INSERT DONEINPROC tokens so the driver would surface only the final DONEPROC update count.
Problem
Compound SQL statements (e.g., DELETE; INSERT; INSERT; UPDATE; INSERT; SELECT) executed via PreparedStatement.execute() That fix introduced a regression for PreparedStatement executing compound SQL (e.g., DELETE; INSERT; INSERT; UPDATE; INSERT; SELECT). Because sp_prepexec wraps the entire batch in a procedure context, all DONE tokens appear as DONEINPROC, not just trigger noise. The unconditional consumption discards legitimate intermediate update counts.
Expected (driver 12.8):
Actual (driver 13.4.0):
Solution
For PreparedStatement, the fix is: don't consume INSERT DONEINPROC tokens, they are real results, not trigger noise. This alone restores correct compound SQL behavior.
However, that would regress the trigger-filtering behavior that PR #2817 fixed (where lastUpdateCount=true means the app doesn't want intermediate trigger counts). So the override uses connection.useLastUpdateCount() as the gate:
lastUpdateCount=true (default) → consume intermediate INSERT counts (preserves trigger filtering from #2817 )
lastUpdateCount=false → retain all counts (app explicitly opted in to seeing everything)
One exception: when generated keys are requested (bRequestedGeneratedKeys), always consume, the appended SCOPE_IDENTITY() query means intermediate INSERT counts must be skipped to reach the identity result.
Testing
Fixes #2940