{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"c-trace-12","type":"registry:block","title":"SQL query plan","description":"An EXPLAIN ANALYZE result opened along the path to the slowest scan, with the index that would remove it.","dependencies":[],"registryDependencies":["@reui/badge","@reui/code-block","trace"],"files":[{"path":"c-trace-12.tsx","type":"registry:block","content":"import { Badge } from \"@/components/reui/badge\"\nimport { CodeBlock } from \"@/components/reui/code-block/code-block\"\n\nimport {\n  Trace,\n  TraceCollapsible,\n  TraceCollapsibleContent,\n  TraceCollapsibleTrigger,\n  TraceDescription,\n  TraceIcon,\n  TraceLine,\n  TraceTitle,\n} from \"@/components/ui/trace\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\ntype PlanNode = {\n  id: string\n  op: string\n  ms: number\n  // Only scans carry numbers here: they are where a plan is read for its cost.\n  details?: [label: string, value: string][]\n  children?: PlanNode[]\n}\n\nconst TOTAL_MS = 798.1\n\nconst PLAN: PlanNode = {\n  id: \"join\",\n  op: \"Hash Join on customer_id\",\n  ms: 798.1,\n  children: [\n    {\n      id: \"orders\",\n      op: \"Seq Scan on orders\",\n      ms: 641.7,\n      details: [\n        [\"Filter\", \"status = 'paid', last 30 days\"],\n        [\"Rows\", \"41,966 of 1,235,368 read\"],\n        [\"Estimate\", \"1,204 rows, off by 35x\"],\n      ],\n    },\n    {\n      id: \"hash\",\n      op: \"Hash\",\n      ms: 21.9,\n      children: [\n        {\n          id: \"customers\",\n          op: \"Seq Scan on customers\",\n          ms: 18.4,\n          details: [[\"Rows\", \"8,412\"]],\n        },\n      ],\n    },\n  ],\n}\n\n// The node with the largest self time (its time minus its children's). Fixed\n// here; a plan viewer computes it from the parsed plan.\nconst HOT_ID = \"orders\"\n\nconst INDEX_SQL = `create index concurrently orders_status_created_at_idx\n  on orders (status, created_at desc);`\n\n// The path to the slow node starts open, and keepMounted keeps any node the\n// reader opened when its parent folds.\nexport function Pattern() {\n  return (\n    <div className=\"flex w-full max-w-lg flex-col gap-4 text-sm\">\n      <Trace>\n        <PlanRow node={PLAN} />\n      </Trace>\n      <Trace>\n        <TraceCollapsible>\n          <TraceCollapsibleTrigger>\n            <TraceLine>\n              <TraceIcon>\n                <IconPlaceholder\n                  lucide=\"LightbulbIcon\"\n                  tabler=\"IconBulb\"\n                  hugeicons=\"BulbIcon\"\n                  phosphor=\"LightbulbIcon\"\n                  remixicon=\"RiLightbulbLine\"\n                />\n              </TraceIcon>\n              <TraceTitle>Suggested an index on orders</TraceTitle>\n              <TraceDescription>est. 641 to 9 ms</TraceDescription>\n            </TraceLine>\n          </TraceCollapsibleTrigger>\n          <TraceCollapsibleContent>\n            <CodeBlock code={INDEX_SQL} language=\"sql\" label=\"Index to add\" />\n          </TraceCollapsibleContent>\n        </TraceCollapsible>\n      </Trace>\n    </div>\n  )\n}\n\nfunction containsHot(node: PlanNode): boolean {\n  return node.id === HOT_ID || (node.children ?? []).some(containsHot)\n}\n\nfunction PlanRow({ node }: { node: PlanNode }) {\n  const hot = node.id === HOT_ID\n  const share = Math.round((node.ms / TOTAL_MS) * 100)\n\n  return (\n    <TraceCollapsible defaultOpen={containsHot(node)}>\n      <TraceCollapsibleTrigger>\n        {/* No icon: the indent already says which node is a child, and the\n            width it frees keeps a deep node's name readable. */}\n        <TraceLine>\n          <TraceTitle>{node.op}</TraceTitle>\n          <TraceDescription>{Math.round(node.ms)} ms</TraceDescription>\n          {hot ? (\n            <Badge variant=\"warning-light\">\n              {share}%<span className=\"sr-only\"> of the query time</span>\n            </Badge>\n          ) : null}\n        </TraceLine>\n      </TraceCollapsibleTrigger>\n      <TraceCollapsibleContent keepMounted>\n        <div className=\"flex flex-col gap-2\">\n          {node.details ? (\n            <dl className=\"flex flex-col gap-0.5 text-xs\">\n              {node.details.map(([label, value]) => (\n                <div key={label} className=\"flex gap-3\">\n                  <dt className=\"w-16 shrink-0\">{label}</dt>\n                  <dd className=\"text-foreground min-w-0\">{value}</dd>\n                </div>\n              ))}\n            </dl>\n          ) : null}\n          {node.children ? (\n            <Trace>\n              {node.children.map((child) => (\n                <PlanRow key={child.id} node={child} />\n              ))}\n            </Trace>\n          ) : null}\n        </div>\n      </TraceCollapsibleContent>\n    </TraceCollapsible>\n  )\n}","target":"components/examples/c-trace-12.tsx"}],"meta":{"order":12,"gridSize":2,"label":"Query Plan"}}