Skip to content

planview analyze returns a hollow parse for exec <procedure> plans (exit 0, empty stderr) #455

Description

@samplesty

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions