Version
planview 1.19.1+5bcfdaaca1a7485bf5692fd2d40dc4a6e793393e
What happens
Given an estimated plan captured with SET SHOWPLAN_XML ON around an EXEC <procedure> for a large stored procedure (~3,000 lines, many statements), planview analyze exits 0 with empty stderr and reports:
total_statements: 1
max_estimated_cost: 0
total_warnings: 0
The plan file itself contains rather more than that:
|
|
| File size |
4.2 MB |
StmtSimple elements |
184 |
...of which carry a QueryPlan |
87 |
StmtCond elements |
29 |
NonParallelPlanReason |
present, non-empty |
Sum of StatementSubTreeCost |
691.3 |
So the parse never descends into the procedure body. --output text and --output json --warnings-only behave the same way on the same file, so it does not look specific to operator-tree serialization.
Why it is worth fixing rather than documenting
The failure mode is silent and produces a well-formed, plausible result. Nothing about the output suggests it is empty because the parse stopped early — it looks exactly like a clean plan with no warnings and negligible cost. That invites reporting "no warnings found" and "cost is negligible" from a plan that in fact carries 87 statement plans and a summed cost of 691.
For contrast, analyze does descend correctly into StmtCond (IF/WHILE) bodies in a plain batch, so the gap appears specific to plans wrapping a procedure call.
Expected
Either descend into the procedure body, or fail loudly. A non-zero exit, or a warning that the plan contains statements the parse could not reach, would both be fine — the problem is that a caller cannot distinguish "no findings" from "found nothing because it did not look".
Suggested detection
A cheap invariant: compare the number of XML statements carrying a QueryPlan against summary.total_statements, and treat a large plan reporting max_estimated_cost: 0 with zero warnings as suspect. That combination reliably indicates the parse did not reach the real statements.
Notes
Happy to attach a sanitised plan file if that helps — the original is against a production schema so it would need scrubbing first. Also glad to test a fix against the same plan.
Thanks for the tool; the Query Store filters and the token-efficient JSON output are genuinely useful, which is why this particular silent failure stood out.
Version
planview 1.19.1+5bcfdaaca1a7485bf5692fd2d40dc4a6e793393eWhat happens
Given an estimated plan captured with
SET SHOWPLAN_XML ONaround anEXEC <procedure>for a large stored procedure (~3,000 lines, many statements),planview analyzeexits 0 with empty stderr and reports:The plan file itself contains rather more than that:
StmtSimpleelementsQueryPlanStmtCondelementsNonParallelPlanReasonStatementSubTreeCostSo the parse never descends into the procedure body.
--output textand--output json --warnings-onlybehave the same way on the same file, so it does not look specific to operator-tree serialization.Why it is worth fixing rather than documenting
The failure mode is silent and produces a well-formed, plausible result. Nothing about the output suggests it is empty because the parse stopped early — it looks exactly like a clean plan with no warnings and negligible cost. That invites reporting "no warnings found" and "cost is negligible" from a plan that in fact carries 87 statement plans and a summed cost of 691.
For contrast,
analyzedoes descend correctly intoStmtCond(IF/WHILE) bodies in a plain batch, so the gap appears specific to plans wrapping a procedure call.Expected
Either descend into the procedure body, or fail loudly. A non-zero exit, or a warning that the plan contains statements the parse could not reach, would both be fine — the problem is that a caller cannot distinguish "no findings" from "found nothing because it did not look".
Suggested detection
A cheap invariant: compare the number of XML statements carrying a
QueryPlanagainstsummary.total_statements, and treat a large plan reportingmax_estimated_cost: 0with zero warnings as suspect. That combination reliably indicates the parse did not reach the real statements.Notes
Happy to attach a sanitised plan file if that helps — the original is against a production schema so it would need scrubbing first. Also glad to test a fix against the same plan.
Thanks for the tool; the Query Store filters and the token-efficient JSON output are genuinely useful, which is why this particular silent failure stood out.