Files
supabase/apps/studio/components/interfaces/ExplainVisualizer/ExplainVisualizer.tsx
Ali Waseem 89e0fe4f28 feature: Explain tab in SQL editor that shows output of explain analyze (#41569)
* wip: explain tab in results editor

* updated to add sql explain

* updated to default back to results

* updated explain function

* updated case with multiple statements

* updated to reset explain query results

* added tests for semi colon comments

* feature: add explain w/ AI on pretty-explain tab (#41588)

* wip: added explain with AI

* wip: updated header with new buttons

* updated prompt

* remove any types

* removed unused flag

* updated header

* formatted code
2025-12-24 10:14:53 -07:00

51 lines
1.6 KiB
TypeScript

import { useMemo } from 'react'
import { ExplainHeader } from './ExplainVisualizer.Header'
import { ExplainNodeRow } from './ExplainVisualizer.NodeRow'
import { calculateMaxDuration, calculateSummary, createNodeTree } from './ExplainVisualizer.parser'
import type { QueryPlanRow } from './ExplainVisualizer.types'
export interface ExplainVisualizerProps {
rows: readonly QueryPlanRow[]
onShowRaw?: () => void
id?: string
}
export function ExplainVisualizer({ rows, onShowRaw, id }: ExplainVisualizerProps) {
const parsedTree = useMemo(() => createNodeTree(rows), [rows])
const maxDuration = useMemo(() => calculateMaxDuration(parsedTree), [parsedTree])
const summary = useMemo(() => calculateSummary(parsedTree), [parsedTree])
if (parsedTree.length === 0) {
return (
<div className="bg-studio border-t">
<p className="m-0 border-0 px-4 py-3 font-mono text-sm text-foreground-light">
No execution plan data available
</p>
</div>
)
}
return (
<div className="bg-studio border-t h-full flex flex-col min-h-0">
{onShowRaw && (
<ExplainHeader
mode="visual"
onToggleMode={onShowRaw}
summary={summary}
id={id}
rows={rows}
/>
)}
{/* Plan nodes */}
<div className="flex-1 overflow-auto min-h-0">
<div className="flex flex-col min-w-max pb-4">
{parsedTree.map((node, idx) => (
<ExplainNodeRow key={idx} node={node} depth={0} maxDuration={maxDuration} />
))}
</div>
</div>
</div>
)
}