Native graphical query plan viewer (#220)#243
Merged
erikdarlingdata merged 11 commits intodevfrom Feb 23, 2026
Merged
Conversation
Phase 1: ShowPlanXML rendering as interactive operator graph in a new Plan Viewer tab. Right-click any query row → View Estimated Plan to parse and display the plan inline (fetches on-demand when needed). - LINQ-to-XML parser with cost computation, warnings, missing indexes - SSMS-style layout: left-to-right with first-child horizontal spine - 113 MIT-licensed operator icons from vscode-mssql - Synthetic SELECT/INSERT/UPDATE/DELETE root node - Rich tooltips, zoom/pan, save .sqlplan, multi-statement selector - Missing index banner with CREATE INDEX suggestions - Warnings banner (spills, implicit conversions, no join predicate) - View Actual Plan menu item stubbed for Phase 2 (query execution) Tested on sql2022 with TPC-H plans. Both apps build clean. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add collapsible properties panel (right-side, GridSplitter) with node selection - Add rich tooltips with costs, rows, I/O, predicates, output columns - Parse ~30 new operator properties: OrderBy, GroupBy, DefinedValues, OuterReferences, join columns, adaptive join, extended I/O stats, scan hints (ForcedIndex/ForceScan/ForceSeek/NoExpandHint), etc. - Fix XML scoping bug: ScopedDescendants() prevents child RelOp property leakage (seek predicates, object names no longer bleed to parent operators) - Fix EstimatedRowsRead/TableCardinality parsing (attributes are on RelOp, not the physical operator element) - Fix DefinedValues to include column-only entries (no scalar expression) - Gate Statement Memory Grant and Statement Info to root node only - Always show boolean properties (Ordered, ForceScan, etc.) for scan/seek ops - Always show I/O/CPU costs, rebinds/rewinds, estimated executions - Add node context menus (Properties, Copy Operator/Object/Predicate) - Statement-level metadata: CE version, DOP, compile stats, query hashes Both Dashboard and Lite updated and tested against SSMS properties output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parse all operator-specific attributes per ShowPlan XSD schema: - RelOp: Partitioned, IsAdaptive/AdaptiveThresholdRows/EstimatedJoinType (fixed: these are on <RelOp>, not the physical operator element) - IndexScan: Lookup, DynamicSeek - NestedLoops: Optimized, WithOrderedPrefetch, WithUnorderedPrefetch - Sort: Distinct - Filter: StartupExpression - Top: WithTies - Hash: BitmapCreator - Parallelism: Remoting, LocalParallelism Fix Lite ViewEstimatedPlan_Click missing switch cases: - ProcedureStatsRow: fetch via FetchProcedurePlanOnDemandAsync - QueryStoreRow: fetch via FetchQueryStorePlanAsync Both apps build clean, properties panel displays all new attributes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wave 1 bug fixes: StatementEstRows int→double, IsMemoryGrantFeedbackAdjusted bool→string (shows actual feedback status), CE version read from StmtSimple. Wave 2 high priority: Merge/NL residual+PassThru predicates, stale stats warning, per-operator memory grants, MaxQueryMemory, Parallelism HashKeys, Top offset/rows, QueryPlan-level warnings. Wave 3 medium priority: EffectiveDOP, MemoryFractions, RunTimePartitionSummary, PlanGuide/UsePlan, ParameterizedText, QS hints, enhanced spill details, Spool stack/PrimaryNodeId, Update DML sort/ActionColumn, columnstore segment stats, UDF timing, TraceFlags, IndexedViewInfo, EstimatedDOP per-operator. Wave 4 structural: StmtCond (IF/ELSE recursive parsing), StmtCursor with cursor metadata and operation sub-plans. All changes applied to both Dashboard and Lite. Both build clean, 0 errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Issue #233: ReproScriptBuilder extracts StatementSetOptions from plan XML and emits matching SET statements (ANSI_NULLS, ARITHABORT, etc.) in repro scripts. Added isAzureSqlDb parameter to skip USE [database] for Azure SQL DB. Removed SET STATISTICS XML OFF from repro scripts (interfered with SSMS plans). - Smart plan selection: "View Plan" now prefers live_query_plan (from dm_exec_query_statistics_xml) when available, falls back to estimated plan. Renamed menu item from "View Estimated Plan" to "View Plan". - ActualPlanExecutor service: Wraps repro script with SET STATISTICS XML ON/OFF, executes query, iterates result sets capturing plan XML, discards all data rows. Supports cancellation via CancellationToken -> SqlCommand.Cancel(). - GetActualPlan_Click handlers in both apps: Confirmation dialog warning about query execution, 120-second timeout, loads actual plan into plan viewer. - Actual stats on plan nodes: Duration, CPU time, and actual vs estimated rows (with accuracy %) displayed on each operator when actual stats are available. - Per-node layout heights: PlanLayoutEngine calculates each node's height based on content (actual stats lines, object name) to prevent vertical overlap. Nodes auto-size visually with MinHeight for estimated plans. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tabbed plans: multiple plans open simultaneously for comparison, close individual tabs - Query text: collapsible read-only expander showing the source query - Statement selector: hide label/cost text for single-statement plans - Node text: white by default, OrangeRed for elapsed >= 1s, CPU >= 1s, row estimate off by 10x+ - Indicator badges: orange triangle for warnings, amber circle for parallelism (both visible simultaneously) - Properties panel: collapsible Expander sections for easier navigation - Dashboard ViewPlanRequested event extended to pass queryText Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full XSD audit against SSMS 22 schema (2611 lines) with systematic gap closure across all major complex types. Parser now covers ~95% of non-PDW/non-Hyperscale attributes and elements. New parsing: - Dispatcher/PSP with OptionalParameterPredicate (SQL 2022+/2025) - Per-thread RunTimeCountersPerThread (23 fields for parallel skew) - Sort/Hash/Exchange SpillDetails as structured warning data - CardinalityFeedback, UDF/StoredProc sub-plans, ScalarUDF detection - Remote operator metadata, StarJoinInfo, RollupInfo, PartitionId - NamedParameterList, TieColumns, UDXName, IndexedViewInfo per-operator - OptimizationReplay, QueryCompilationReplay, RowRequalifications PlanAnalyzer (new): - 5 analysis rules: Filter operators, Eager Index Spools, Serial plan detection, UDF timing thresholds, row estimate mismatch (10x/100x) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…l index suggestion Loading indicator: Plan Viewer tab now shows a progress bar and Cancel button during actual plan execution. Removed the 120-second timeout — queries run until complete or cancelled. Dashboard uses ActualPlanStarted/ActualPlanFinished events; Lite wires inline. New PlanAnalyzer rules: - Rule 6: Scalar UDF references (works on estimated plans) - Rule 7: Spill severity promotion (>1000 pages → Critical) - Rule 8: Parallel thread skew (one thread handling 90%+ of rows) - Rule 9: Memory grant issues (10x+ overestimate, grant wait time) - Rule 10: Key Lookup with residual predicate - Rule 11: Scan with residual predicate Eager spool enhancement: Parser now extracts SeekPredicateNew key columns and OutputList includes to generate a suggested CREATE INDEX statement. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The badge Grid elements had their own ToolTip strings that spawned blank-looking popups over the parent node's rich tooltip. Removing them lets the parent border's detailed tooltip show through instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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
Closes #220
Changes
Plan Viewer UI (both apps)
PlanViewerControl.xaml/.cs— graphical canvas with zoom/pan, node rendering, edge drawing, properties panel, collapsible warnings/missing indexes sectionsPlanLayoutEngine.cs— right-to-left tree layout algorithmPlanIconMapper.cs— maps 120+ operator types to SSMS-sourced PNG iconsResources/PlanIcons/— 120 operator icon PNGsPlan Parser & Models (both apps)
ShowPlanParser.cs(~1600 lines) — full XDocument-based XML parser covering statements, QueryPlan metadata, RelOp tree, operator-specific elements, warnings, per-thread runtime stats, scalar UDF detection, Dispatcher/PSP, memory grants, spill details, and morePlanModels.cs(~515 lines) — complete data model: ParsedPlan → PlanBatch → PlanStatement → PlanNode tree with all XSD attributesPlan Analysis Engine (both apps)
PlanAnalyzer.cs— 11 post-parse rules:Actual Plan Execution (both apps)
ActualPlanExecutor.cs— executes queries with SET STATISTICS XML ON, cancellable, no timeoutReproScriptBuilder.cs— extracts SET options from plan XML for faithful reproIntegration
ServerTab.xaml/.cs— tabbed plan container with empty state, loading state, close buttonsQueryPerformanceContent.xaml.cs(Dashboard) — right-click context menu wiring, ActualPlanStarted/Finished eventsServerTab.xaml.cs(Lite) — inline actual plan wiringTest Plan
Generated with Claude Code