Skip to content

feat: add visual explain plan with AI analysis#128

Merged
debba merged 17 commits intomainfrom
feat/visual-explain-analyze
Apr 14, 2026
Merged

feat: add visual explain plan with AI analysis#128
debba merged 17 commits intomainfrom
feat/visual-explain-analyze

Conversation

@debba
Copy link
Copy Markdown
Owner

@debba debba commented Apr 11, 2026

Summary

This PR introduces a full visual SQL EXPLAIN workflow across the editor and notebook experience.

Users can now open a dedicated Visual Explain modal for supported queries, inspect the execution plan as a graph or table, review the raw driver output, and optionally ask the configured AI provider for a plan analysis.

What Changed

Frontend

  • added a new VisualExplainModal with:
    • graph view for plan nodes and relationships
    • tabular view for easier row-by-row inspection
    • raw output view for direct driver output inspection
    • AI analysis view backed by the configured AI provider
  • added ExplainGraph, ExplainTableView, ExplainSummaryBar, and ExplainAiAnalysis components
  • added reusable explain-plan utilities and types for layout, formatting, and node cost styling
  • exposed the new Explain Plan action in both the SQL editor and notebook SQL cells
  • added localized UI strings for English, Italian, Spanish, and Chinese
  • extended AI settings with a dedicated prompt for explain-plan analysis

Backend / Tauri

  • added the explain_query_plan command to execute and return a structured explain plan
  • added the analyze_ai_explain_plan command to send the SQL query plus explain output to the configured AI provider
  • added prompt configuration support for explain-plan analysis
  • added explain-related models and driver capability plumbing needed by the frontend
  • added cancellation handling around explain execution, aligned with existing query execution patterns

Driver Support

  • PostgreSQL now returns parsed JSON explain plans, with optional ANALYZE and buffer data
  • SQLite now exposes EXPLAIN QUERY PLAN output through the shared explain-plan model
  • MySQL/MariaDB support was expanded significantly:
    • server-version-aware capability detection
    • smarter EXPLAIN ANALYZE usage when supported
    • JSON explain parsing improvements
    • better MariaDB handling for filesort, wrappers, temporary tables, and subquery cache patterns
    • tabular explain fallback when richer formats are unavailable

Query Safety / UX

  • added explainability checks so EXPLAIN only runs for supported statement types
  • strips leading SQL comments before determining whether a query can be explained
  • surfaces a localized error for non-explainable statements
  • warns users when ANALYZE may execute data-modifying statements

Why

The existing SQL tooling could explain queries with AI, but it did not provide a native, structured way to inspect execution plans inside the app. This change closes that gap by combining:

  • a visual representation for quick plan understanding
  • a table/raw fallback for accuracy and debugging
  • AI-assisted interpretation for users who want guidance on bottlenecks and indexing opportunities

Testing

  • pnpm test --run tests/utils/explainPlan.test.ts tests/utils/sql.test.ts
  • pnpm typecheck
  • pnpm test:rust

Results

  • frontend tests: 2 files passed, 66 tests passed
  • Rust tests: 317 passed, 0 failed
  • integration tests: existing MySQL/Postgres integration tests remain ignored

Notes

  • This PR touches both frontend and backend because the feature requires new UI, shared plan models, new Tauri commands, and driver-specific explain parsing.
  • The MySQL driver contains the largest part of the implementation due to compatibility handling across MySQL and MariaDB explain formats.

@debba debba linked an issue Apr 11, 2026 that may be closed by this pull request
// EXPLAIN ANALYZE — MySQL 8.0.18+ text tree with estimated + actual data
if analyze && caps.supports_explain_analyze {
let mut conn = pool.acquire().await.map_err(|e| e.to_string())?;
let analyze_sql = format!("EXPLAIN ANALYZE {}", query);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: SQL Injection vulnerability. The user-supplied query is directly interpolated into SQL without parameterization. While is_explainable_query provides basic filtering, it's not sufficient protection.

This pattern appears in multiple locations in this file (lines 1103, 1136, 1169).

}

let explain_sql = if analyze {
format!("EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS) {}", query)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: SQL Injection vulnerability. The user-supplied query is directly interpolated into SQL without parameterization. While there's upstream validation, direct string interpolation into SQL is unsafe.

Same issue at line 1035.

let pool = get_sqlite_pool(params).await?;
let mut conn = pool.acquire().await.map_err(|e| e.to_string())?;

let explain_sql = format!("EXPLAIN QUERY PLAN {}", query);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: SQL Injection vulnerability. The user-supplied query is directly interpolated into SQL without parameterization.

</div>
{entries.map(([name, value], i) => (
<div
key={`${name}-${i}`}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: React key collision risk. Using name-i as key can still cause collisions if the same property name appears twice. Consider using a more unique key like node.id-name-i.

Comment thread src-tauri/src/commands.rs
Ok(plan)
}
Ok(Err(e)) => {
log::error!("Explain query failed: {}", e);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Double error handling - error is logged here and then returned to caller who may also log it. Consider removing the log::error! here to avoid duplicate logging.

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Apr 11, 2026

Code Review Summary

Status: 4 Issues Found | Recommendation: Address CRITICAL issues before merge

Overview

Severity Count
CRITICAL 3
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

CRITICAL

File Line Issue
src-tauri/src/drivers/mysql/mod.rs 1072 SQL Injection - query directly interpolated into SQL (also at 1103, 1136, 1169)
src-tauri/src/drivers/postgres/mod.rs 1033 SQL Injection - query directly interpolated into SQL (also at 1035)
src-tauri/src/drivers/sqlite/mod.rs 585 SQL Injection - query directly interpolated into SQL

SUGGESTION

File Line Issue
src-tauri/src/commands.rs 2127 Double error logging - error logged and returned
Resolved Issues
File Line Issue Status
src/components/modals/visual-explain/ExplainTableView.tsx 303 React key collision risk FIXED - Code refactored, DetailSection moved to ExplainNodeDetails.tsx
Incremental Review (commit b936e93)

Files changed since last review:

  • src/components/modals/visual-explain/ExplainNodeDetails.tsx - New component (extracted from ExplainTableView)
  • src/components/modals/visual-explain/ExplainOverviewBar.tsx - New overview bar with plan summary statistics (minor fix: added as const to tone literals)
  • src/components/modals/visual-explain/ExplainTableView.tsx - Refactored to use new components, added estimate gap column
  • src/components/modals/visual-explain/ExplainGraph.tsx - Added selection handling props
  • src/components/modals/VisualExplainModal.tsx - Integrated new components, added selection state, improved header
  • src/components/ui/ExplainPlanNode.tsx - Added selection visualization and estimate gap display
  • src/utils/explainPlan.ts - Added plan analysis utilities (getExplainPlanSummary, getRowEstimateRatio, etc.)
  • src/components/modals/NewConnectionModal.tsx - Auto-load databases when editing multi-db connections
  • Translation files - Added new keys for overview features
  • Version bump to 0.9.16

No new issues introduced.

Files Reviewed (32+ files)

Backend (Rust):

  • src-tauri/src/drivers/mysql/mod.rs - SQL injection in EXPLAIN queries
  • src-tauri/src/drivers/postgres/mod.rs - SQL injection in EXPLAIN queries
  • src-tauri/src/drivers/sqlite/mod.rs - SQL injection in EXPLAIN queries
  • src-tauri/src/drivers/common.rs - Added is_explainable_query check
  • src-tauri/src/commands.rs - Added explain_query_plan command
  • src-tauri/src/ai.rs - Added analyze_ai_explain_plan command
  • src-tauri/src/config.rs - Added explain plan prompt configuration

Frontend (TypeScript/React):

  • src/components/modals/VisualExplainModal.tsx - Main modal with selection state
  • src/components/modals/visual-explain/ExplainTableView.tsx - Refactored table view
  • src/components/modals/visual-explain/ExplainNodeDetails.tsx - New node details panel
  • src/components/modals/visual-explain/ExplainOverviewBar.tsx - New overview bar
  • src/components/modals/visual-explain/ExplainGraph.tsx - Graph with selection
  • src/components/modals/visual-explain/ExplainAiAnalysis.tsx - AI analysis component
  • src/components/modals/visual-explain/ExplainSummaryBar.tsx - Summary bar
  • src/components/modals/NewConnectionModal.tsx - Connection modal improvements
  • src/components/ui/ExplainPlanNode.tsx - Node component with selection ring
  • src/utils/explainPlan.ts - Plan analysis utilities
  • Plus 20 additional files

Fix these issues in Kilo Cloud


Reviewed by kimi-k2.5-0127 · 914,102 tokens

@debba debba merged commit 67c2cb7 into main Apr 14, 2026
2 checks passed
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.

Visual Explain Analyze

1 participant