Skip to content

Fix #502 follow-up: the advice reads the captured query too - #512

Merged
erikdarlingdata merged 1 commit into
devfrom
fix/502-advice-full-query
Sep 11, 2026
Merged

Fix #502 follow-up: the advice reads the captured query too#512
erikdarlingdata merged 1 commit into
devfrom
fix/502-advice-full-query

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

Fixes #502, for the surface the reporter actually screenshotted. Follow-up to #504.

What #504 missed

#504 recovered the captured query for Copy Query Text and Open in Query Editor, and its "Not covered" section deliberately left Human Advice and Robot Advice analyzing the plan's short copy. The reporter's screenshot is the Human Advice pane, so the nightly read as "cutting same as before" — his words on the issue.

The premise checks out against a real server: a 10,692-character single-statement query captured on SQL Server 2022 comes back with StatementText at exactly 3,999 characters, cut mid-token.

The fix

ResultMapper.Map takes the captured query text and substitutes it for a single-statement plan whose text hit the cap — the same guard as the viewer's PlanOrCapturedStatementText, for the same reason: the captured text is the whole batch, showplan records no statement offsets, and with more than one statement there is no way to say which slice belongs to which row. A confidently wrong query is worse than a short one.

The model is untouched. Rule 39 and the properties panel keep reporting what the plan records; only the mapped output carries the recovery. When it happened, the mapped truncation warning says the text was recovered instead of describing a shortened statement right next to the complete query. Rule 39's base message also stops claiming Copy/Open work from the shortened version — #504 already made that false.

Who passes the text now

Every caller that holds it:

  • Query-editor advice, selected tab and fallback — the fallback also regains the _serverMetadata it was silently dropping, so its advice keeps the Server Context section
  • File-mode advice and both compare-plans dialogs
  • The MCP plan tools (session.QueryText) and MCP Query Store capture (full query_sql_text)
  • PlanOperations session analysis
  • CLI analyze with SQL input (it executed the query itself) and CLI query-store

File/stream paths pass nothing — a .sqlplan alone has nothing to recover from, and Rule 39 explains why the text is short.

Verified end to end

The real SQL Server 2022 plan above, run through the pipeline: advice statement text goes from 3,999 characters to the full 10,692, TextFormatter output contains the whole query, and the warning explains the recovery.

Tests

Six new in TruncatedStatementTextTests (single-statement recovery through to the Human Advice text, warning message swap with the model's warning untouched, multi-statement and uncaptured and untruncated all unchanged, parameter substitution over the recovered text with the ParameterizedStatementText pairing intact). Full suite 531 passed, 1 pre-existing skip, 0 failed.

🤖 Generated with Claude Code

https://claude.ai/code/session_013tW5wVxgbtcCegPuC6Zbqe

#504 recovered the captured query for Copy Query Text and Open in
Query Editor but left Human Advice, Robot Advice, and the MCP tools
analyzing the plan's 4,000-character stub - the surface the reporter
actually screenshotted, so the nightly read as no fix at all.

ResultMapper.Map now takes the captured query text and substitutes it
for a single-statement plan whose text hit the showplan cap, under the
same guard as the viewer's PlanOrCapturedStatementText. The model is
untouched: Rule 39 and the properties panel keep reporting what the
plan records; only the mapped output carries the recovery, and its
truncation warning then says the text was recovered instead of
contradicting the complete query beside it.

Every caller that holds the text passes it: query-editor advice
(selected tab and fallback, which also regains the server metadata it
was silently dropping), file-mode advice, both compare dialogs, the
MCP plan and Query Store tools, PlanOperations session analysis, and
the CLI analyze (SQL input) and query-store commands. File/stream
paths pass nothing - a .sqlplan alone has nothing to recover from.

Verified end to end against SQL Server 2022: a 10,692-character
single-statement query whose plan records 3,999 characters now shows
the full query in the advice output. Six new tests; full suite 531
passed, 1 pre-existing skip, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013tW5wVxgbtcCegPuC6Zbqe
@claude

claude Bot commented Sep 11, 2026

Copy link
Copy Markdown

Reviewed the diff (ResultMapper.cs + call-site plumbing + PlanAnalyzer.Statement.cs + tests). This is a clean, well-scoped fix — no correctness, security, or convention issues found.

Notes from the review, for the record:

  • The single-statement/truncated/non-empty-capture guard in ResultMapper.MapCancellable (counted over PlanStatements.EnumerateAll, matching _allStatements) exactly mirrors the existing PlanViewerControl.PlanOrCapturedStatementText guard, so the "no statement offsets → can't attribute a slice" reasoning stays consistent between the viewer and the mapped output.
  • Recovered text only ever flows into human-readable advice/warning strings (TextFormatter, JSON StatementText/ParameterizedStatementText) — never back into a generated/executed SQL string — so there's no injection surface here even though the input (captured query text) is attacker-influenced in the sense that it echoes user-supplied SQL.
  • The QuerySessionControl.axaml.cs fallback-tab fix (passing _serverMetadata that was previously dropped) is a real, separate bug fix bundled in cleanly with a comment explaining it.
  • Confirmed the callers that should stay text-less do (PlanOperations.OpenStreamCoreAsync for file/stream sessions, Blazor Index.razor), and the ones that should pass captured text all do (query editor incl. fallback, both compare-plans dialogs, MCP plan/Query Store tools, CLI analyze/query-store).
  • No T-SQL generation touched, no version-bump-relevant files touched (no Ssms/vsixmanifest, no Blazor-linked Core file), no new NoWarn.

Nothing to flag.

@erikdarlingdata
erikdarlingdata merged commit 943abf6 into dev Sep 11, 2026
3 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/502-advice-full-query branch September 11, 2026 20:34
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.

1 participant