Leave the sp_executesql declaration list out of substituted statement text - #560
Merged
Merged
Conversation
A plan from the plan cache or Query Store records an sp_executesql statement with its declaration list in front: "(@p1 int, @p2 int)SELECT". Substitution read those names as references, so the advice, exports, MCP tools, "Copy Query Text (with values)" and planview's text output showed "(10 int, 20 int)SELECT ...", which neither matches the plan nor runs. Only the statement after the list gets values now, and when it gets any, the list is dropped. With no values the text stays as the plan recorded it. A list that never closes (the plan cut the text off at 4,000 characters inside it) is left alone. parameterized_statement_text still carries the original. ReproScriptBuilder had its own copy of the list parser; both now use ParameterSubstitution.DeclarationListEnd, which the web project can see. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ZVrq8tpA2DBPEFEqahFK6
|
Reviewed. The |
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
A plan from the plan cache or Query Store records an
sp_executesqlstatement with its declaration list in front of it:(@p1 int, @p2 int)SELECT .... Parameter substitution (#467, #482) read the names in that list as parameter references. So the statement text became(10 int, 20 int)SELECT ... WHERE t.A IN (10, 20). That text is not what the plan records, and it does not run.This text appears in these places:
planview analyze -o textAuto-parameterized plans from the plan cache have the same problem.
(@1 tinyint,@2 int)SELECTbecame(52 tinyint,2 int)SELECT.Now only the statement after the list gets values. When it gets at least one value, the list is dropped. This text is meant to run, and a declaration list is not T-SQL on its own. When no value is substituted, the text stays as the plan recorded it, with its list.
parameterized_statement_textstill carries the original text and its list.A plan cuts statement text off at 4,000 characters. The declarations for a long IN list, such as the ones Dapper writes, can fill all of them. Then the list never closes, and the text holds no statement at all. That text now stays as it is. Before, it became
(1 int,2 int,....ReproScriptBuilderalready stripped the same list for the repro script, with its own copy of the parser. The two now share one parser,ParameterSubstitution.DeclarationListEnd. The web project compilesParameterSubstitution.cswithoutReproScriptBuilder.cs, so the shared parser is inParameterSubstitution.I found this while working on #558. The plan in that issue came from the plan cache, and
planview analyzeprinted its statement as(10 int, 20 int)SELECT ....Tests
ParameterSubstitutiontests:decimal(18,2)andnvarchar(50)ends at its own closing parenthesis.ReproScriptBuildertests:ComparisonBaseline.txtchanges by 4 lines. They are the statement text of the two fixtures that start with a declaration list:(10 int, 20 int)SELECTand(52 tinyint,2 int)SELECTlose their lists. No other line changes.WarningBaseline.txtdoes not change.🤖 Generated with Claude Code
https://claude.ai/code/session_017ZVrq8tpA2DBPEFEqahFK6