pgexplain 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/util/exit.ts","../src/diagnostics/diagnostic.ts","../src/diagnostics/catalog.ts","../src/config.ts","../src/core/schema.ts","../src/core/parse.ts","../src/core/metrics.ts","../src/util/format.ts","../src/advisor/rules/util.ts","../src/advisor/rules/bitmap-lossy.ts","../src/advisor/rules/cartesian-product.ts","../src/advisor/rules/correlated-subplan.ts","../src/advisor/rules/could-be-index-only.ts","../src/advisor/rules/filter-could-be-index-cond.ts","../src/advisor/rules/hash-spill-disk.ts","../src/advisor/rules/high-filter-discard.ts","../src/advisor/rules/index-only-heap-fetches.ts","../src/advisor/rules/low-cache-hit.ts","../src/advisor/rules/nested-loop-large-outer.ts","../src/advisor/rules/row-misestimate.ts","../src/advisor/rules/seq-scan-large.ts","../src/advisor/rules/significant-jit.ts","../src/advisor/rules/sort-spill-disk.ts","../src/advisor/rules/trigger-time.ts","../src/advisor/rules/workers-not-launched.ts","../src/advisor/rules/index.ts","../src/advisor/index.ts","../src/input/redact.ts","../src/report/tree.ts","../src/report/json.ts","../src/report/html.ts","../src/report/markdown.ts","../src/util/color.ts","../src/report/terminal.ts","../src/report/render.ts","../src/index.ts"],"names":["ExitCode","DOCS","bottlenecks","heat"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Process exit codes. Documented in README and `pg-explain --help` so scripts and\n * CI can branch on the *kind* of failure without parsing text.\n */\nexport enum ExitCode {\n /** Report produced. Findings alone do not change this unless --strict/--fail-on. */\n Success = 0,\n /** CI gate tripped: findings present AND --strict / --fail-on threshold met. */\n CiGate = 1,\n /** Usage error: bad flags/args, refused non-SELECT, unsupported option. */\n Usage = 2,\n /** Input error: no/empty stdin and no --file, unreadable file. */\n Input = 3,\n /** Parse/validation error: not valid EXPLAIN JSON or wrong shape. */\n Parse = 4,\n /** Database error: connect/auth/permission/timeout/cancel. */\n Database = 5,\n /** pg-explain itself hit an unexpected error. */\n Internal = 70,\n /** Interrupted by SIGINT. (128 + signal number.) */\n Sigint = 130,\n}\n","import type { Diagnostic, Remediation, Severity } from \"../core/model.ts\";\nimport type { ExitCode } from \"../util/exit.ts\";\n\n/**\n * An error that carries a fully-actionable Diagnostic and a process exit code.\n * cli.ts catches these, renders the diagnostic to stderr, and exits with `exitCode`.\n * Anything NOT an AppError that reaches the top level becomes PGX_INTERNAL.\n */\nexport class AppError extends Error {\n readonly diagnostic: Diagnostic;\n readonly exitCode: ExitCode;\n\n constructor(diagnostic: Diagnostic, exitCode: ExitCode, cause?: unknown) {\n super(diagnostic.title);\n this.name = \"AppError\";\n this.diagnostic = diagnostic;\n this.exitCode = exitCode;\n if (cause !== undefined) this.cause = cause;\n }\n}\n\n/** Convenience constructor for plan-domain findings (used by advisor rules). */\nexport function finding(\n code: string,\n severity: Severity,\n parts: {\n title: string;\n detail: string;\n cause: string;\n remediation: Remediation;\n docsUrl?: string;\n location?: Diagnostic[\"location\"];\n meta?: Diagnostic[\"meta\"];\n },\n): Diagnostic {\n return { code, domain: \"plan\", severity, ...parts };\n}\n\nconst SEVERITY_RANK: Record<Severity, number> = { error: 0, warn: 1, info: 2 };\n\n/** Sort by severity (error first), keeping input order within a severity (stable). */\nexport function bySeverity(a: Diagnostic, b: Diagnostic): number {\n return SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];\n}\n\nexport function maxSeverity(a: Severity, b: Severity): Severity {\n return SEVERITY_RANK[a] <= SEVERITY_RANK[b] ? a : b;\n}\n\n/** True when `s` is at least as severe as `threshold` (error ≥ warn ≥ info). */\nexport function severityAtLeast(s: Severity, threshold: Severity): boolean {\n return SEVERITY_RANK[s] <= SEVERITY_RANK[threshold];\n}\n\n/**\n * Remove secrets from any string before it is logged, shown, or written.\n * Targets:\n * - userinfo passwords in connection URLs: postgres://user:secret@host → user:***@host\n * - libpq keyword form: password=secret → password=***\n * - PG* env-style: PGPASSWORD=secret → PGPASSWORD=***\n * - URL query params: ?password=secret&sslmode=… → ?password=***&…\n */\nexport function scrubCredentials(input: string): string {\n if (!input) return input;\n return input\n .replace(/(\\b[a-z][a-z0-9+.-]*:\\/\\/[^:/?#@\\s]+:)([^@\\s]+)(@)/gi, \"$1***$3\")\n .replace(/\\bpassword\\s*=\\s*'[^']*'/gi, \"password='***'\")\n .replace(/(\\bpassword\\s*=\\s*)([^\\s&'\"]+)/gi, \"$1***\")\n .replace(/(\\bPGPASSWORD\\s*=\\s*)([^\\s&'\"]+)/gi, \"$1***\");\n}\n","import type { Diagnostic, DiagnosticLocation, Severity } from \"../core/model.ts\";\nimport { ExitCode } from \"../util/exit.ts\";\nimport { AppError } from \"./diagnostic.ts\";\n\nconst DOCS = \"https://www.postgresql.org/docs/current\";\n\ninterface OpSpec {\n severity: Severity;\n exit: ExitCode;\n title: string;\n detail: string;\n cause: string;\n remediation: Diagnostic[\"remediation\"];\n docsUrl?: string;\n}\n\n/**\n * The operational error catalog. Every entry tells the developer WHAT happened,\n * WHY, and HOW to fix it. Codes are stable and greppable; they never change meaning.\n * Dynamic specifics (host, user, db, timeout) are injected via `overrides.detail`.\n */\nconst CATALOG = {\n PGX_AUTH_FAILED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Authentication failed\",\n detail: \"The server rejected the supplied credentials.\",\n cause:\n \"The password or role is wrong, or pg_hba.conf does not permit this role from your host.\",\n remediation: {\n summary: \"Verify the credentials and supply the password safely (never on the command line).\",\n steps: [\n \"Confirm the username and password are correct.\",\n \"Provide the password via PGPASSWORD or ~/.pgpass instead of the command line.\",\n \"Check that pg_hba.conf allows this role from your client host.\",\n ],\n commands: [\n { label: \"Set password via env\", shell: \"export PGPASSWORD=<password>\" },\n {\n label: \"Or store it (chmod 600)\",\n shell: 'echo \"<host>:<port>:<db>:<user>:<password>\" >> ~/.pgpass && chmod 600 ~/.pgpass',\n },\n ],\n },\n docsUrl: `${DOCS}/auth-pg-hba-conf.html`,\n },\n\n PGX_HOST_UNREACHABLE: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Cannot reach the PostgreSQL server\",\n detail: \"DNS resolution failed or the TCP connection was refused.\",\n cause:\n \"Wrong host/port, the server is down, or a firewall/VPN/security group is blocking the port.\",\n remediation: {\n summary: \"Verify the host and port, then probe reachability.\",\n steps: [\n \"Double-check --host and --port (or the DSN) for typos.\",\n \"Confirm the server is running and accepts TCP connections.\",\n \"Check VPN, firewall, and cloud security-group rules for the port.\",\n ],\n commands: [{ label: \"Probe reachability\", shell: \"pg_isready -h <host> -p <port>\" }],\n },\n docsUrl: `${DOCS}/libpq-connect.html`,\n },\n\n PGX_DB_NOT_FOUND: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Database does not exist\",\n detail: \"The named database was not found on the server.\",\n cause: \"The database name is misspelled or the database has not been created.\",\n remediation: {\n summary: \"List the available databases and correct the name.\",\n commands: [\n { label: \"List databases\", shell: \"psql -h <host> -U <user> -l\" },\n { label: \"Re-run with the right name\", shell: \"pg-explain run --dbname <name> ...\" },\n ],\n },\n },\n\n PGX_SSL_REQUIRED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Server requires SSL\",\n detail: \"The server requires an encrypted connection but a plaintext one was offered.\",\n cause: \"pg_hba.conf mandates SSL (e.g. `hostssl`) for this role/host.\",\n remediation: {\n summary: \"Enable SSL on the connection.\",\n commands: [\n { label: \"Require encryption\", shell: \"pg-explain run --sslmode require ...\" },\n {\n label: \"Or verify the certificate too\",\n shell: \"pg-explain run --sslmode verify-full --sslrootcert <ca.pem> ...\",\n },\n ],\n },\n docsUrl: `${DOCS}/libpq-ssl.html`,\n },\n\n PGX_SSL_VERIFY_FAILED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"TLS certificate verification failed\",\n detail: \"Under verify-full the certificate chain is untrusted or the hostname does not match.\",\n cause:\n \"The CA is not trusted locally, or the certificate's CN/SAN does not match the host you connect to.\",\n remediation: {\n summary: \"Point at the CA bundle and confirm the hostname matches the certificate.\",\n steps: [\n \"Provide the CA certificate the server's cert chains to.\",\n \"Confirm the certificate CN/SAN matches the --host value.\",\n \"Only fall back to `--sslmode require` (encryption without identity check) if you accept the risk.\",\n ],\n commands: [\n {\n label: \"Trust a CA\",\n shell: \"pg-explain run --sslmode verify-full --sslrootcert <ca.pem> ...\",\n },\n ],\n },\n docsUrl: `${DOCS}/libpq-ssl.html`,\n },\n\n PGX_CONN_TIMEOUT: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Connection timed out\",\n detail: \"The connect handshake did not complete within the connect deadline.\",\n cause: \"High network latency, an overloaded server, or a firewall silently dropping packets.\",\n remediation: {\n summary: \"Raise the connect budget and investigate the network path.\",\n commands: [\n { label: \"Increase connect timeout\", shell: \"pg-explain run --connect-timeout 30s ...\" },\n ],\n },\n docsUrl: `${DOCS}/libpq-connect.html`,\n },\n\n PGX_PERMISSION_DENIED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Permission denied\",\n detail: \"The connecting role lacks a privilege the query needs.\",\n cause:\n \"EXPLAIN must plan the query, which requires SELECT (and any referenced privileges) on the relations.\",\n remediation: {\n summary: \"Grant the missing privilege, or connect with a role that already has it.\",\n commands: [\n { label: \"Grant SELECT (run as owner)\", sql: \"GRANT SELECT ON <table> TO <role>;\" },\n ],\n },\n docsUrl: `${DOCS}/sql-grant.html`,\n },\n\n PGX_RELATION_NOT_FOUND: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Relation does not exist\",\n detail: \"A table or view referenced by the query was not found.\",\n cause: \"The name is misspelled, or it lives in a schema that is not on the search_path.\",\n remediation: {\n summary: \"Schema-qualify the relation or set the search_path.\",\n steps: [\"Check spelling and the schema.\", \"List tables with `\\\\dt` in psql.\"],\n commands: [{ label: \"Set the search path\", sql: \"SET search_path = <schema>, public;\" }],\n },\n },\n\n PGX_STATEMENT_TIMEOUT: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Statement timeout reached\",\n detail: \"statement_timeout fired while EXPLAIN ANALYZE was executing the query.\",\n cause: \"The query genuinely takes longer than the configured statement_timeout to run.\",\n remediation: {\n summary: \"Raise the timeout, or avoid executing the query at all.\",\n steps: [\n \"Raise the per-run statement timeout.\",\n \"Or get an estimate-only plan that never executes (drop --analyze).\",\n \"Or reduce measurement overhead with --timing off.\",\n ],\n commands: [\n { label: \"Raise the timeout\", shell: \"pg-explain run --statement-timeout 60s ...\" },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-client.html#GUC-STATEMENT-TIMEOUT`,\n },\n\n PGX_LOCK_TIMEOUT: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Lock timeout reached\",\n detail: \"lock_timeout elapsed while waiting to acquire a lock on a relation.\",\n cause: \"Another transaction holds a conflicting lock on a relation the query touches.\",\n remediation: {\n summary: \"Raise the lock timeout, identify the blocker, or retry off-peak.\",\n commands: [\n { label: \"Raise the lock timeout\", shell: \"pg-explain run --lock-timeout 30s ...\" },\n {\n label: \"Find blockers\",\n sql: \"SELECT * FROM pg_locks l JOIN pg_stat_activity a USING (pid) WHERE NOT l.granted;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-client.html#GUC-LOCK-TIMEOUT`,\n },\n\n PGX_QUERY_CANCELED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Query was canceled\",\n detail: \"The query was canceled by an administrator or a signal before completing.\",\n cause:\n \"An admin pg_cancel_backend call, a resource group, or a pool limit canceled the statement.\",\n remediation: {\n summary: \"Re-run the command; if it recurs, check for admin cancellation or pool limits.\",\n },\n },\n\n PGX_UNSUPPORTED_PG_VERSION: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"EXPLAIN option not supported by this server\",\n detail: \"A requested EXPLAIN option requires a newer PostgreSQL major version.\",\n cause:\n \"Options are version-gated (e.g. SETTINGS≥12, WAL≥13, GENERIC_PLAN≥16, SERIALIZE/MEMORY≥17).\",\n remediation: {\n summary:\n \"Drop the unsupported option, target a newer server, or let pg-explain auto-omit it.\",\n commands: [{ label: \"Auto-omit unsupported options\", shell: \"pg-explain run --compat ...\" }],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_INVALID_EXPLAIN_OPTION: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"Invalid EXPLAIN option combination\",\n detail: \"The server rejected an EXPLAIN option or a mutually-exclusive combination.\",\n cause:\n \"Some options require ANALYZE (WAL, SERIALIZE, TIMING) and GENERIC_PLAN is incompatible with ANALYZE.\",\n remediation: {\n summary: \"Fix the option combination; see `pg-explain --help` for valid combinations.\",\n steps: [\n \"WAL/SERIALIZE/TIMING require --analyze.\",\n \"GENERIC_PLAN cannot be combined with --analyze.\",\n ],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_MALFORMED_JSON: {\n severity: \"error\",\n exit: ExitCode.Parse,\n title: \"Input is not valid JSON\",\n detail: \"The plan input could not be parsed as JSON.\",\n cause: \"The input was truncated when captured, or it is not EXPLAIN (FORMAT JSON) output.\",\n remediation: {\n summary: \"Validate the input and make sure it is FORMAT JSON output.\",\n commands: [{ label: \"Validate JSON\", shell: \"jq . plan.json\" }],\n },\n },\n\n PGX_UNEXPECTED_PLAN_SHAPE: {\n severity: \"error\",\n exit: ExitCode.Parse,\n title: \"Input is not an EXPLAIN plan\",\n detail: \"The JSON parsed but does not contain a recognizable EXPLAIN plan tree.\",\n cause: \"The 'Plan' node is missing — this may be query result rows rather than a plan.\",\n remediation: {\n summary: \"Regenerate the plan with FORMAT JSON and pipe that in.\",\n commands: [\n { label: \"Capture a plan\", sql: \"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) <your query>;\" },\n ],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_EMPTY_INPUT: {\n severity: \"error\",\n exit: ExitCode.Input,\n title: \"No plan input received\",\n detail: \"stdin and the named file were both empty.\",\n cause: \"No plan was piped in and no query/file was provided.\",\n remediation: {\n summary: \"Pipe a plan, or provide SQL to run.\",\n commands: [\n { label: \"Analyze a saved plan\", shell: \"pg-explain < plan.json\" },\n { label: \"Or run a query\", shell: 'pg-explain run --query \"<sql>\" --dsn <dsn>' },\n ],\n },\n },\n\n PGX_NON_SELECT_REFUSED: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"Refusing to ANALYZE a data-modifying statement\",\n detail: \"EXPLAIN ANALYZE executes the statement, and this one would modify data.\",\n cause:\n \"INSERT/UPDATE/DELETE/MERGE/DDL run for real under ANALYZE; running it could change your data.\",\n remediation: {\n summary:\n \"Use --force to run it inside an automatically rolled-back transaction, or drop --analyze.\",\n steps: [\n \"With --force, pg-explain wraps it as `BEGIN; <stmt>; ROLLBACK;` so nothing is committed.\",\n \"Without --analyze you get an estimate-only plan that never executes.\",\n ],\n commands: [\n {\n label: \"Run safely (auto-rollback)\",\n shell: \"pg-explain run --force --file mutation.sql --dsn <dsn>\",\n },\n ],\n },\n },\n\n PGX_MULTIPLE_STATEMENTS: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"Multiple SQL statements found\",\n detail: \"The input contains more than one statement; pg-explain analyzes one at a time.\",\n cause: \"A .sql file or --query string contained several semicolon-separated statements.\",\n remediation: {\n summary: \"Select one statement, or split them into separate invocations.\",\n commands: [\n {\n label: \"Pick the Nth statement (1-based)\",\n shell: \"pg-explain run --statement 2 --file queries.sql --dsn <dsn>\",\n },\n ],\n },\n },\n\n PGX_COST_ONLY_PLAN: {\n severity: \"info\",\n exit: ExitCode.Success,\n title: \"Cost-only plan — estimate-vs-actual checks unavailable\",\n detail: \"This plan has cost estimates but no actual row/time data.\",\n cause: \"It was produced by plain EXPLAIN (without ANALYZE), so runtime behavior is unknown.\",\n remediation: {\n summary: \"Re-run with ANALYZE to unlock estimate-vs-actual, timing, and spill findings.\",\n commands: [\n { label: \"Capture actuals\", sql: \"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) <query>;\" },\n ],\n },\n docsUrl: `${DOCS}/using-explain.html#USING-EXPLAIN-ANALYZE`,\n },\n\n PGX_NO_BUFFERS: {\n severity: \"info\",\n exit: ExitCode.Success,\n title: \"No BUFFERS data — cache/I/O analysis skipped\",\n detail: \"Buffer counters are absent, so cache-hit ratio and I/O findings cannot be computed.\",\n cause: \"The plan was captured without BUFFERS.\",\n remediation: {\n summary: \"Add BUFFERS to surface shared/temp block usage and the cache-hit ratio.\",\n commands: [\n { label: \"Capture buffers\", sql: \"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) <query>;\" },\n ],\n },\n },\n\n PGX_EMPTY_PLAN: {\n severity: \"info\",\n exit: ExitCode.Success,\n title: \"Nothing to analyze\",\n detail: \"The plan has no scans or joins to evaluate (e.g. a bare Result node).\",\n cause: \"The query is trivial and has no tuning surface.\",\n remediation: { summary: \"Confirm this is the query you intended to profile.\" },\n },\n\n PGX_PG_DRIVER_MISSING: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"The 'pg' driver is not installed\",\n detail: \"The run command needs the PostgreSQL driver, which is an optional dependency.\",\n cause:\n \"pgexplain ships 'pg' as optional so plan-only use stays dependency-free; it isn't installed here.\",\n remediation: {\n summary:\n \"Install the pg driver, then re-run. (Plan-only analysis from a file/stdin needs no driver.)\",\n commands: [\n { label: \"with pnpm\", shell: \"pnpm add pg\" },\n { label: \"with npm\", shell: \"npm install pg\" },\n ],\n },\n },\n\n PGX_QUERY_FAILED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"The query could not be planned or executed\",\n detail: \"PostgreSQL returned an error while running EXPLAIN.\",\n cause:\n \"The statement has a syntax error, references something invalid, or hit a server-side limit.\",\n remediation: {\n summary:\n \"Read the server message below, fix the statement, and re-run. Test it in psql first if unsure.\",\n commands: [{ label: \"Try it directly\", shell: 'psql \"<dsn>\" -c \"EXPLAIN <your statement>\"' }],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_INTERNAL: {\n severity: \"error\",\n exit: ExitCode.Internal,\n title: \"pg-explain hit an unexpected error\",\n detail: \"This is a bug in pg-explain, not in your query or plan.\",\n cause: \"An unhandled condition was reached.\",\n remediation: {\n summary: \"Re-run with --debug for a credential-scrubbed stack trace, then file an issue.\",\n commands: [\n { label: \"Show the trace\", shell: \"pg-explain --debug ...\" },\n { label: \"Report your version\", shell: \"pg-explain --version\" },\n ],\n },\n },\n} satisfies Record<string, OpSpec>;\n\nexport type OpCode = keyof typeof CATALOG;\n\n/** Every operational code, for iteration (docs generation, completeness tests). */\nexport const OP_CODES = Object.keys(CATALOG) as OpCode[];\n\ninterface OpOverrides {\n /** Replace the default detail with situation-specific text (will be credential-scrubbed by the caller). */\n detail?: string;\n meta?: Diagnostic[\"meta\"];\n location?: DiagnosticLocation;\n}\n\n/** Build the Diagnostic for an operational code (used for info-level, non-fatal notices). */\nexport function opDiagnostic(code: OpCode, overrides: OpOverrides = {}): Diagnostic {\n const spec: OpSpec = CATALOG[code];\n const diag: Diagnostic = {\n code,\n domain: \"operational\",\n severity: spec.severity,\n title: spec.title,\n detail: overrides.detail ?? spec.detail,\n cause: spec.cause,\n remediation: spec.remediation,\n };\n if (spec.docsUrl) diag.docsUrl = spec.docsUrl;\n if (overrides.location) diag.location = overrides.location;\n if (overrides.meta) diag.meta = overrides.meta;\n return diag;\n}\n\n/** Build a throwable AppError for an operational code, with the correct exit code. */\nexport function opError(code: OpCode, overrides: OpOverrides = {}, cause?: unknown): AppError {\n return new AppError(opDiagnostic(code, overrides), CATALOG[code].exit, cause);\n}\n\nexport function exitCodeFor(code: OpCode): ExitCode {\n return CATALOG[code].exit;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Severity, Thresholds } from \"./core/model.ts\";\nimport { opError } from \"./diagnostics/catalog.ts\";\n\nexport interface RuleConfig {\n enabled?: boolean;\n severity?: Severity;\n}\n\nexport interface PgExplainConfig {\n thresholds: Thresholds;\n /** Per-rule enable/disable and severity overrides, keyed by rule id. */\n rules: Record<string, RuleConfig>;\n}\n\nexport const DEFAULT_THRESHOLDS: Thresholds = {\n seqScanRows: 100_000,\n nestedLoopOuterRows: 10_000,\n filterDiscardRatio: 0.9,\n filterRemovedAbs: 10_000,\n misestimateFactor: 10,\n heapFetchRatio: 0.1,\n heapFetchAbs: 1_000,\n correlatedLoops: 1_000,\n jitPct: 25,\n triggerPct: 10,\n lowCacheHitRatio: 0.9,\n};\n\nexport const DEFAULT_CONFIG: PgExplainConfig = {\n thresholds: { ...DEFAULT_THRESHOLDS },\n rules: {},\n};\n\nconst CONFIG_FILES = [\".pgexplainrc.json\", \".pgexplainrc\"];\n\n/** A partial config as it appears in a config file (all fields optional). */\ninterface PartialConfig {\n thresholds?: Partial<Thresholds>;\n rules?: Record<string, RuleConfig>;\n}\n\nfunction merge(partial: PartialConfig): PgExplainConfig {\n return {\n thresholds: { ...DEFAULT_THRESHOLDS, ...(partial.thresholds ?? {}) },\n rules: { ...(partial.rules ?? {}) },\n };\n}\n\nasync function readJson(path: string): Promise<unknown> {\n let text: string;\n try {\n text = await readFile(path, \"utf8\");\n } catch (err) {\n throw opError(\n \"PGX_EMPTY_INPUT\",\n {\n detail: `Could not read config '${path}': ${err instanceof Error ? err.message : String(err)}`,\n },\n err,\n );\n }\n try {\n return JSON.parse(text);\n } catch (err) {\n throw opError(\n \"PGX_MALFORMED_JSON\",\n {\n detail: `Config '${path}' is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n },\n err,\n );\n }\n}\n\n/**\n * Load config: an explicit --config path, else a `.pgexplainrc[.json]` or a\n * `pgExplain` key in package.json in cwd. Missing config is fine (returns defaults);\n * an unreadable/invalid explicit path is an actionable error.\n */\nexport async function loadConfig(\n explicitPath: string | undefined,\n cwd = process.cwd(),\n): Promise<PgExplainConfig> {\n if (explicitPath) return merge((await readJson(explicitPath)) as PartialConfig);\n\n for (const name of CONFIG_FILES) {\n try {\n const text = await readFile(join(cwd, name), \"utf8\");\n return merge(JSON.parse(text) as PartialConfig);\n } catch {\n // not present / unreadable — try the next source\n }\n }\n\n try {\n const pkg = JSON.parse(await readFile(join(cwd, \"package.json\"), \"utf8\")) as {\n pgExplain?: PartialConfig;\n };\n if (pkg.pgExplain) return merge(pkg.pgExplain);\n } catch {\n // no package.json or no key — fall through to defaults\n }\n\n return { ...DEFAULT_CONFIG, thresholds: { ...DEFAULT_THRESHOLDS }, rules: {} };\n}\n","import { z } from \"zod\";\n\n/**\n * Version-tolerant validation for EXPLAIN (FORMAT JSON) output.\n *\n * We only assert the *shape* we depend on (\"Node Type\" + recursive \"Plans\"); every\n * other field is accepted and preserved via looseObject so plans from PG 14 → 18\n * validate identically. Field access happens against the original parsed JSON (the\n * `raw` node), so unknown/new fields are never lost.\n */\nconst PlanNodeSchema = z.looseObject({\n \"Node Type\": z.string(),\n get Plans() {\n return z.array(PlanNodeSchema).optional();\n },\n});\n\nconst StatementSchema = z.looseObject({\n Plan: PlanNodeSchema,\n \"Planning Time\": z.number().optional(),\n \"Execution Time\": z.number().optional(),\n Triggers: z.array(z.looseObject({})).optional(),\n JIT: z.looseObject({}).optional(),\n Settings: z.record(z.string(), z.unknown()).optional(),\n});\n\n/** EXPLAIN FORMAT JSON is an array of statements (usually one). */\nexport const ExplainOutputSchema = z.array(StatementSchema).min(1);\n\nexport type ExplainOutput = z.infer<typeof ExplainOutputSchema>;\nexport type ExplainStatement = z.infer<typeof StatementSchema>;\n","import { opError } from \"../diagnostics/catalog.ts\";\nimport type { JitInfo, PlanNode, PlanTree, RawPlan, TriggerInfo } from \"./model.ts\";\nimport { ExplainOutputSchema } from \"./schema.ts\";\n\n// ── safe field readers ────────────────────────────────────────────────────────\n\nfunction num(raw: RawPlan, key: string): number | undefined {\n const v = raw[key];\n return typeof v === \"number\" ? v : undefined;\n}\n\nfunction str(raw: RawPlan, key: string): string | undefined {\n const v = raw[key];\n return typeof v === \"string\" ? v : undefined;\n}\n\nfunction strArray(raw: RawPlan, key: string): string[] | undefined {\n const v = raw[key];\n if (Array.isArray(v) && v.every((x) => typeof x === \"string\")) return v as string[];\n if (typeof v === \"string\") return [v];\n return undefined;\n}\n\n// ── JSON parse with line/column for actionable malformed-input errors ─────────\n\nfunction parseJsonWithLocation(input: string): unknown {\n try {\n return JSON.parse(input);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n let line: number | undefined;\n let col: number | undefined;\n\n const lc = message.match(/line (\\d+) column (\\d+)/i);\n if (lc?.[1] && lc[2]) {\n line = Number(lc[1]);\n col = Number(lc[2]);\n } else {\n const pos = message.match(/position (\\d+)/i);\n if (pos?.[1]) {\n const offset = Number(pos[1]);\n const before = input.slice(0, offset);\n line = before.split(\"\\n\").length;\n col = offset - before.lastIndexOf(\"\\n\");\n }\n }\n\n const where = line && col ? ` (line ${line}, col ${col})` : \"\";\n throw opError(\n \"PGX_MALFORMED_JSON\",\n {\n detail: `The plan input could not be parsed as JSON${where}: ${message}`,\n location: line && col ? { kind: \"input\", line, col } : { kind: \"input\" },\n },\n err,\n );\n }\n}\n\n// ── normalization ─────────────────────────────────────────────────────────────\n\nfunction normalizeNode(raw: RawPlan, nextId: () => number): PlanNode {\n const node: PlanNode = {\n id: nextId(),\n nodeType: raw[\"Node Type\"],\n planRows: num(raw, \"Plan Rows\") ?? 0,\n children: [],\n metrics: {},\n raw,\n };\n\n assign(node, {\n parentRelationship: str(raw, \"Parent Relationship\"),\n subplanName: str(raw, \"Subplan Name\"),\n relationName: str(raw, \"Relation Name\"),\n schema: str(raw, \"Schema\"),\n alias: str(raw, \"Alias\"),\n indexName: str(raw, \"Index Name\"),\n planWidth: num(raw, \"Plan Width\"),\n startupCost: num(raw, \"Startup Cost\"),\n totalCost: num(raw, \"Total Cost\"),\n actualRows: num(raw, \"Actual Rows\"),\n actualLoops: num(raw, \"Actual Loops\"),\n actualStartupTime: num(raw, \"Actual Startup Time\"),\n actualTotalTime: num(raw, \"Actual Total Time\"),\n filter: str(raw, \"Filter\"),\n rowsRemovedByFilter: num(raw, \"Rows Removed by Filter\"),\n indexCond: str(raw, \"Index Cond\"),\n recheckCond: str(raw, \"Recheck Cond\"),\n rowsRemovedByIndexRecheck: num(raw, \"Rows Removed by Index Recheck\"),\n heapFetches: num(raw, \"Heap Fetches\"),\n hashCond: str(raw, \"Hash Cond\"),\n joinType: str(raw, \"Join Type\"),\n joinFilter: str(raw, \"Join Filter\"),\n rowsRemovedByJoinFilter: num(raw, \"Rows Removed by Join Filter\"),\n output: strArray(raw, \"Output\"),\n sortMethod: str(raw, \"Sort Method\"),\n sortSpaceType: str(raw, \"Sort Space Type\"),\n sortSpaceUsed: num(raw, \"Sort Space Used\"),\n sortKey: strArray(raw, \"Sort Key\"),\n hashBuckets: num(raw, \"Hash Buckets\"),\n originalHashBuckets: num(raw, \"Original Hash Buckets\"),\n hashBatches: num(raw, \"Hash Batches\"),\n originalHashBatches: num(raw, \"Original Hash Batches\"),\n peakMemoryUsage: num(raw, \"Peak Memory Usage\"),\n diskUsage: num(raw, \"Disk Usage\"),\n exactHeapBlocks: num(raw, \"Exact Heap Blocks\"),\n lossyHeapBlocks: num(raw, \"Lossy Heap Blocks\"),\n sharedHitBlocks: num(raw, \"Shared Hit Blocks\"),\n sharedReadBlocks: num(raw, \"Shared Read Blocks\"),\n sharedDirtiedBlocks: num(raw, \"Shared Dirtied Blocks\"),\n sharedWrittenBlocks: num(raw, \"Shared Written Blocks\"),\n localHitBlocks: num(raw, \"Local Hit Blocks\"),\n localReadBlocks: num(raw, \"Local Read Blocks\"),\n tempReadBlocks: num(raw, \"Temp Read Blocks\"),\n tempWrittenBlocks: num(raw, \"Temp Written Blocks\"),\n ioReadTime: num(raw, \"I/O Read Time\"),\n ioWriteTime: num(raw, \"I/O Write Time\"),\n workersPlanned: num(raw, \"Workers Planned\"),\n workersLaunched: num(raw, \"Workers Launched\"),\n });\n\n const childPlans = raw.Plans;\n if (Array.isArray(childPlans)) {\n for (const child of childPlans) {\n node.children.push(normalizeNode(child, nextId));\n }\n }\n return node;\n}\n\n/** Copy only the defined keys, so optional fields stay absent (not `undefined`). */\nfunction assign<T extends object>(target: T, fields: Partial<T>): void {\n for (const [k, v] of Object.entries(fields)) {\n if (v !== undefined) (target as Record<string, unknown>)[k] = v;\n }\n}\n\nfunction parseTriggers(raw: unknown): TriggerInfo[] {\n if (!Array.isArray(raw)) return [];\n return raw.map((t) => {\n const r = t as RawPlan;\n const info: TriggerInfo = {};\n assign(info, {\n name: str(r, \"Trigger Name\"),\n constraintName: str(r, \"Constraint Name\"),\n relation: str(r, \"Relation\"),\n calls: num(r, \"Calls\"),\n time: num(r, \"Time\"),\n });\n return info;\n });\n}\n\nfunction parseJit(raw: unknown): JitInfo | undefined {\n if (!raw || typeof raw !== \"object\") return undefined;\n const r = raw as RawPlan;\n const timing = r.Timing as RawPlan | undefined;\n const jit: JitInfo = {};\n const functions = num(r, \"Functions\");\n if (functions !== undefined) jit.functions = functions;\n if (timing && typeof timing === \"object\") {\n jit.timing = {\n total: num(timing, \"Total\"),\n generation: num(timing, \"Generation\"),\n inlining: num(timing, \"Inlining\"),\n optimization: num(timing, \"Optimization\"),\n emission: num(timing, \"Emission\"),\n };\n }\n return jit;\n}\n\n/**\n * Parse EXPLAIN (FORMAT JSON) text into one PlanTree per statement.\n * Accepts the standard `[{ \"Plan\": … }]`, a bare statement object, or a bare plan node.\n * Throws AppError(PGX_MALFORMED_JSON | PGX_UNEXPECTED_PLAN_SHAPE) with a location.\n */\nexport function parseExplainJson(input: string): PlanTree[] {\n const json = parseJsonWithLocation(input);\n\n // Normalize the accepted shapes into the canonical array-of-statements.\n let candidate: unknown = json;\n if (json && typeof json === \"object\" && !Array.isArray(json)) {\n const obj = json as Record<string, unknown>;\n candidate = \"Plan\" in obj ? [obj] : \"Node Type\" in obj ? [{ Plan: obj }] : json;\n }\n\n const result = ExplainOutputSchema.safeParse(candidate);\n if (!result.success) {\n throw opError(\"PGX_UNEXPECTED_PLAN_SHAPE\", {\n detail: `The JSON is valid but is not an EXPLAIN plan: ${result.error.issues[0]?.message ?? \"missing 'Plan' node\"}.`,\n location: { kind: \"input\" },\n });\n }\n\n return result.data.map((stmt): PlanTree => {\n let id = 0;\n const root = normalizeNode(stmt.Plan as RawPlan, () => id++);\n const hasAnalyze = root.actualLoops !== undefined || stmt[\"Execution Time\"] !== undefined;\n const hasBuffers = root.sharedHitBlocks !== undefined || root.sharedReadBlocks !== undefined;\n\n const tree: PlanTree = {\n root,\n triggers: parseTriggers(stmt.Triggers),\n hasAnalyze,\n hasBuffers,\n raw: stmt.Plan as RawPlan,\n };\n if (stmt[\"Planning Time\"] !== undefined) tree.planningTime = stmt[\"Planning Time\"];\n if (stmt[\"Execution Time\"] !== undefined) tree.executionTime = stmt[\"Execution Time\"];\n const jit = parseJit(stmt.JIT);\n if (jit) tree.jit = jit;\n if (stmt.Settings) tree.settings = stmt.Settings as Record<string, string>;\n return tree;\n });\n}\n\n/** Depth-first pre-order walk (root first). Used by metrics and the advisor. */\nexport function walk(node: PlanNode, visit: (n: PlanNode) => void): void {\n visit(node);\n for (const child of node.children) walk(child, visit);\n}\n\n/** Flatten a tree to an array in pre-order. */\nexport function flatten(node: PlanNode): PlanNode[] {\n const out: PlanNode[] = [];\n walk(node, (n) => out.push(n));\n return out;\n}\n","import type { PlanNode, PlanTree } from \"./model.ts\";\nimport { flatten, walk } from \"./parse.ts\";\n\n/**\n * Fill `node.metrics` for every node. All row/time figures are PER-LOOP corrected:\n * Postgres reports \"Actual Rows\"/\"Actual Total Time\" as the average of a single loop,\n * so the true total is `× \"Actual Loops\"`. Buffer counters are already cumulative and\n * are NOT multiplied. No-ops cleanly on cost-only plans (leaves metrics empty).\n */\nexport function computeMetrics(tree: PlanTree): void {\n // Pass 1 — per-node quantities that don't depend on siblings/children.\n walk(tree.root, (node) => {\n const { actualRows, actualLoops, actualTotalTime } = node;\n\n if (actualRows !== undefined && actualLoops !== undefined) {\n node.metrics.totalRows = actualRows * actualLoops;\n }\n if (actualTotalTime !== undefined && actualLoops !== undefined) {\n node.metrics.inclusiveMs = actualTotalTime * actualLoops;\n }\n\n // Estimate vs actual (only meaningful with actuals).\n if (node.metrics.totalRows !== undefined) {\n const est = Math.max(node.planRows, 1);\n const act = Math.max(node.metrics.totalRows, 1);\n node.metrics.estimateFactor = est >= act ? est / act : act / est;\n node.metrics.estimateDirection =\n node.planRows > node.metrics.totalRows\n ? \"over\"\n : node.metrics.totalRows > node.planRows\n ? \"under\"\n : \"accurate\";\n }\n\n // Cache-hit ratio from shared buffers (cumulative — no ×loops).\n const hit = node.sharedHitBlocks ?? 0;\n const read = node.sharedReadBlocks ?? 0;\n node.metrics.cacheHitRatio = hit + read > 0 ? hit / (hit + read) : null;\n\n // Filter discard ratio (per-loop corrected).\n if (node.rowsRemovedByFilter !== undefined && actualLoops !== undefined) {\n const removed = node.rowsRemovedByFilter * actualLoops;\n const kept = node.metrics.totalRows ?? 0;\n const denom = removed + kept;\n if (denom > 0) node.metrics.filterDiscardRatio = removed / denom;\n }\n\n // Bitmap lossy ratio.\n if (node.lossyHeapBlocks !== undefined) {\n const lossy = node.lossyHeapBlocks;\n const exact = node.exactHeapBlocks ?? 0;\n const denom = lossy + exact;\n if (denom > 0) node.metrics.lossyRatio = lossy / denom;\n }\n });\n\n // Pass 2 — self time = inclusive − Σ(children inclusive), clamped ≥ 0.\n walk(tree.root, (node) => {\n if (node.metrics.inclusiveMs === undefined) return;\n let childrenMs = 0;\n for (const child of node.children) childrenMs += child.metrics.inclusiveMs ?? 0;\n node.metrics.selfMs = Math.max(node.metrics.inclusiveMs - childrenMs, 0);\n });\n\n // Pass 3 — % of total execution time.\n const totalMs = executionMs(tree);\n if (totalMs && totalMs > 0) {\n walk(tree.root, (node) => {\n if (node.metrics.selfMs !== undefined) {\n node.metrics.pctOfTotal = (100 * node.metrics.selfMs) / totalMs;\n }\n });\n }\n}\n\n/** Total execution time in ms: prefer the reported value, else the root's inclusive time. */\nexport function executionMs(tree: PlanTree): number | undefined {\n return tree.executionTime ?? tree.root.metrics.inclusiveMs;\n}\n\n/** Top N nodes by self time (the real bottlenecks), descending. */\nexport function bottlenecks(tree: PlanTree, n = 5): PlanNode[] {\n return flatten(tree.root)\n .filter((node) => node.metrics.selfMs !== undefined)\n .sort((a, b) => (b.metrics.selfMs ?? 0) - (a.metrics.selfMs ?? 0))\n .slice(0, n);\n}\n\n/** A short human label for a node, e.g. \"Seq Scan on orders\". */\nexport function nodeLabel(node: PlanNode): string {\n let label = node.nodeType;\n if (node.indexName && node.relationName)\n label += ` using ${node.indexName} on ${node.relationName}`;\n else if (node.relationName) label += ` on ${node.relationName}`;\n if (node.alias && node.alias !== node.relationName) label += ` (${node.alias})`;\n return label;\n}\n","/** Locale-aware, unit-consistent formatting shared by every renderer. */\n\n/** Postgres default block size; buffer counters are in blocks. */\nconst BLOCK_BYTES = 8192;\n\nexport function fmtInt(n: number): string {\n return Math.round(n).toLocaleString(\"en-US\");\n}\n\n/** Times are milliseconds throughout. */\nexport function fmtMs(ms: number): string {\n if (ms < 1) return `${ms.toFixed(3)} ms`;\n if (ms < 1000) return `${ms.toFixed(1)} ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(2)} s`;\n const min = Math.floor(ms / 60_000);\n const sec = ((ms % 60_000) / 1000).toFixed(0);\n return `${min}m ${sec}s`;\n}\n\nexport function fmtPct(fraction0to100: number): string {\n return `${fraction0to100.toFixed(1)}%`;\n}\n\n/** Postgres reports sort/hash space in KiB. */\nexport function fmtKiB(kib: number): string {\n return fmtBytes(kib * 1024);\n}\n\n/** Buffer counters are in 8 KiB blocks. */\nexport function fmtBlocks(blocks: number): string {\n return `${fmtInt(blocks)} blk (${fmtBytes(blocks * BLOCK_BYTES)})`;\n}\n\nexport function fmtBytes(bytes: number): string {\n const units = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\"];\n let v = bytes;\n let i = 0;\n while (v >= 1024 && i < units.length - 1) {\n v /= 1024;\n i++;\n }\n const s = i === 0 ? String(Math.round(v)) : v.toFixed(1);\n return `${s} ${units[i]}`;\n}\n\n/** Round a KiB value up to the next whole MiB (work_mem recommendations). */\nexport function roundUpMiB(kib: number, stepMiB = 4): string {\n const mib = Math.ceil(kib / 1024 / stepMiB) * stepMiB;\n return `${Math.max(mib, stepMiB)}MB`;\n}\n\nexport interface TreeGlyphs {\n branch: string;\n last: string;\n vert: string;\n space: string;\n}\n\nexport const UNICODE_TREE: TreeGlyphs = { branch: \"├─ \", last: \"└─ \", vert: \"│ \", space: \" \" };\nexport const ASCII_TREE: TreeGlyphs = { branch: \"+- \", last: \"`- \", vert: \"| \", space: \" \" };\n","import type {\n AnalysisContext,\n Diagnostic,\n DiagnosticLocation,\n PlanNode,\n Remediation,\n Rule,\n Severity,\n} from \"../../core/model.ts\";\n\nexport const DOCS = \"https://www.postgresql.org/docs/current\";\n\nexport function locationOf(node: PlanNode): DiagnosticLocation {\n const loc: DiagnosticLocation = { kind: \"node\", nodeId: node.id, nodeType: node.nodeType };\n if (node.relationName) loc.relation = node.relationName;\n return loc;\n}\n\n/**\n * Build a plan finding. The Diagnostic `code` is the rule id (a PGX_* code), severity\n * is resolved through config overrides, and the location points at the offending node.\n * Every rule goes through here so all findings carry remediation + a node location.\n */\nexport function makeFinding(\n rule: Rule,\n ctx: AnalysisContext,\n node: PlanNode,\n parts: {\n title: string;\n detail: string;\n cause: string;\n remediation: Remediation;\n docsUrl?: string;\n meta?: Diagnostic[\"meta\"];\n /** Per-finding severity fallback (e.g. underestimate→warn); config still wins. */\n severity?: Severity;\n },\n): Diagnostic {\n const d: Diagnostic = {\n code: rule.id,\n domain: \"plan\",\n severity: ctx.severityOf(rule.id, parts.severity ?? rule.defaultSeverity),\n title: parts.title,\n detail: parts.detail,\n cause: parts.cause,\n remediation: parts.remediation,\n location: locationOf(node),\n };\n if (parts.docsUrl) d.docsUrl = parts.docsUrl;\n if (parts.meta) d.meta = parts.meta;\n return d;\n}\n\n/** First child is the outer (driving) side of a join. */\nexport function outerChild(node: PlanNode): PlanNode | undefined {\n return node.children[0];\n}\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Bitmap heap scan whose bitmap exceeded work_mem and degraded to page granularity.\n * When the per-tuple bitmap won't fit, Postgres stores only the heap *page* numbers\n * (\"lossy\" blocks) and re-checks the index condition against every tuple on those\n * pages, reading more heap and re-evaluating the predicate. Raising work_mem keeps the\n * bitmap exact; a more selective index also shrinks it.\n */\nexport const bitmapLossy: Rule = {\n id: \"PGX_BITMAP_LOSSY\",\n title: \"Lossy bitmap heap scan\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Bitmap Heap Scan\") return [];\n\n const lossy = node.lossyHeapBlocks ?? 0;\n if (lossy <= 0) return [];\n\n const exact = node.exactHeapBlocks ?? 0;\n const rel = node.relationName ?? \"the table\";\n const rechecked = node.rowsRemovedByIndexRecheck ?? 0;\n const recheckNote =\n rechecked > 0\n ? ` The recheck discarded ${fmtInt(rechecked)} extra rows that the lossy bitmap could not exclude.`\n : \"\";\n\n return [\n makeFinding(bitmapLossy, ctx, node, {\n title: `Lossy bitmap heap scan on ${rel} (${fmtInt(lossy)} lossy blocks)`,\n detail: `The bitmap for ${rel} held ${fmtInt(lossy)} lossy (page-granularity) blocks alongside ${fmtInt(\n exact,\n )} exact blocks, so Postgres re-checked the index condition against every tuple on the lossy pages.${recheckNote}`,\n cause:\n \"The exact (per-tuple) bitmap did not fit in work_mem, so Postgres fell back to storing whole heap pages and recheck the index condition while reading them — more heap I/O and CPU than an exact bitmap.\",\n remediation: {\n summary: `Raise work_mem for this session so the bitmap stays exact (no lossy blocks, no rechecks) on ${rel}; alternatively make the index condition more selective or add a composite index so the bitmap is smaller.`,\n steps: [\n \"Increase work_mem for the session, then re-run EXPLAIN (ANALYZE) and confirm Lossy Heap Blocks drops to 0.\",\n \"If raising work_mem is undesirable, make the index condition more selective (a more selective leading column or a composite index over the filtered columns) so fewer heap pages enter the bitmap.\",\n ],\n commands: [\n {\n label: \"Give this session more work_mem\",\n sql: \"SET work_mem = '<X>MB';\",\n },\n {\n label: \"Or shrink the bitmap with a more selective index\",\n sql: `CREATE INDEX ON ${rel} (<more selective / composite columns>);`,\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-WORK-MEM`,\n meta: { lossyBlocks: lossy, exactBlocks: exact },\n }),\n ];\n },\n};\n","import type { PlanNode, Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/** Measured rows if available, else the planner estimate. */\nfunction rowsOf(node: PlanNode): number {\n return node.metrics.totalRows ?? node.planRows;\n}\n\n/**\n * Nested Loop with no join predicate anywhere — neither a Join Filter on the loop\n * nor an Index Cond / Recheck Cond on the inner side. Every outer row is paired with\n * every inner row, so the result is the cross product (rows ≈ outer × inner). This is\n * almost always a forgotten ON / WHERE join condition; precision is kept high by\n * requiring both sides to actually produce rows.\n */\nexport const cartesianProduct: Rule = {\n id: \"PGX_CARTESIAN_PRODUCT\",\n title: \"Cartesian product (missing join condition)\",\n defaultSeverity: \"error\",\n check(node, ctx) {\n if (node.nodeType !== \"Nested Loop\") return [];\n if (node.joinFilter) return [];\n\n const inner = node.children[1];\n if (!inner) return [];\n // A join key on the inner side (index lookup) means there IS a predicate.\n if (inner.indexCond || inner.recheckCond) return [];\n\n const outer = node.children[0];\n if (!outer) return [];\n\n const outerRows = rowsOf(outer);\n const innerRows = rowsOf(inner);\n // Single-row sides are legitimately matched against everything (e.g. a LIMIT 1\n // or aggregate); a cross product is only meaningful when both sides are sets.\n if (outerRows <= 1 || innerRows <= 1) return [];\n\n const estimated = node.metrics.totalRows === undefined;\n const product = fmtInt(outerRows * innerRows);\n\n return [\n makeFinding(cartesianProduct, ctx, node, {\n title: `Cartesian product: Nested Loop with no join condition (~${product}${estimated ? \" est.\" : \"\"} rows)`,\n detail: `The Nested Loop has no Join Filter and the inner side has no Index Cond or Recheck Cond, so each of ${fmtInt(\n outerRows,\n )} outer rows is paired with every one of ${fmtInt(innerRows)} inner rows${\n estimated ? \" (estimated — run with ANALYZE for actuals)\" : \"\"\n }.`,\n cause:\n \"No predicate links the two relations, so Postgres can only emit the full cross product. This usually means an ON or WHERE join condition was omitted (e.g. a comma join across tables).\",\n remediation: {\n summary:\n \"Add the missing join condition linking the two tables on their key columns (e.g. ON a.id = b.a_id). If a cross product is truly intended, make it explicit with CROSS JOIN and bound it with a LIMIT or aggregation.\",\n steps: [\n \"Find the two relations feeding this Nested Loop in your query.\",\n \"Add an ON (or WHERE) clause matching their key columns so the loop becomes selective.\",\n \"If you really want every combination, write CROSS JOIN explicitly and cap the size with LIMIT or an aggregate.\",\n ],\n commands: [\n {\n label: \"Add the join predicate\",\n sql: \"SELECT ...\\nFROM <outer_table> a\\nJOIN <inner_table> b ON a.<key> = b.<key>;\",\n },\n {\n label: \"Or make the cross join explicit and bounded\",\n sql: \"SELECT ...\\nFROM <outer_table> a\\nCROSS JOIN <inner_table> b\\nLIMIT <n>;\",\n },\n ],\n },\n docsUrl: `${DOCS}/queries-table-expressions.html#QUERIES-JOIN`,\n meta: { outerRows: Math.round(outerRows), innerRows: Math.round(innerRows) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A correlated subquery surfaces as a SubPlan node whose `actualLoops` equals the\n * number of outer rows: the planner re-executes it once per row instead of running\n * it once. Above the loop threshold this dominates execution time. The fix is to\n * de-correlate it — rewrite as a JOIN/LATERAL or hoist into a CTE evaluated once.\n */\nexport const correlatedSubplan: Rule = {\n id: \"PGX_CORRELATED_SUBPLAN\",\n title: \"Correlated subplan re-executed per row\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n const isSubplan =\n node.parentRelationship === \"SubPlan\" || (node.subplanName?.startsWith(\"SubPlan\") ?? false);\n if (!isSubplan) return [];\n\n const loops = node.actualLoops ?? 0;\n if (loops <= ctx.thresholds.correlatedLoops) return [];\n\n const name = node.subplanName ?? \"the subplan\";\n\n return [\n makeFinding(correlatedSubplan, ctx, node, {\n title: `Correlated ${name} re-executed ${fmtInt(loops)} times`,\n detail: `${name} ran ${fmtInt(loops)} times — once per outer row — instead of being evaluated a single time.`,\n cause:\n \"The subquery references a column from the enclosing query, so the planner cannot pull it out of the per-row loop and re-runs the whole subplan for every outer row.\",\n remediation: {\n summary: `De-correlate the subquery: rewrite it as a JOIN or LATERAL join, or hoist it into a CTE/derived table evaluated once, then index the correlation key so the rewrite stays cheap.`,\n steps: [\n \"Identify the outer column the subquery references (the correlation key).\",\n \"For a scalar subquery in SELECT/WHERE, rewrite it as a LEFT JOIN to a grouped derived table, or a LATERAL join when it returns per-row results.\",\n \"For EXISTS/IN, prefer the semi-join form (EXISTS / = ANY) the planner can de-correlate into a single hash/merge join.\",\n \"Add an index on the correlation key so the resulting JOIN does not fall back to the same per-row cost.\",\n // Before (correlated, runs once per outer row):\n // SELECT o.id, (SELECT count(*) FROM events e WHERE e.order_id = o.id) AS n FROM orders o;\n // After (evaluated once, joined):\n // SELECT o.id, COALESCE(e.n, 0) AS n\n // FROM orders o\n // LEFT JOIN (SELECT order_id, count(*) AS n FROM events GROUP BY order_id) e\n // ON e.order_id = o.id;\n \"See the before/after sketch: SELECT (SELECT count(*) FROM events e WHERE e.order_id = o.id) becomes a LEFT JOIN to (SELECT order_id, count(*) FROM events GROUP BY order_id).\",\n ],\n commands: [\n {\n label: \"Index the correlation key so the de-correlated JOIN stays cheap\",\n sql: \"CREATE INDEX ON <subquery table> (<correlation key column>);\",\n },\n ],\n },\n docsUrl: `${DOCS}/queries-table-expressions.html#QUERIES-LATERAL`,\n meta: { loops },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Hint: an Index Scan that projects only a few columns and applies no residual\n * filter (the whole predicate lives in the Index Cond) MIGHT qualify for an\n * Index Only Scan if the index covers every selected column. We cannot see the\n * index definition from EXPLAIN, so this is low-confidence — phrased as a\n * suggestion and kept at `info`. Requires VERBOSE for the Output column list.\n */\nexport const couldBeIndexOnly: Rule = {\n id: \"PGX_COULD_BE_INDEX_ONLY\",\n title: \"Index scan may be eligible for index-only\",\n defaultSeverity: \"info\",\n check(node, ctx) {\n if (node.nodeType !== \"Index Scan\") return [];\n if (!node.indexName) return [];\n // A residual Filter means columns beyond the index are needed for the\n // predicate, so it cannot become index-only — skip those.\n if (node.filter) return [];\n // Need VERBOSE output to know which columns are projected.\n if (!node.output || node.output.length === 0) return [];\n // Only hint for a small, plausibly-coverable column set.\n if (node.output.length > 4) return [];\n\n const rel = node.relationName ?? \"the table\";\n const cols = node.output;\n const colList = cols.join(\", \");\n const includeCols = cols.join(\", \");\n\n return [\n makeFinding(couldBeIndexOnly, ctx, node, {\n title: `Index Scan using ${node.indexName} on ${rel} may be eligible for index-only`,\n detail: `This Index Scan projects only ${cols.length} column${\n cols.length === 1 ? \"\" : \"s\"\n } (${colList}) and applies no residual filter, so its predicate is fully resolved by ${node.indexName}. If that index also covers the selected columns, Postgres could use an Index Only Scan and skip the heap entirely.`,\n cause:\n \"An Index Scan still visits the table heap to fetch the projected columns. When every selected column is contained in the index (as a key or INCLUDE column) and the visibility map is current, Postgres can answer from the index alone (Index Only Scan).\",\n remediation: {\n summary: `Add the selected columns (${includeCols}) to ${node.indexName} as INCLUDE columns so it covers the query, then keep the visibility map current with VACUUM so Postgres can switch ${rel} to an Index Only Scan.`,\n steps: [\n \"Confirm which columns the index already covers (\\\\d <index> in psql) — this hint assumes VERBOSE Output and cannot read the index definition.\",\n \"If any projected column is missing, recreate the index with those columns as INCLUDE (non-key) columns.\",\n \"Run VACUUM so the visibility map is set; Index Only Scans fall back to heap fetches on pages not marked all-visible.\",\n ],\n commands: [\n {\n label: \"Create a covering index\",\n sql: `CREATE INDEX ON ${rel} (<key columns from the Index Cond>) INCLUDE (${includeCols});`,\n },\n {\n label: \"Keep the visibility map current\",\n sql: `VACUUM ${rel};`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-index-only-scans.html`,\n meta: { outputColumns: cols.length },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * An index/bitmap scan that still applies a residual Filter after the index lookup.\n * The Filter is evaluated on every heap row the index returned; folding those columns\n * into the index lets Postgres apply them as an Index Cond during traversal, skipping\n * the rows entirely. This is a hint (severity info): a non-sargable predicate cannot be\n * indexed, so the fix is phrased around making the filter index-friendly.\n */\nexport const filterCouldBeIndexCond: Rule = {\n id: \"PGX_FILTER_COULD_BE_INDEX_COND\",\n title: \"Filter could be an index condition\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n const indexed =\n node.nodeType === \"Index Scan\" ||\n node.nodeType === \"Index Only Scan\" ||\n node.nodeType === \"Bitmap Heap Scan\";\n if (!indexed) return [];\n if (!node.filter) return [];\n if (!node.indexCond && !node.recheckCond) return [];\n if ((node.rowsRemovedByFilter ?? 0) <= 0) return [];\n\n const rel = node.relationName ?? \"the table\";\n const cond = node.indexCond ?? node.recheckCond ?? \"\";\n const loops = node.actualLoops ?? 1;\n const removed = (node.rowsRemovedByFilter ?? 0) * loops;\n\n return [\n makeFinding(filterCouldBeIndexCond, ctx, node, {\n title: `Residual filter on ${rel} could be an index condition`,\n detail: `${node.nodeType} on ${rel} used the index for ${cond} but then applied Filter ${node.filter} to the fetched rows, discarding ${fmtInt(removed)} of them.`,\n cause: `The Filter columns are not part of the index, so Postgres must fetch each row the index matched and re-check the predicate in the executor instead of skipping non-matching entries during the index traversal.`,\n remediation: {\n summary: `Extend the index on ${rel} to include the Filter columns from ${node.filter} as trailing key columns, so the predicate is applied as an Index Cond during traversal instead of as a post-fetch Filter.`,\n steps: [\n `Confirm the Filter ${node.filter} is sargable — no functions or implicit casts wrapping the column.`,\n \"Append the filter columns after the existing key columns so the index still serves the original lookup.\",\n \"Re-run EXPLAIN (ANALYZE) and check the Filter moved into the Index Cond with no Rows Removed by Filter.\",\n ],\n commands: [\n {\n label: \"Extend the index with the filter columns\",\n sql: `CREATE INDEX ON ${rel} (<existing key columns>, <filter columns>);`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-multicolumn.html`,\n meta: { rowsRemovedByFilter: Math.round(removed) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt, fmtKiB, roundUpMiB } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A Hash node split its build side into multiple batches, meaning the hash table did\n * not fit in work_mem and spilled to disk. The ideal is a single batch; more batches\n * than originally planned (hashBatches > originalHashBatches) means Postgres also had\n * to re-partition at runtime after under-sizing the build side.\n */\nexport const hashSpillDisk: Rule = {\n id: \"PGX_HASH_SPILL_DISK\",\n title: \"Hash join spilled to disk\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Hash\") return [];\n\n const hashBatches = node.hashBatches ?? 1;\n if (hashBatches <= 1) return [];\n\n const originalHashBatches = node.originalHashBatches ?? hashBatches;\n const repartitioned = hashBatches > originalHashBatches;\n\n // Size work_mem to hold the whole build side (peak memory + what spilled) with headroom.\n const peakKiB = node.peakMemoryUsage ?? 0;\n const diskKiB = node.diskUsage ?? 0;\n const workMemRecommended = roundUpMiB((peakKiB + diskKiB) * 1.2);\n\n return [\n makeFinding(hashSpillDisk, ctx, node, {\n title: `Hash build side spilled to disk (${fmtInt(hashBatches)} batches)`,\n detail: `The hash table was split into ${fmtInt(hashBatches)} batches${\n repartitioned ? ` (up from ${fmtInt(originalHashBatches)} planned)` : \"\"\n }, so the build side did not fit in work_mem and overflowed to temporary files${\n diskKiB > 0 ? ` (${fmtKiB(diskKiB)} written to disk)` : \"\"\n }.`,\n cause: repartitioned\n ? \"Postgres had to add batches at runtime because the build side was larger than estimated — usually a row underestimate sized work_mem too small.\"\n : \"The build (hash) side was larger than work_mem, forcing the hash join to partition it across disk-backed batches.\",\n remediation: {\n summary: `Raise work_mem to about ${workMemRecommended} so the build side fits in a single batch, and make sure the SMALLER input is the hash/build side (a wrong build side usually comes from a row underestimate — fix the stats). Reducing build-side rows also avoids the spill.`,\n steps: [\n `Set work_mem high enough to hold the build side in one batch (~${workMemRecommended} here) at session or role scope, not globally — every sort/hash node can use work_mem, so a global bump can exhaust memory.`,\n \"Confirm the smaller relation is on the build (Hash) side; if Postgres chose the larger side, a row underestimate is likely — re-run ANALYZE or raise statistics targets so the planner picks the smaller build side.\",\n \"Alternatively, filter or aggregate the build side earlier so fewer rows need to be hashed.\",\n ],\n commands: [\n {\n label: \"Raise work_mem for this session\",\n sql: `SET work_mem = '${workMemRecommended}';`,\n },\n {\n label: \"Or set it for a specific role\",\n sql: `ALTER ROLE <role> SET work_mem = '${workMemRecommended}';`,\n },\n {\n label: \"Refresh planner statistics on the build-side table\",\n sql: \"ANALYZE <build_side_table>;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-WORK-MEM`,\n meta: { hashBatches, workMemRecommended },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A node reads many rows then throws most of them away via a post-read Filter. The\n * discarded rows were still fetched and examined, so the work is wasted. Pushing the\n * predicate into an index turns the Filter into an Index Cond, letting Postgres skip\n * the non-matching rows entirely instead of reading and rejecting them.\n */\nexport const highFilterDiscard: Rule = {\n id: \"PGX_HIGH_FILTER_DISCARD\",\n title: \"Filter discards most rows read\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n const ratio = node.metrics.filterDiscardRatio;\n if (ratio === undefined || ratio <= ctx.thresholds.filterDiscardRatio) return [];\n\n const removed = (node.rowsRemovedByFilter ?? 0) * (node.actualLoops ?? 1);\n if (removed <= ctx.thresholds.filterRemovedAbs) return [];\n\n const rel = node.relationName ?? \"the table\";\n const kept = node.metrics.totalRows ?? 0;\n const discardPct = ratio * 100;\n const filter = node.filter ?? \"the filter predicate\";\n\n return [\n makeFinding(highFilterDiscard, ctx, node, {\n title: `Filter on ${rel} discards ${fmtPct(discardPct)} of rows read`,\n detail: `Postgres read this node's rows then dropped ${fmtInt(removed)} of them (${fmtPct(\n discardPct,\n )}), keeping only ${fmtInt(kept)}, via the post-read filter ${filter}.`,\n cause: `The predicate ${filter} is evaluated as a Filter after the rows are fetched, so every discarded row was still read and examined — work no index condition narrowed.`,\n remediation: {\n summary: `Move ${filter} into an index on ${rel} so the predicate becomes an Index Cond instead of a post-read Filter, letting Postgres skip the non-matching rows. For a low-cardinality predicate, a partial index keyed on the discarded condition is smaller and faster.`,\n steps: [\n \"Identify the column(s) referenced by the filter above.\",\n \"Ensure the predicate is sargable (no function-wrapping or implicit casts on the indexed column).\",\n \"Use a plain index when the columns are selective across queries; use a partial index when the same constant predicate is always applied.\",\n ],\n commands: [\n {\n label: \"Index the filter columns\",\n sql: `CREATE INDEX ON ${rel} (<filter columns>);`,\n },\n {\n label: \"Or a partial index for a fixed low-cardinality predicate\",\n sql: `CREATE INDEX ON ${rel} (<filter columns>) WHERE <predicate>;`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-partial.html`,\n meta: { discardPct: Math.round(discardPct) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Index-only scan that still hit the heap. Each heap fetch means the visibility map\n * marked that page as not all-visible, so Postgres had to read the table row to check\n * visibility — defeating the index-only optimization. The usual cause is a table that\n * has not been vacuumed recently enough relative to its write rate.\n */\nexport const indexOnlyHeapFetches: Rule = {\n id: \"PGX_INDEX_ONLY_HEAP_FETCHES\",\n title: \"Index-only scan with heap fetches\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Index Only Scan\") return [];\n\n const heapFetches = node.heapFetches ?? 0;\n if (heapFetches <= 0) return [];\n\n const rows = Math.max(node.metrics.totalRows ?? 1, 1);\n const ratio = heapFetches / rows;\n if (ratio <= ctx.thresholds.heapFetchRatio && heapFetches <= ctx.thresholds.heapFetchAbs) {\n return [];\n }\n\n const rel = node.relationName ?? \"the table\";\n\n return [\n makeFinding(indexOnlyHeapFetches, ctx, node, {\n title: `Index-only scan on ${rel} did ${fmtInt(heapFetches)} heap fetches`,\n detail: `The index-only scan on ${rel} fell back to the heap ${fmtInt(heapFetches)} times for ${fmtInt(\n rows,\n )} rows produced. Each fetch is an extra table page read the index-only path was meant to avoid.`,\n cause: `Heap fetches happen when the visibility map does not mark the pages as all-visible, so Postgres must read the table row to confirm visibility. This usually means ${rel} has not been vacuumed recently enough for its write/update rate.`,\n remediation: {\n summary: `Run VACUUM (or VACUUM ANALYZE) on ${rel} to refresh the visibility map so the index-only scan can skip the heap. For a high-churn table, lower autovacuum_vacuum_scale_factor so autovacuum keeps the map current.`,\n steps: [\n `VACUUM ${rel} to update the visibility map; add ANALYZE if statistics are also stale.`,\n \"If heap fetches keep returning, the table is updated faster than autovacuum runs — make autovacuum more aggressive on it.\",\n \"Confirm the scan stays index-only afterwards by re-running EXPLAIN (ANALYZE) and checking Heap Fetches drops toward 0.\",\n ],\n commands: [\n {\n label: \"Refresh the visibility map\",\n sql: `VACUUM (ANALYZE) ${rel};`,\n },\n {\n label: \"Keep the map current on a high-churn table\",\n sql: `ALTER TABLE ${rel} SET (autovacuum_vacuum_scale_factor = 0.02);`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-index-only-scans.html`,\n meta: { heapFetches },\n }),\n ];\n },\n};\n","import { nodeLabel } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtBlocks, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/** Below this many disk-read blocks the cold-cache noise outweighs any real signal. */\nconst MIN_READ_BLOCKS = 1000;\n\n/**\n * Low shared-buffer cache hit ratio: the node fetched many pages from disk rather\n * than from PostgreSQL's buffer cache. This is often just a cold cache on the first\n * run, so the finding is informational and leads with \"re-run to confirm\" before\n * suggesting shared_buffers sizing or a more selective index.\n */\nexport const lowCacheHit: Rule = {\n id: \"PGX_LOW_CACHE_HIT\",\n title: \"Low cache hit ratio (heavy disk reads)\",\n defaultSeverity: \"info\",\n requiresBuffers: true,\n check(node, ctx) {\n const ratio = node.metrics.cacheHitRatio;\n const readBlocks = node.sharedReadBlocks ?? 0;\n if (ratio == null) return [];\n if (ratio >= ctx.thresholds.lowCacheHitRatio) return [];\n if (readBlocks <= MIN_READ_BLOCKS) return [];\n\n const label = nodeLabel(node);\n const rel = node.relationName;\n const ratioPct = ratio * 100;\n\n return [\n makeFinding(lowCacheHit, ctx, node, {\n title: `Low cache hit ratio at ${label} (${fmtPct(ratioPct)})`,\n detail: `${label} served only ${fmtPct(ratioPct)} of its shared-buffer accesses from cache, reading ${fmtBlocks(readBlocks)} from disk.`,\n cause:\n \"The pages this node needed were not resident in shared_buffers, so PostgreSQL had to read them from disk. On a first run this is an expected cold cache; if it persists, the working set is larger than the cache or the scan touches more pages than necessary.\",\n remediation: {\n summary: `Re-run the query to check whether this is just a cold cache — the ratio should climb on a warm run. If it stays low, the working set exceeds shared_buffers: size shared_buffers/effective_cache_size to your RAM, or add a selective index on ${rel ?? \"the scanned relation\"} so far fewer pages are read.`,\n steps: [\n \"Run the same EXPLAIN (ANALYZE, BUFFERS) a second time; a much higher hit ratio means the first run was a cold cache and no action is needed.\",\n \"If the ratio stays low, check whether shared_buffers (and effective_cache_size for planner costing) are sized to the machine's RAM.\",\n \"If the node reads far more pages than the rows it returns, add a selective index so only matching pages are fetched.\",\n ],\n commands: [\n {\n label: \"Inspect current buffer-cache sizing\",\n sql: \"SHOW shared_buffers; SHOW effective_cache_size;\",\n },\n {\n label: \"Reduce pages read with a selective index\",\n sql: `CREATE INDEX ON ${rel ?? \"<table>\"} (<predicate columns>);`,\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-SHARED-BUFFERS`,\n meta: { cacheHitPct: Math.round(ratioPct * 10) / 10, readBlocks },\n }),\n ];\n },\n};\n","import { nodeLabel } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding, outerChild } from \"./util.ts\";\n\n/**\n * Nested loop whose outer (driving) side produced many rows. A nested loop runs the\n * inner subtree once per outer row, so a large outer side multiplies the inner cost.\n * The planner usually picks this only when it expects few outer rows — so the root\n * cause is normally a cardinality misestimate. Fix the estimate first (so it switches\n * to a hash/merge join); if the estimate is right, index the inner join key.\n */\nexport const nestedLoopLargeOuter: Rule = {\n id: \"PGX_NESTED_LOOP_LARGE_OUTER\",\n title: \"Nested loop with a large outer side\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Nested Loop\") return [];\n\n const outer = outerChild(node);\n const outerRows = outer?.metrics.totalRows;\n if (outerRows === undefined || outerRows <= ctx.thresholds.nestedLoopOuterRows) return [];\n\n const outerLabel = outer ? nodeLabel(outer) : \"the outer side\";\n const inner = node.children[1];\n const innerLabel = inner ? nodeLabel(inner) : \"the inner side\";\n const innerCond = inner?.indexCond ?? inner?.joinFilter ?? inner?.filter ?? node.joinFilter;\n const misestimated = outer?.metrics.estimateDirection === \"under\";\n\n return [\n makeFinding(nestedLoopLargeOuter, ctx, node, {\n title: `Nested loop driven by ${fmtInt(outerRows)} outer rows (${outerLabel})`,\n detail: `The nested loop's outer side (${outerLabel}) produced ${fmtInt(\n outerRows,\n )} rows, so its inner side (${innerLabel}) is re-executed roughly that many times.`,\n cause: misestimated\n ? `The planner expected far fewer outer rows than the ${fmtInt(\n outerRows,\n )} that actually came back, so it chose a per-row nested loop where a single hash/merge join would have been cheaper.`\n : `A nested loop probes the inner side once per outer row; with ${fmtInt(\n outerRows,\n )} outer rows that is ${fmtInt(outerRows)} inner executions.`,\n remediation: {\n summary: `Fix the outer-side row estimate first — re-ANALYZE ${\n outer?.relationName ?? \"the driving table\"\n }, raise its column statistics, or add extended statistics — so the planner switches to a hash or merge join. If the estimate is already accurate, add an index on the inner join key (${\n innerCond ?? \"<inner join column>\"\n }) so each of the ${fmtInt(outerRows)} probes is cheap.`,\n steps: [\n \"Compare the outer node's estimated vs actual rows: a large gap means the estimate is the real problem.\",\n \"Refresh statistics so the planner sees the true cardinality and can prefer a hash/merge join.\",\n \"If columns are correlated, create extended (multivariate) statistics on them.\",\n \"If estimates are already correct, index the inner join key so each probe is an index lookup, not a scan.\",\n \"As a last resort to confirm the diagnosis, test with `SET enable_nestloop = off` for this query only.\",\n ],\n commands: [\n {\n label: \"Refresh planner statistics on the driving table\",\n sql: `ANALYZE ${outer?.relationName ?? \"<outer table>\"};`,\n },\n {\n label: \"Increase statistics target on the misestimated column, then re-ANALYZE\",\n sql: `ALTER TABLE ${\n outer?.relationName ?? \"<outer table>\"\n } ALTER COLUMN <column> SET STATISTICS 1000;\\nANALYZE ${\n outer?.relationName ?? \"<outer table>\"\n };`,\n },\n {\n label: \"Add extended statistics for correlated columns\",\n sql: `CREATE STATISTICS ${\n outer?.relationName ?? \"<outer table>\"\n }_stats (dependencies, ndistinct) ON <col_a>, <col_b> FROM ${\n outer?.relationName ?? \"<outer table>\"\n };\\nANALYZE ${outer?.relationName ?? \"<outer table>\"};`,\n },\n {\n label: \"If estimates are correct, index the inner join key\",\n sql: `CREATE INDEX ON ${\n inner?.relationName ?? \"<inner table>\"\n } (<inner join column>);`,\n },\n {\n label: \"Confirm the diagnosis by disabling nested loops for this query only\",\n sql: \"SET enable_nestloop = off;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-query.html`,\n meta: { outerRows: Math.round(outerRows) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * The planner's row estimate is wildly off from the actual row count. Bad estimates\n * cascade into bad join/sort/memory choices, so a large factor — especially an\n * underestimate feeding a nested loop or hash — is a leading cause of slow plans.\n * Usually it means statistics are stale or too coarse for the predicate.\n */\nexport const rowMisestimate: Rule = {\n id: \"PGX_ROW_MISESTIMATE\",\n title: \"Row count misestimate\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n const { estimateFactor, estimateDirection, totalRows } = node.metrics;\n if (estimateFactor === undefined) return [];\n if (estimateFactor < ctx.thresholds.misestimateFactor) return [];\n if (estimateDirection === undefined || estimateDirection === \"accurate\") return [];\n\n // Cut noise: a 20× error on 3 rows is irrelevant; only care at real volume.\n const rows = Math.max(totalRows ?? 0, node.planRows);\n if (rows < 100) return [];\n\n const factor = Math.round(estimateFactor);\n const rel = node.relationName;\n const onRel = rel ? ` on ${rel}` : \"\";\n const target = rel ?? \"the underlying table\";\n const under = estimateDirection === \"under\";\n const direction = under ? \"underestimate\" : \"overestimate\";\n\n const actual = totalRows ?? 0;\n const detail = `Postgres estimated ${fmtInt(node.planRows)} rows but ${fmtInt(actual)} were produced — a ${fmtInt(factor)}x ${direction}${onRel}.`;\n\n return [\n makeFinding(rowMisestimate, ctx, node, {\n // Severity: underestimates are the dangerous ones (under-sized joins/memory).\n severity: under ? \"warn\" : \"info\",\n title: `${fmtInt(factor)}x row ${direction}${onRel}`,\n detail,\n cause:\n \"The planner's row estimate is based on statistics that are stale, missing, or too coarse for this predicate (e.g. correlated columns the planner treats as independent).\",\n remediation: {\n summary: `Refresh and sharpen statistics for ${target}: run ANALYZE ${rel ?? \"<relation>\"}, raise per-column statistics targets on the predicate columns, and add extended statistics for correlated columns so the planner estimates rows correctly.${\n under\n ? \" Underestimates feeding a nested loop or hash join are the highest priority — fix these first.\"\n : \"\"\n }`,\n steps: [\n `Refresh table statistics first; this alone often fixes the estimate.`,\n `If the column has a skewed/uneven distribution, raise its statistics target and re-ANALYZE.`,\n `If the predicate spans multiple correlated columns, create extended statistics so the planner stops assuming independence.`,\n ],\n commands: [\n {\n label: \"Refresh statistics\",\n sql: `ANALYZE ${rel ?? \"<relation>\"};`,\n },\n {\n label: \"Raise per-column statistics target\",\n sql: `ALTER TABLE ${rel ?? \"<relation>\"} ALTER COLUMN <column> SET STATISTICS 1000;\\nANALYZE ${rel ?? \"<relation>\"};`,\n },\n {\n label: \"Add extended statistics for correlated columns\",\n sql: `CREATE STATISTICS <stats_name> (dependencies, ndistinct) ON <col_a>, <col_b> FROM ${rel ?? \"<relation>\"};\\nANALYZE ${rel ?? \"<relation>\"};`,\n },\n ],\n },\n docsUrl: `${DOCS}/planner-stats.html`,\n meta: {\n estimatedRows: Math.round(node.planRows),\n actualRows: Math.round(actual),\n factor,\n direction: estimateDirection,\n },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Sequential scan reading a large relation. Often an index would let Postgres skip\n * most of the table. If the scan genuinely needs most rows it is correct, so the fix\n * is phrased around the predicate.\n */\nexport const seqScanLarge: Rule = {\n id: \"PGX_SEQ_SCAN_LARGE\",\n title: \"Sequential scan on a large table\",\n defaultSeverity: \"warn\",\n check(node, ctx) {\n if (node.nodeType !== \"Seq Scan\") return [];\n\n // Prefer measured rows; fall back to the estimate on cost-only plans.\n const rows = node.metrics.totalRows ?? node.planRows;\n if (rows < ctx.thresholds.seqScanRows) return [];\n\n const rel = node.relationName ?? \"the table\";\n const estimated = node.metrics.totalRows === undefined;\n const filterCols = node.filter ? ` matching ${node.filter}` : \"\";\n\n return [\n makeFinding(seqScanLarge, ctx, node, {\n title: `Sequential scan on ${rel} (${fmtInt(rows)}${estimated ? \" est.\" : \"\"} rows)`,\n detail: `Postgres read ${rel} sequentially, scanning roughly ${fmtInt(rows)} rows${\n estimated ? \" (estimated — run with ANALYZE for actuals)\" : \"\"\n }.`,\n cause: node.filter\n ? `A row filter (${node.filter}) is applied after reading every row, so no index narrowed the scan.`\n : \"No index condition narrowed the scan, so the whole relation was read.\",\n remediation: {\n summary: `Add an index covering the WHERE/JOIN predicate on ${rel} so Postgres can skip non-matching rows. If the query genuinely needs most of the table, the seq scan is correct — reduce the rows touched instead.`,\n steps: [\n \"Identify the selective columns in the WHERE/JOIN predicate.\",\n \"Ensure they are sargable (no function-wrapping or implicit casts on the column).\",\n \"If selectivity is low, a partial index (WHERE …) may be better.\",\n ],\n commands: [\n {\n label: \"Index the predicate columns\",\n sql: `CREATE INDEX ON ${rel} (<predicate columns>)${filterCols ? \" -- columns from the filter above\" : \"\"};`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-intro.html`,\n meta: { rows: Math.round(rows) },\n }),\n ];\n },\n};\n","import { executionMs } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtMs, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * JIT compilation time dominates total execution. Common on short queries whose plan\n * cost crossed `jit_above_cost`: the one-off cost of generating/optimizing machine code\n * outweighs the runtime it saves, so the query would have been faster with JIT off.\n * Tree-level rule — only acts at the root.\n */\nexport const significantJit: Rule = {\n id: \"PGX_SIGNIFICANT_JIT\",\n title: \"JIT compilation dominates execution\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node !== ctx.tree.root) return [];\n\n const t = ctx.tree.jit?.timing;\n const jitTotal =\n t?.total ??\n (t?.generation ?? 0) + (t?.inlining ?? 0) + (t?.optimization ?? 0) + (t?.emission ?? 0);\n const execMs = executionMs(ctx.tree);\n if (!execMs || jitTotal <= 0) return [];\n\n const jitPct = (100 * jitTotal) / execMs;\n if (jitPct <= ctx.thresholds.jitPct) return [];\n\n return [\n makeFinding(significantJit, ctx, node, {\n title: `JIT compilation took ${fmtMs(jitTotal)} (${fmtPct(jitPct)} of execution)`,\n detail: `JIT spent ${fmtMs(jitTotal)} generating, optimizing, and emitting machine code, out of ${fmtMs(\n execMs,\n )} total execution time. The compilation overhead outweighs the runtime it saved.`,\n cause:\n \"The plan's estimated cost crossed jit_above_cost, so Postgres JIT-compiled the query — but the query is too short for compilation to pay off, often because a row overestimate inflated the cost.\",\n remediation: {\n summary:\n \"Raise jit_above_cost (and jit_inline_above_cost / jit_optimize_above_cost) so short queries skip JIT, or disable JIT for this session with SET jit = off. Then investigate why the cost estimate is high enough to trigger JIT — frequently a row overestimate fixable with ANALYZE.\",\n steps: [\n \"Confirm the query is consistently short-running before tuning — JIT pays off on long, CPU-bound queries.\",\n \"Raise jit_above_cost above this plan's total cost so similar queries skip JIT entirely.\",\n \"If only inlining/optimization are expensive, raise jit_inline_above_cost / jit_optimize_above_cost instead of disabling JIT.\",\n \"Check the planner's row estimates against actuals — an overestimate that inflates cost is the usual reason a cheap query triggers JIT; run ANALYZE on the relations involved.\",\n ],\n commands: [\n { label: \"Disable JIT for this session\", sql: \"SET jit = off;\" },\n {\n label: \"Raise the JIT cost thresholds\",\n sql: \"SET jit_above_cost = <above this plan's total cost>;\\nSET jit_inline_above_cost = <higher>;\\nSET jit_optimize_above_cost = <higher>;\",\n },\n {\n label: \"Refresh statistics if the cost is driven by a row overestimate\",\n sql: \"ANALYZE <table>;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-query.html#GUC-JIT-ABOVE-COST`,\n meta: { jitMs: Math.round(jitTotal), jitPct: Math.round(jitPct) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtKiB, roundUpMiB } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A Sort node spilled to disk because it exceeded work_mem. External merge sorts do\n * extra temp-file I/O and are far slower than an in-memory quicksort. Either raise\n * work_mem for this query, or feed the sort pre-ordered rows via a matching index.\n */\nexport const sortSpillDisk: Rule = {\n id: \"PGX_SORT_SPILL_DISK\",\n title: \"Sort spilled to disk\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Sort\") return [];\n\n const onDisk =\n node.sortSpaceType === \"Disk\" ||\n (node.sortMethod !== undefined && /external/i.test(node.sortMethod));\n if (!onDisk) return [];\n\n // Recommend ~2.2× the disk footprint (sort overhead vs. raw data) rounded up to MiB.\n const usedKiB = node.sortSpaceUsed ?? 0;\n const workMemRecommended = roundUpMiB(usedKiB > 0 ? usedKiB * 2.2 : 0);\n const usedText = usedKiB > 0 ? ` using ${fmtKiB(usedKiB)} of temp space` : \"\";\n const method = node.sortMethod ? ` (${node.sortMethod})` : \"\";\n const orderBy =\n node.sortKey && node.sortKey.length > 0 ? node.sortKey.join(\", \") : \"<ORDER BY columns>\";\n\n const summary =\n usedKiB > 0\n ? `Raise work_mem for this query so the sort stays in memory, e.g. SET work_mem = '${workMemRecommended}' at session or role scope (do NOT raise it globally without accounting for max_connections — each connection can allocate work_mem several times over). Alternatively, add an index on (${orderBy}) so rows arrive pre-sorted and the Sort node disappears.`\n : `Raise work_mem for this query so the sort stays in memory, e.g. SET work_mem = '64MB' at session or role scope (do NOT raise it globally without accounting for max_connections — each connection can allocate work_mem several times over). Alternatively, add an index on (${orderBy}) so rows arrive pre-sorted and the Sort node disappears.`;\n\n return [\n makeFinding(sortSpillDisk, ctx, node, {\n title: `Sort spilled to disk${usedText}`,\n detail: `The Sort node ran an external merge sort on disk${method}${usedText}, because the data exceeded work_mem.`,\n cause:\n \"work_mem was too small to hold the sort set, so Postgres wrote sorted runs to temporary files and merged them — adding temp-file I/O that an in-memory sort avoids.\",\n remediation: {\n summary,\n steps: [\n \"Set work_mem at session or role scope for this workload, not cluster-wide.\",\n `Size it above the spilled footprint${usedKiB > 0 ? ` (~${fmtKiB(usedKiB)}); ${workMemRecommended} leaves headroom` : \"\"}.`,\n `Or add an index on (${orderBy}) so the sort is satisfied by an ordered scan and removed entirely.`,\n ],\n commands: [\n {\n label: \"Raise work_mem for this session\",\n sql: `SET work_mem = '${usedKiB > 0 ? workMemRecommended : \"64MB\"}';`,\n },\n {\n label: \"Or set it per role\",\n sql: `ALTER ROLE <role> SET work_mem = '${usedKiB > 0 ? workMemRecommended : \"64MB\"}';`,\n },\n {\n label: \"Or add an index matching the sort key\",\n sql: `CREATE INDEX ON <table> (${orderBy});`,\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-WORK-MEM`,\n meta: { sortSpaceUsedKiB: Math.round(usedKiB), workMemRecommended },\n }),\n ];\n },\n};\n","import { executionMs } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtMs, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Triggers consume a significant fraction of execution time. Trigger work (FK\n * constraint checks, AFTER triggers, etc.) runs outside the plan tree, so it is\n * invisible in the node timings and easy to miss. We surface it when the summed\n * trigger time crosses `triggerPct` of total execution time.\n */\nexport const triggerTime: Rule = {\n id: \"PGX_TRIGGER_TIME\",\n title: \"Triggers consume significant time\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n // Tree-level rule — act only at the root.\n if (node !== ctx.tree.root) return [];\n\n const triggers = ctx.tree.triggers;\n const execMs = executionMs(ctx.tree);\n const triggerTotal = triggers.reduce((s, t) => s + (t.time ?? 0), 0);\n if (!triggers.length || !execMs || triggerTotal <= 0) return [];\n\n const pct = (100 * triggerTotal) / execMs;\n if (pct <= ctx.thresholds.triggerPct) return [];\n\n // Name the heaviest trigger so the message is concrete.\n const worst = triggers.reduce((a, b) => ((b.time ?? 0) > (a.time ?? 0) ? b : a));\n const worstLabel = worst.name ?? worst.constraintName ?? \"a trigger\";\n const onRel = worst.relation ? ` on ${worst.relation}` : \"\";\n\n return [\n makeFinding(triggerTime, ctx, node, {\n title: `Triggers consumed ${fmtMs(triggerTotal)} (${fmtPct(pct)} of execution)`,\n detail: `Trigger execution took ${fmtMs(triggerTotal)} of the ${fmtMs(\n execMs,\n )} total — ${fmtPct(pct)} of the time is spent outside the plan tree (heaviest: \"${worstLabel}\"${onRel}).`,\n cause:\n \"Time spent firing triggers (often foreign-key constraint checks or AFTER triggers) is not attributed to any plan node, so it is invisible in the node timings even though it dominates the statement.\",\n remediation: {\n summary: `Index the foreign-key columns involved in the constraint checks so each row's lookup is cheap, and review the trigger function bodies for per-row inefficiency. For bulk loads, defer constraints (SET CONSTRAINTS ALL DEFERRED) or disable and replay triggers around the batch.`,\n steps: [\n \"Confirm both the referencing and referenced FK columns are indexed — an FK check does a lookup on the referenced key for every row, and a missing index makes it a full scan per row.\",\n \"Inspect each trigger function body for per-row work that could be batched or removed.\",\n \"For bulk INSERT/UPDATE/COPY, defer FK constraints until commit, or temporarily disable user triggers and replay the work once after the batch.\",\n ],\n commands: [\n {\n label: \"Index the referencing FK column(s) so constraint checks are cheap\",\n sql: `CREATE INDEX ON <referencing_table> (<fk_columns>);`,\n },\n {\n label: \"Defer FK constraint checks to commit for a bulk load\",\n sql: `BEGIN;\\nSET CONSTRAINTS ALL DEFERRED;\\n-- bulk INSERT/UPDATE/COPY here\\nCOMMIT;`,\n },\n {\n label: \"Disable user triggers around a batch, then re-enable\",\n sql: `ALTER TABLE <table> DISABLE TRIGGER USER;\\n-- bulk work here\\nALTER TABLE <table> ENABLE TRIGGER USER;`,\n },\n ],\n },\n docsUrl: `${DOCS}/sql-createtrigger.html`,\n meta: { triggerMs: Math.round(triggerTotal), triggerPct: Math.round(pct) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A Gather / Gather Merge node asked for more parallel workers than it got. Postgres\n * caps the total number of background workers globally (max_worker_processes /\n * max_parallel_workers), so a busy server can starve a query of the workers it planned\n * for, leaving the parallel plan running mostly serial. This is informational: if the\n * plan was not actually faster in parallel, fewer workers may be fine.\n */\nexport const workersNotLaunched: Rule = {\n id: \"PGX_WORKERS_NOT_LAUNCHED\",\n title: \"Parallel workers planned but not launched\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Gather\" && node.nodeType !== \"Gather Merge\") return [];\n if (node.workersPlanned === undefined || node.workersLaunched === undefined) return [];\n if (node.workersLaunched >= node.workersPlanned) return [];\n\n const planned = node.workersPlanned;\n const launched = node.workersLaunched;\n const shortfall = planned - launched;\n\n return [\n makeFinding(workersNotLaunched, ctx, node, {\n title: `${node.nodeType} got ${fmtInt(launched)} of ${fmtInt(planned)} planned workers`,\n detail: `This ${node.nodeType} planned for ${fmtInt(planned)} parallel worker${\n planned === 1 ? \"\" : \"s\"\n } but only ${fmtInt(launched)} were launched (${fmtInt(shortfall)} short), so part of the work ran serially.`,\n cause:\n \"The global background-worker pool was exhausted: max_worker_processes or max_parallel_workers was already saturated (often by other concurrent parallel queries) when this node tried to start its workers.\",\n remediation: {\n summary: `Raise max_parallel_workers and max_worker_processes so the pool can supply the ${fmtInt(\n planned,\n )} workers this query plans for, and confirm max_parallel_workers_per_gather permits them. If parallelism is not actually speeding this query up, the shortfall is harmless.`,\n steps: [\n \"Check current limits: max_worker_processes, max_parallel_workers, max_parallel_workers_per_gather.\",\n \"max_parallel_workers must be <= max_worker_processes; raise both together (max_worker_processes change needs a restart).\",\n \"Look for other concurrent parallel queries saturating the shared pool during peak load.\",\n \"If a serial plan is no slower here, leave the settings alone — this is informational.\",\n ],\n commands: [\n {\n label: \"Enlarge the global parallel-worker pool\",\n sql: \"ALTER SYSTEM SET max_parallel_workers = '<N>';\\nALTER SYSTEM SET max_worker_processes = '<N+>';\\nSELECT pg_reload_conf();\",\n },\n {\n label: \"Allow more workers per Gather\",\n sql: \"ALTER SYSTEM SET max_parallel_workers_per_gather = '<N>';\\nSELECT pg_reload_conf();\",\n },\n {\n label: \"Inspect the current settings\",\n sql: \"SELECT name, setting FROM pg_settings WHERE name IN ('max_worker_processes', 'max_parallel_workers', 'max_parallel_workers_per_gather');\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS`,\n meta: { planned, launched },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { bitmapLossy } from \"./bitmap-lossy.ts\";\nimport { cartesianProduct } from \"./cartesian-product.ts\";\nimport { correlatedSubplan } from \"./correlated-subplan.ts\";\nimport { couldBeIndexOnly } from \"./could-be-index-only.ts\";\nimport { filterCouldBeIndexCond } from \"./filter-could-be-index-cond.ts\";\nimport { hashSpillDisk } from \"./hash-spill-disk.ts\";\nimport { highFilterDiscard } from \"./high-filter-discard.ts\";\nimport { indexOnlyHeapFetches } from \"./index-only-heap-fetches.ts\";\nimport { lowCacheHit } from \"./low-cache-hit.ts\";\nimport { nestedLoopLargeOuter } from \"./nested-loop-large-outer.ts\";\nimport { rowMisestimate } from \"./row-misestimate.ts\";\nimport { seqScanLarge } from \"./seq-scan-large.ts\";\nimport { significantJit } from \"./significant-jit.ts\";\nimport { sortSpillDisk } from \"./sort-spill-disk.ts\";\nimport { triggerTime } from \"./trigger-time.ts\";\nimport { workersNotLaunched } from \"./workers-not-launched.ts\";\n\n/**\n * Every advisor rule, in display order (most actionable structural issues first).\n * Rule ids ARE the PGX_* diagnostic codes (greppable, config-keyed). One file per rule.\n */\nexport const ALL_RULES: Rule[] = [\n cartesianProduct,\n seqScanLarge,\n nestedLoopLargeOuter,\n highFilterDiscard,\n sortSpillDisk,\n hashSpillDisk,\n correlatedSubplan,\n rowMisestimate,\n filterCouldBeIndexCond,\n couldBeIndexOnly,\n indexOnlyHeapFetches,\n bitmapLossy,\n workersNotLaunched,\n lowCacheHit,\n significantJit,\n triggerTime,\n];\n","import { DEFAULT_CONFIG, type PgExplainConfig } from \"../config.ts\";\nimport { bottlenecks, executionMs, nodeLabel } from \"../core/metrics.ts\";\nimport type {\n AnalysisContext,\n AnalysisResult,\n Diagnostic,\n PlanTree,\n Severity,\n} from \"../core/model.ts\";\nimport { flatten } from \"../core/parse.ts\";\nimport { bySeverity, maxSeverity } from \"../diagnostics/diagnostic.ts\";\nimport { fmtMs } from \"../util/format.ts\";\nimport { ALL_RULES } from \"./rules/index.ts\";\n\n/**\n * Run every enabled rule over the tree and assemble the result. Assumes\n * computeMetrics(tree) has already run. Rules that need data the plan lacks\n * (ANALYZE/BUFFERS) are skipped so cost-only plans degrade gracefully.\n */\nexport function runAdvisor(\n tree: PlanTree,\n config: PgExplainConfig = DEFAULT_CONFIG,\n): AnalysisResult {\n const ctx: AnalysisContext = {\n tree,\n thresholds: config.thresholds,\n severityOf: (id, fallback) => config.rules[id]?.severity ?? fallback,\n isEnabled: (id) => config.rules[id]?.enabled !== false,\n };\n\n const nodes = flatten(tree.root);\n const diagnostics: Diagnostic[] = [];\n\n for (const rule of ALL_RULES) {\n if (!ctx.isEnabled(rule.id)) continue;\n if (rule.requiresAnalyze && !tree.hasAnalyze) continue;\n if (rule.requiresBuffers && !tree.hasBuffers) continue;\n for (const node of nodes) {\n for (const finding of rule.check(node, ctx)) diagnostics.push(finding);\n }\n }\n\n diagnostics.sort(bySeverity);\n\n let worst: Severity | null = null;\n for (const d of diagnostics) worst = worst === null ? d.severity : maxSeverity(worst, d.severity);\n\n const bn = bottlenecks(tree, 5);\n return {\n tree,\n diagnostics,\n bottlenecks: bn,\n verdict: buildVerdict(tree, diagnostics, bn),\n worstSeverity: worst,\n };\n}\n\nfunction buildVerdict(\n tree: PlanTree,\n diagnostics: Diagnostic[],\n bn: AnalysisResult[\"bottlenecks\"],\n): string {\n const counts: Record<Severity, number> = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity]++;\n\n const parts: string[] = [];\n if (counts.error) parts.push(`${counts.error} critical`);\n if (counts.warn) parts.push(`${counts.warn} warning${counts.warn > 1 ? \"s\" : \"\"}`);\n if (counts.info) parts.push(`${counts.info} note${counts.info > 1 ? \"s\" : \"\"}`);\n const findings = parts.length ? parts.join(\", \") : \"no issues found\";\n\n const top = bn[0];\n let bottleneck = \"\";\n if (top?.metrics.selfMs !== undefined) {\n const pct =\n top.metrics.pctOfTotal !== undefined\n ? ` (${top.metrics.pctOfTotal.toFixed(0)}% of time)`\n : \"\";\n bottleneck = ` — top cost: ${nodeLabel(top)}${pct}`;\n }\n\n const ms = executionMs(tree);\n const timing = ms !== undefined ? ` Total ${fmtMs(ms)}.` : \" Cost-only plan (no timing).\";\n return `${findings}${bottleneck}.${timing}`;\n}\n","import type { PlanNode, PlanTree } from \"../core/model.ts\";\nimport { walk } from \"../core/parse.ts\";\n\n/**\n * Strip literal values out of a plan so a shared report or CI artifact can't leak\n * real data. VERBOSE output and filter/condition expressions embed constants\n * (e.g. `status = 'shipped'`, `amount > 1000`) — those become `'?'` / `N`.\n *\n * ponytail: regex over expression strings, not a SQL parser. Catches string and\n * numeric literals, which is where real values live; identifiers/operators stay.\n */\nexport function redactExpression(expr: string): string {\n return expr\n .replace(/'(?:[^']|'')*'/g, \"'?'\") // string literals (with '' escapes)\n .replace(/\\b\\d+(?:\\.\\d+)?\\b/g, \"N\"); // numeric literals\n}\n\nconst EXPR_FIELDS = [\n \"filter\",\n \"indexCond\",\n \"recheckCond\",\n \"hashCond\",\n \"joinFilter\",\n] as const satisfies readonly (keyof PlanNode)[];\n\nfunction redactNode(node: PlanNode): void {\n for (const field of EXPR_FIELDS) {\n const value = node[field];\n if (typeof value === \"string\") (node[field] as string) = redactExpression(value);\n }\n if (node.output) node.output = node.output.map(redactExpression);\n if (node.sortKey) node.sortKey = node.sortKey.map(redactExpression);\n}\n\n/** Redact every expression field in the tree, in place. */\nexport function redactPlanTree(tree: PlanTree): void {\n walk(tree.root, redactNode);\n}\n","import { executionMs, nodeLabel } from \"../core/metrics.ts\";\nimport type { PlanNode, PlanTree } from \"../core/model.ts\";\nimport { fmtInt, fmtMs, type TreeGlyphs } from \"../util/format.ts\";\n\nexport interface TreeLine {\n node: PlanNode;\n /** Indentation + branch glyphs already applied. */\n prefix: string;\n}\n\n/** Lay out the plan as indented lines. Shared by the markdown/terminal/text renderers. */\nexport function treeLines(tree: PlanTree, glyphs: TreeGlyphs): TreeLine[] {\n const lines: TreeLine[] = [];\n const recurse = (node: PlanNode, indent: string, isLast: boolean, isRoot: boolean): void => {\n const connector = isRoot ? \"\" : isLast ? glyphs.last : glyphs.branch;\n lines.push({ node, prefix: indent + connector });\n const childIndent = isRoot ? \"\" : indent + (isLast ? glyphs.space : glyphs.vert);\n node.children.forEach((child, i) => {\n recurse(child, childIndent, i === node.children.length - 1, false);\n });\n };\n recurse(tree.root, \"\", true, true);\n return lines;\n}\n\n/** A compact, plain-text metric summary for one node (no color). */\nexport function nodeSummary(node: PlanNode): string {\n const m = node.metrics;\n const parts: string[] = [];\n\n if (m.totalRows !== undefined) {\n let rows = `rows=${fmtInt(m.totalRows)}`;\n if (\n m.estimateFactor !== undefined &&\n m.estimateFactor >= 2 &&\n m.estimateDirection !== \"accurate\"\n ) {\n rows += ` (est ${fmtInt(node.planRows)}, ${m.estimateFactor.toFixed(0)}× ${m.estimateDirection})`;\n }\n parts.push(rows);\n } else {\n parts.push(`rows≈${fmtInt(node.planRows)} est`);\n }\n\n if (m.selfMs !== undefined) {\n let t = `self ${fmtMs(m.selfMs)}`;\n if (m.pctOfTotal !== undefined && m.pctOfTotal >= 1) t += ` (${m.pctOfTotal.toFixed(0)}%)`;\n parts.push(t);\n }\n\n if (node.metrics.cacheHitRatio != null) {\n parts.push(`cache ${(node.metrics.cacheHitRatio * 100).toFixed(0)}%`);\n }\n\n return parts.join(\" · \");\n}\n\nexport { executionMs, nodeLabel };\n","import { executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, PlanNode, Severity } from \"../core/model.ts\";\nimport { flatten } from \"../core/parse.ts\";\nimport { nodeLabel } from \"./tree.ts\";\n\n/** Bump on any breaking change to the JSON shape. Consumers can assert on it. */\nexport const JSON_SCHEMA_VERSION = 1;\n\n/** Stable, machine-readable report for CI and tooling. */\nexport function renderJson(result: AnalysisResult, pretty = true): string {\n const { tree, diagnostics, bottlenecks } = result;\n\n const counts: Record<Severity, number> = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity]++;\n\n const report = {\n schemaVersion: JSON_SCHEMA_VERSION,\n verdict: result.verdict,\n worstSeverity: result.worstSeverity,\n summary: {\n planningTimeMs: tree.planningTime ?? null,\n executionTimeMs: executionMs(tree) ?? null,\n hasAnalyze: tree.hasAnalyze,\n hasBuffers: tree.hasBuffers,\n nodeCount: flatten(tree.root).length,\n findings: counts,\n },\n diagnostics,\n bottlenecks: bottlenecks\n .filter((n) => (n.metrics.selfMs ?? 0) > 0)\n .map((n) => ({\n id: n.id,\n label: nodeLabel(n),\n nodeType: n.nodeType,\n relation: n.relationName ?? null,\n selfMs: n.metrics.selfMs ?? null,\n pctOfTotal: n.metrics.pctOfTotal ?? null,\n totalRows: n.metrics.totalRows ?? null,\n })),\n plan: serializeNode(tree.root),\n };\n\n return JSON.stringify(report, null, pretty ? 2 : 0);\n}\n\n/** Slim node for JSON: normalized fields + metrics + children, never the raw blob. */\nfunction serializeNode(node: PlanNode): Record<string, unknown> {\n const { children, metrics, raw, ...fields } = node;\n void raw;\n return { ...fields, metrics, children: children.map(serializeNode) };\n}\n","import { executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, Severity } from \"../core/model.ts\";\nimport { fmtMs, UNICODE_TREE } from \"../util/format.ts\";\nimport { nodeLabel, nodeSummary, treeLines } from \"./tree.ts\";\n\nconst SEV: Record<Severity, { label: string; cls: string }> = {\n error: { label: \"Critical\", cls: \"sev-error\" },\n warn: { label: \"Warning\", cls: \"sev-warn\" },\n info: { label: \"Note\", cls: \"sev-info\" },\n};\n\nfunction esc(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\n/** A single self-contained HTML file: inline CSS, no external assets, safe to email. */\nexport function renderHtml(result: AnalysisResult): string {\n const { tree, diagnostics } = result;\n const ms = executionMs(tree);\n\n const treeHtml = treeLines(tree, UNICODE_TREE)\n .map(({ node, prefix }) => {\n const pct = node.metrics.pctOfTotal ?? 0;\n const heat = pct >= 50 ? \"hot\" : pct >= 20 ? \"warm\" : pct >= 5 ? \"\" : \"cold\";\n return `<div class=\"node ${heat}\"><span class=\"glyph\">${esc(prefix)}</span><span class=\"label\">${esc(nodeLabel(node))}</span> <span class=\"meta\">${esc(nodeSummary(node))}</span></div>`;\n })\n .join(\"\\n\");\n\n const findingsHtml = diagnostics.length\n ? diagnostics.map(findingHtml).join(\"\\n\")\n : '<p class=\"ok\">No anti-patterns detected. 🎉</p>';\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>pg-explain report</title>\n<style>\n :root { color-scheme: light dark; }\n body { font: 15px/1.5 -apple-system, system-ui, sans-serif; margin: 0; padding: 2rem; max-width: 980px; margin-inline: auto; }\n h1 { font-size: 1.4rem; } h2 { font-size: 1.1rem; margin-top: 2rem; border-bottom: 1px solid #8884; padding-bottom: .3rem; }\n .verdict { padding: .75rem 1rem; border-left: 4px solid #888; background: #8881; border-radius: 4px; }\n .verdict.sev-error { border-color: #e5484d; } .verdict.sev-warn { border-color: #f5a623; } .verdict.sev-info { border-color: #4493f8; }\n table { border-collapse: collapse; width: 100%; } td, th { text-align: left; padding: .3rem .6rem; border-bottom: 1px solid #8883; }\n .tree { overflow-x: auto; } .node { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre; font-size: 13px; }\n .glyph { color: #8888; } .meta { color: #888; }\n .node.hot .label { color: #e5484d; font-weight: 700; } .node.warm .label { color: #f5a623; } .node.cold .label { opacity: .6; }\n .finding { border: 1px solid #8883; border-radius: 6px; padding: 1rem; margin: 1rem 0; }\n .finding .tag { font-size: .75rem; font-weight: 700; padding: .1rem .5rem; border-radius: 3px; color: #fff; }\n .sev-error .tag { background: #e5484d; } .sev-warn .tag { background: #f5a623; } .sev-info .tag { background: #4493f8; }\n .finding code, pre { font-family: ui-monospace, monospace; font-size: 13px; }\n pre { background: #8881; padding: .6rem .8rem; border-radius: 4px; overflow-x: auto; }\n .label-cmd { color: #888; font-size: .85rem; margin-top: .5rem; }\n .ok { color: #2e7d32; }\n</style>\n</head>\n<body>\n<h1>pg-explain report</h1>\n<div class=\"verdict ${result.worstSeverity ? SEV[result.worstSeverity].cls : \"\"}\">${esc(result.verdict)}</div>\n\n<h2>Summary</h2>\n<table>\n ${tree.planningTime !== undefined ? `<tr><th>Planning time</th><td>${esc(fmtMs(tree.planningTime))}</td></tr>` : \"\"}\n ${ms !== undefined ? `<tr><th>Execution time</th><td>${esc(fmtMs(ms))}</td></tr>` : \"\"}\n ${!tree.hasAnalyze ? \"<tr><th>Mode</th><td>cost-only (no ANALYZE)</td></tr>\" : \"\"}\n <tr><th>Findings</th><td>${diagnostics.length}</td></tr>\n</table>\n\n<h2>Plan tree</h2>\n<div class=\"tree\">\n${treeHtml}\n</div>\n\n<h2>Findings</h2>\n${findingsHtml}\n</body>\n</html>\n`;\n}\n\nfunction findingHtml(d: Diagnostic): string {\n const sev = SEV[d.severity];\n const steps = d.remediation.steps?.length\n ? `<ul>${d.remediation.steps.map((s) => `<li>${esc(s)}</li>`).join(\"\")}</ul>`\n : \"\";\n const cmds = (d.remediation.commands ?? [])\n .map((c) => {\n const body = c.sql ?? c.shell ?? \"\";\n const label = c.label ? `<div class=\"label-cmd\">${esc(c.label)}</div>` : \"\";\n return `${label}<pre><code>${esc(body)}</code></pre>`;\n })\n .join(\"\");\n const docs = d.docsUrl ? `<p>📖 <a href=\"${esc(d.docsUrl)}\">PostgreSQL docs</a></p>` : \"\";\n const meta = d.location?.relation\n ? ` <span class=\"meta\">on ${esc(d.location.relation)}</span>`\n : \"\";\n\n return `<div class=\"finding ${sev.cls}\">\n <p><span class=\"tag\">${sev.label}</span> <strong>${esc(d.title)}</strong> <code>${esc(d.code)}</code>${meta}</p>\n <p><strong>What:</strong> ${esc(d.detail)}</p>\n <p><strong>Why:</strong> ${esc(d.cause)}</p>\n <p><strong>Fix:</strong> ${esc(d.remediation.summary)}</p>\n ${steps}\n ${cmds}\n ${docs}\n</div>`;\n}\n","import { executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, Severity } from \"../core/model.ts\";\nimport { fmtInt, fmtMs, UNICODE_TREE } from \"../util/format.ts\";\nimport { nodeLabel, nodeSummary, treeLines } from \"./tree.ts\";\n\nconst SEV_LABEL: Record<Severity, string> = {\n error: \"🔴 Critical\",\n warn: \"🟠 Warning\",\n info: \"🔵 Note\",\n};\n\nexport interface MarkdownOptions {\n tldr?: boolean;\n}\n\n/** The headline deliverable: a shareable Markdown report. */\nexport function renderMarkdown(result: AnalysisResult, opts: MarkdownOptions = {}): string {\n const { tree, diagnostics, bottlenecks } = result;\n const out: string[] = [];\n\n out.push(\"# pg-explain report\", \"\");\n out.push(`> **Verdict:** ${result.verdict}`, \"\");\n\n // Summary.\n out.push(\"## Summary\", \"\");\n const ms = executionMs(tree);\n out.push(\"| Metric | Value |\", \"| --- | --- |\");\n if (tree.planningTime !== undefined) out.push(`| Planning time | ${fmtMs(tree.planningTime)} |`);\n if (ms !== undefined) out.push(`| Execution time | ${fmtMs(ms)} |`);\n if (!tree.hasAnalyze) out.push(\"| Mode | cost-only (no ANALYZE) |\");\n out.push(`| Findings | ${summarizeCounts(diagnostics)} |`, \"\");\n\n if (opts.tldr) {\n out.push(...renderFindings(diagnostics, true));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n }\n\n // Plan tree.\n out.push(\"## Plan tree\", \"\", \"```\");\n for (const { node, prefix } of treeLines(tree, UNICODE_TREE)) {\n out.push(`${prefix}${nodeLabel(node)} — ${nodeSummary(node)}`);\n }\n out.push(\"```\", \"\");\n\n // Bottlenecks.\n const ranked = bottlenecks.filter((n) => (n.metrics.selfMs ?? 0) > 0);\n if (ranked.length) {\n out.push(\"## Bottlenecks (by self time)\", \"\");\n out.push(\"| # | Node | Self time | % of total | Rows |\", \"| --- | --- | --- | --- | --- |\");\n ranked.forEach((node, i) => {\n const pct =\n node.metrics.pctOfTotal !== undefined ? `${node.metrics.pctOfTotal.toFixed(1)}%` : \"—\";\n const rows = node.metrics.totalRows !== undefined ? fmtInt(node.metrics.totalRows) : \"—\";\n out.push(\n `| ${i + 1} | ${nodeLabel(node)} | ${fmtMs(node.metrics.selfMs ?? 0)} | ${pct} | ${rows} |`,\n );\n });\n out.push(\"\");\n }\n\n // Findings.\n out.push(...renderFindings(diagnostics, false));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n}\n\nfunction renderFindings(diagnostics: Diagnostic[], tldr: boolean): string[] {\n const out: string[] = [\"## Findings\", \"\"];\n if (diagnostics.length === 0) {\n out.push(\"No anti-patterns detected. 🎉\", \"\");\n return out;\n }\n\n for (const d of diagnostics) {\n out.push(`### ${SEV_LABEL[d.severity]} — ${d.title}`, \"\");\n out.push(`\\`${d.code}\\``, \"\");\n out.push(`**What:** ${d.detail}`, \"\");\n out.push(`**Why:** ${d.cause}`, \"\");\n out.push(`**Fix:** ${d.remediation.summary}`, \"\");\n if (!tldr) {\n if (d.remediation.steps?.length) {\n for (const step of d.remediation.steps) out.push(`- ${step}`);\n out.push(\"\");\n }\n for (const cmd of d.remediation.commands ?? []) {\n const body = cmd.sql ?? cmd.shell ?? \"\";\n const lang = cmd.sql ? \"sql\" : \"sh\";\n if (cmd.label) out.push(`_${cmd.label}:_`);\n out.push(\"```\" + lang, body, \"```\", \"\");\n }\n if (d.docsUrl) out.push(`📖 [PostgreSQL docs](${d.docsUrl})`, \"\");\n }\n }\n return out;\n}\n\nfunction summarizeCounts(diagnostics: Diagnostic[]): string {\n const counts: Record<Severity, number> = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity]++;\n if (diagnostics.length === 0) return \"none\";\n return `${counts.error} critical, ${counts.warn} warning(s), ${counts.info} note(s)`;\n}\n","// picocolors is CommonJS; import the default export and destructure (named ESM\n// imports fail at runtime). tsup keeps it external, so this resolves to the CJS module.\nimport pc from \"picocolors\";\n\nconst { createColors, isColorSupported } = pc;\n\ntype Colors = ReturnType<typeof createColors>;\n\n// picocolors already honors NO_COLOR / FORCE_COLOR / TTY. configureColor lets the\n// CLI override that with --color/--no-color.\nlet active: Colors = createColors(isColorSupported);\n\nexport function configureColor(mode: \"auto\" | \"always\" | \"never\"): void {\n active = createColors(mode === \"always\" || (mode === \"auto\" && isColorSupported));\n}\n\n/** Current color functions. Renderers call this so --no-color takes effect. */\nexport function colors(): Colors {\n return active;\n}\n","import { executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, PlanNode, Severity } from \"../core/model.ts\";\nimport { colors } from \"../util/color.ts\";\nimport { ASCII_TREE, fmtMs, UNICODE_TREE } from \"../util/format.ts\";\nimport { nodeLabel, nodeSummary, treeLines } from \"./tree.ts\";\n\nexport interface TerminalOptions {\n /** ASCII tree glyphs + no bars; suitable for logs / screen readers. */\n ascii?: boolean;\n bars?: boolean;\n tldr?: boolean;\n}\n\nconst SEV_TAG: Record<Severity, string> = { error: \"CRITICAL\", warn: \"WARNING\", info: \"NOTE\" };\n\nfunction sevColor(sev: Severity, text: string): string {\n const c = colors();\n if (sev === \"error\") return c.red(c.bold(text));\n if (sev === \"warn\") return c.yellow(text);\n return c.cyan(text);\n}\n\n/** Heat the node label by its share of total time. */\nfunction heat(node: PlanNode, text: string): string {\n const c = colors();\n const pct = node.metrics.pctOfTotal;\n if (pct === undefined) return text;\n if (pct >= 50) return c.red(c.bold(text));\n if (pct >= 20) return c.yellow(text);\n if (pct >= 5) return text;\n return c.dim(text);\n}\n\nfunction bar(pct: number, width = 8): string {\n const filled = Math.round((pct / 100) * width);\n return \"▇\".repeat(Math.min(filled, width)) + \"▁\".repeat(Math.max(width - filled, 0));\n}\n\nexport function renderTerminal(result: AnalysisResult, opts: TerminalOptions = {}): string {\n const c = colors();\n const { tree, diagnostics, bottlenecks } = result;\n const glyphs = opts.ascii ? ASCII_TREE : UNICODE_TREE;\n const out: string[] = [];\n\n out.push(c.bold(\"pg-explain report\"));\n out.push(`${c.bold(\"Verdict:\")} ${verdictColored(result)}`);\n out.push(\"\");\n\n if (opts.tldr) {\n out.push(...findingsBlock(diagnostics, opts));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n }\n\n // Plan tree.\n out.push(c.bold(\"Plan tree\"));\n for (const { node, prefix } of treeLines(tree, glyphs)) {\n const heatBar =\n opts.bars !== false && node.metrics.pctOfTotal !== undefined\n ? ` ${c.dim(bar(node.metrics.pctOfTotal))}`\n : \"\";\n out.push(\n `${c.dim(prefix)}${heat(node, nodeLabel(node))}${heatBar} ${c.dim(nodeSummary(node))}`,\n );\n }\n out.push(\"\");\n\n // Bottlenecks.\n const ranked = bottlenecks.filter((n) => (n.metrics.selfMs ?? 0) > 0);\n if (ranked.length) {\n out.push(c.bold(\"Bottlenecks (by self time)\"));\n ranked.forEach((node, i) => {\n const pct =\n node.metrics.pctOfTotal !== undefined ? `${node.metrics.pctOfTotal.toFixed(0)}%` : \"—\";\n out.push(\n ` ${i + 1}. ${heat(node, nodeLabel(node))} — ${fmtMs(node.metrics.selfMs ?? 0)} (${pct})`,\n );\n });\n out.push(\"\");\n }\n\n out.push(...findingsBlock(diagnostics, opts));\n const ms = executionMs(tree);\n if (ms !== undefined) out.push(c.dim(`Total execution time: ${fmtMs(ms)}`));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n}\n\nfunction verdictColored(result: AnalysisResult): string {\n if (result.worstSeverity === null) return colors().green(result.verdict);\n return sevColor(result.worstSeverity, result.verdict);\n}\n\nfunction findingsBlock(diagnostics: Diagnostic[], opts: TerminalOptions): string[] {\n const c = colors();\n const out: string[] = [c.bold(\"Findings\")];\n if (diagnostics.length === 0) {\n out.push(` ${c.green(\"No anti-patterns detected.\")}`, \"\");\n return out;\n }\n for (const d of diagnostics) {\n out.push(\"\");\n out.push(\n `${sevColor(d.severity, `[${SEV_TAG[d.severity]}]`)} ${c.bold(d.title)} ${c.dim(d.code)}`,\n );\n out.push(` ${c.dim(\"What:\")} ${d.detail}`);\n out.push(` ${c.dim(\"Why: \")} ${d.cause}`);\n out.push(` ${c.dim(\"Fix: \")} ${d.remediation.summary}`);\n if (!opts.tldr) {\n for (const step of d.remediation.steps ?? []) out.push(` - ${step}`);\n for (const cmd of d.remediation.commands ?? []) {\n const body = cmd.sql ?? cmd.shell ?? \"\";\n const label = cmd.label ? `${c.dim(`${cmd.label}:`)} ` : \"\";\n out.push(` ${label}${c.green(body)}`);\n }\n if (d.docsUrl) out.push(` ${c.dim(`docs: ${d.docsUrl}`)}`);\n }\n }\n out.push(\"\");\n return out;\n}\n","import type { AnalysisResult } from \"../core/model.ts\";\nimport { renderHtml } from \"./html.ts\";\nimport { renderJson } from \"./json.ts\";\nimport { renderMarkdown } from \"./markdown.ts\";\nimport { renderTerminal } from \"./terminal.ts\";\n\nexport type Format = \"terminal\" | \"markdown\" | \"json\" | \"html\" | \"text\";\n\nexport const FORMATS: Format[] = [\"terminal\", \"markdown\", \"json\", \"html\", \"text\"];\n\nexport function isFormat(s: string): s is Format {\n return (FORMATS as string[]).includes(s);\n}\n\nexport interface RenderOptions {\n format: Format;\n /** Summary + findings only, no plan tree. */\n tldr?: boolean;\n /** ASCII tree glyphs (terminal/text). */\n ascii?: boolean;\n /** Pretty-print JSON. */\n pretty?: boolean;\n}\n\n/** Render an analysis result to the requested format. Color is configured by the caller. */\nexport function render(result: AnalysisResult, opts: RenderOptions): string {\n switch (opts.format) {\n case \"markdown\":\n return renderMarkdown(result, { tldr: opts.tldr });\n case \"json\":\n return renderJson(result, opts.pretty ?? true);\n case \"html\":\n return renderHtml(result);\n case \"text\":\n // Plain text: ASCII tree, no bars. Caller disables color for this format.\n return renderTerminal(result, { ascii: true, bars: false, tldr: opts.tldr });\n default:\n return renderTerminal(result, { ascii: opts.ascii, tldr: opts.tldr });\n }\n}\n","/**\n * Public library API. Consumers can parse, analyze, and render plans programmatically:\n *\n * import { analyze, render } from \"pgexplain\";\n * const result = analyze(explainJsonText);\n * console.log(render(result, { format: \"markdown\" }));\n */\nimport { runAdvisor } from \"./advisor/index.ts\";\nimport { DEFAULT_CONFIG, type PgExplainConfig } from \"./config.ts\";\nimport { computeMetrics } from \"./core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, PlanTree, Severity } from \"./core/model.ts\";\nimport { flatten, parseExplainJson } from \"./core/parse.ts\";\nimport { opDiagnostic, opError } from \"./diagnostics/catalog.ts\";\nimport { bySeverity, maxSeverity } from \"./diagnostics/diagnostic.ts\";\nimport { redactPlanTree } from \"./input/redact.ts\";\n\nexport interface AnalyzeOptions {\n config?: PgExplainConfig;\n /** 1-based statement index when the input holds more than one. */\n statement?: number;\n /** Strip literal values from expressions before analysis (no data leaks downstream). */\n redact?: boolean;\n}\n\n/** Parse → (redact) → compute metrics → run advisor → attach informational notices. */\nexport function analyze(input: string, options: AnalyzeOptions = {}): AnalysisResult {\n const trees = parseExplainJson(input);\n const tree = selectStatement(trees, options.statement);\n if (options.redact) redactPlanTree(tree);\n computeMetrics(tree);\n\n const result = runAdvisor(tree, options.config ?? DEFAULT_CONFIG);\n\n const notices = planNotices(tree);\n if (notices.length) {\n result.diagnostics = [...result.diagnostics, ...notices].sort(bySeverity);\n result.worstSeverity = result.diagnostics.reduce<Severity | null>(\n (worst, d) => (worst === null ? d.severity : maxSeverity(worst, d.severity)),\n null,\n );\n }\n return result;\n}\n\nfunction selectStatement(trees: PlanTree[], statement?: number): PlanTree {\n if (statement !== undefined) {\n const tree = trees[statement - 1];\n if (!tree) {\n throw opError(\"PGX_MULTIPLE_STATEMENTS\", {\n detail: `--statement ${statement} is out of range; the input has ${trees.length} statement(s).`,\n });\n }\n return tree;\n }\n const first = trees[0];\n if (!first) throw opError(\"PGX_UNEXPECTED_PLAN_SHAPE\"); // schema guarantees ≥1, defensive\n return first;\n}\n\n/** Informational diagnostics about the plan's completeness (cost-only, no buffers, …). */\nfunction planNotices(tree: PlanTree): Diagnostic[] {\n const notices: Diagnostic[] = [];\n if (!tree.hasAnalyze) notices.push(opDiagnostic(\"PGX_COST_ONLY_PLAN\"));\n else if (!tree.hasBuffers) notices.push(opDiagnostic(\"PGX_NO_BUFFERS\"));\n\n const nodes = flatten(tree.root);\n const trivial = nodes.length === 1 && /^(Result|Values? Scan)$/.test(tree.root.nodeType);\n if (trivial) notices.push(opDiagnostic(\"PGX_EMPTY_PLAN\"));\n\n return notices;\n}\n\nexport { runAdvisor } from \"./advisor/index.ts\";\nexport { DEFAULT_CONFIG, DEFAULT_THRESHOLDS, type PgExplainConfig } from \"./config.ts\";\nexport { bottlenecks, computeMetrics, executionMs, nodeLabel } from \"./core/metrics.ts\";\nexport type * from \"./core/model.ts\";\nexport { flatten, parseExplainJson, walk } from \"./core/parse.ts\";\nexport { AppError, scrubCredentials } from \"./diagnostics/diagnostic.ts\";\nexport { JSON_SCHEMA_VERSION } from \"./report/json.ts\";\nexport { FORMATS, type Format, isFormat, type RenderOptions, render } from \"./report/render.ts\";\nexport { ExitCode } from \"./util/exit.ts\";\n"]}
1
+ {"version":3,"sources":["../src/util/exit.ts","../src/diagnostics/diagnostic.ts","../src/diagnostics/catalog.ts","../src/config.ts","../src/core/parse-text.ts","../src/core/schema.ts","../src/core/parse.ts","../src/core/metrics.ts","../src/util/format.ts","../src/advisor/rules/util.ts","../src/advisor/rules/bitmap-lossy.ts","../src/advisor/rules/cartesian-product.ts","../src/advisor/rules/correlated-subplan.ts","../src/advisor/rules/could-be-index-only.ts","../src/advisor/rules/filter-could-be-index-cond.ts","../src/advisor/rules/hash-spill-disk.ts","../src/advisor/rules/high-filter-discard.ts","../src/advisor/rules/index-only-heap-fetches.ts","../src/advisor/rules/limit-large-offset.ts","../src/advisor/rules/low-cache-hit.ts","../src/advisor/rules/memoize-evictions.ts","../src/advisor/rules/nested-loop-large-outer.ts","../src/advisor/rules/row-misestimate.ts","../src/advisor/rules/seq-scan-large.ts","../src/advisor/rules/significant-jit.ts","../src/advisor/rules/sort-spill-disk.ts","../src/advisor/rules/trigger-time.ts","../src/advisor/rules/workers-not-launched.ts","../src/advisor/rules/index.ts","../src/advisor/index.ts","../src/input/redact.ts","../src/locks/advisor.ts","../src/report/tree.ts","../src/report/json.ts","../src/report/html.ts","../src/report/markdown.ts","../src/util/color.ts","../src/report/terminal.ts","../src/report/render.ts","../src/index.ts"],"names":["ExitCode","DOCS","actual","bottlenecks","heat"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Process exit codes. Documented in README and `pg-explain --help` so scripts and\n * CI can branch on the *kind* of failure without parsing text.\n */\nexport enum ExitCode {\n /** Report produced. Findings alone do not change this unless --strict/--fail-on. */\n Success = 0,\n /** CI gate tripped: findings present AND --strict / --fail-on threshold met. */\n CiGate = 1,\n /** Usage error: bad flags/args, refused non-SELECT, unsupported option. */\n Usage = 2,\n /** Input error: no/empty stdin and no --file, unreadable file. */\n Input = 3,\n /** Parse/validation error: not valid EXPLAIN JSON or wrong shape. */\n Parse = 4,\n /** Database error: connect/auth/permission/timeout/cancel. */\n Database = 5,\n /** pg-explain itself hit an unexpected error. */\n Internal = 70,\n /** Interrupted by SIGINT. (128 + signal number.) */\n Sigint = 130,\n}\n","import type { Diagnostic, Remediation, Severity } from \"../core/model.ts\";\nimport type { ExitCode } from \"../util/exit.ts\";\n\n/**\n * An error that carries a fully-actionable Diagnostic and a process exit code.\n * cli.ts catches these, renders the diagnostic to stderr, and exits with `exitCode`.\n * Anything NOT an AppError that reaches the top level becomes PGX_INTERNAL.\n */\nexport class AppError extends Error {\n readonly diagnostic: Diagnostic;\n readonly exitCode: ExitCode;\n\n constructor(diagnostic: Diagnostic, exitCode: ExitCode, cause?: unknown) {\n super(diagnostic.title);\n this.name = \"AppError\";\n this.diagnostic = diagnostic;\n this.exitCode = exitCode;\n if (cause !== undefined) this.cause = cause;\n }\n}\n\n/** Convenience constructor for plan-domain findings (used by advisor rules). */\nexport function finding(\n code: string,\n severity: Severity,\n parts: {\n title: string;\n detail: string;\n cause: string;\n remediation: Remediation;\n docsUrl?: string;\n location?: Diagnostic[\"location\"];\n meta?: Diagnostic[\"meta\"];\n },\n): Diagnostic {\n return { code, domain: \"plan\", severity, ...parts };\n}\n\nconst SEVERITY_RANK: Record<Severity, number> = { error: 0, warn: 1, info: 2 };\n\n/** Sort by severity (error first), keeping input order within a severity (stable). */\nexport function bySeverity(a: Diagnostic, b: Diagnostic): number {\n return SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];\n}\n\nexport function maxSeverity(a: Severity, b: Severity): Severity {\n return SEVERITY_RANK[a] <= SEVERITY_RANK[b] ? a : b;\n}\n\n/** True when `s` is at least as severe as `threshold` (error ≥ warn ≥ info). */\nexport function severityAtLeast(s: Severity, threshold: Severity): boolean {\n return SEVERITY_RANK[s] <= SEVERITY_RANK[threshold];\n}\n\n/**\n * Remove secrets from any string before it is logged, shown, or written.\n * Targets:\n * - userinfo passwords in connection URLs: postgres://user:secret@host → user:***@host\n * - libpq keyword form: password=secret → password=***\n * - PG* env-style: PGPASSWORD=secret → PGPASSWORD=***\n * - URL query params: ?password=secret&sslmode=… → ?password=***&…\n */\nexport function scrubCredentials(input: string): string {\n if (!input) return input;\n return input\n .replace(/(\\b[a-z][a-z0-9+.-]*:\\/\\/[^:/?#@\\s]+:)([^@\\s]+)(@)/gi, \"$1***$3\")\n .replace(/\\bpassword\\s*=\\s*'[^']*'/gi, \"password='***'\")\n .replace(/(\\bpassword\\s*=\\s*)([^\\s&'\"]+)/gi, \"$1***\")\n .replace(/(\\bPGPASSWORD\\s*=\\s*)([^\\s&'\"]+)/gi, \"$1***\");\n}\n","import type { Diagnostic, DiagnosticLocation, Severity } from \"../core/model.ts\";\nimport { ExitCode } from \"../util/exit.ts\";\nimport { AppError } from \"./diagnostic.ts\";\n\nconst DOCS = \"https://www.postgresql.org/docs/current\";\n\ninterface OpSpec {\n severity: Severity;\n exit: ExitCode;\n title: string;\n detail: string;\n cause: string;\n remediation: Diagnostic[\"remediation\"];\n docsUrl?: string;\n}\n\n/**\n * The operational error catalog. Every entry tells the developer WHAT happened,\n * WHY, and HOW to fix it. Codes are stable and greppable; they never change meaning.\n * Dynamic specifics (host, user, db, timeout) are injected via `overrides.detail`.\n */\nconst CATALOG = {\n PGX_AUTH_FAILED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Authentication failed\",\n detail: \"The server rejected the supplied credentials.\",\n cause:\n \"The password or role is wrong, or pg_hba.conf does not permit this role from your host.\",\n remediation: {\n summary: \"Verify the credentials and supply the password safely (never on the command line).\",\n steps: [\n \"Confirm the username and password are correct.\",\n \"Provide the password via PGPASSWORD or ~/.pgpass instead of the command line.\",\n \"Check that pg_hba.conf allows this role from your client host.\",\n ],\n commands: [\n { label: \"Set password via env\", shell: \"export PGPASSWORD=<password>\" },\n {\n label: \"Or store it (chmod 600)\",\n shell: 'echo \"<host>:<port>:<db>:<user>:<password>\" >> ~/.pgpass && chmod 600 ~/.pgpass',\n },\n ],\n },\n docsUrl: `${DOCS}/auth-pg-hba-conf.html`,\n },\n\n PGX_HOST_UNREACHABLE: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Cannot reach the PostgreSQL server\",\n detail: \"DNS resolution failed or the TCP connection was refused.\",\n cause:\n \"Wrong host/port, the server is down, or a firewall/VPN/security group is blocking the port.\",\n remediation: {\n summary: \"Verify the host and port, then probe reachability.\",\n steps: [\n \"Double-check --host and --port (or the DSN) for typos.\",\n \"Confirm the server is running and accepts TCP connections.\",\n \"Check VPN, firewall, and cloud security-group rules for the port.\",\n ],\n commands: [{ label: \"Probe reachability\", shell: \"pg_isready -h <host> -p <port>\" }],\n },\n docsUrl: `${DOCS}/libpq-connect.html`,\n },\n\n PGX_DB_NOT_FOUND: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Database does not exist\",\n detail: \"The named database was not found on the server.\",\n cause: \"The database name is misspelled or the database has not been created.\",\n remediation: {\n summary: \"List the available databases and correct the name.\",\n commands: [\n { label: \"List databases\", shell: \"psql -h <host> -U <user> -l\" },\n { label: \"Re-run with the right name\", shell: \"pg-explain run --dbname <name> ...\" },\n ],\n },\n },\n\n PGX_SSL_REQUIRED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Server requires SSL\",\n detail: \"The server requires an encrypted connection but a plaintext one was offered.\",\n cause: \"pg_hba.conf mandates SSL (e.g. `hostssl`) for this role/host.\",\n remediation: {\n summary: \"Enable SSL on the connection.\",\n commands: [\n { label: \"Require encryption\", shell: \"pg-explain run --sslmode require ...\" },\n {\n label: \"Or verify the certificate too\",\n shell: \"pg-explain run --sslmode verify-full --sslrootcert <ca.pem> ...\",\n },\n ],\n },\n docsUrl: `${DOCS}/libpq-ssl.html`,\n },\n\n PGX_SSL_VERIFY_FAILED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"TLS certificate verification failed\",\n detail: \"Under verify-full the certificate chain is untrusted or the hostname does not match.\",\n cause:\n \"The CA is not trusted locally, or the certificate's CN/SAN does not match the host you connect to.\",\n remediation: {\n summary: \"Point at the CA bundle and confirm the hostname matches the certificate.\",\n steps: [\n \"Provide the CA certificate the server's cert chains to.\",\n \"Confirm the certificate CN/SAN matches the --host value.\",\n \"Only fall back to `--sslmode require` (encryption without identity check) if you accept the risk.\",\n ],\n commands: [\n {\n label: \"Trust a CA\",\n shell: \"pg-explain run --sslmode verify-full --sslrootcert <ca.pem> ...\",\n },\n ],\n },\n docsUrl: `${DOCS}/libpq-ssl.html`,\n },\n\n PGX_CONN_TIMEOUT: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Connection timed out\",\n detail: \"The connect handshake did not complete within the connect deadline.\",\n cause: \"High network latency, an overloaded server, or a firewall silently dropping packets.\",\n remediation: {\n summary: \"Raise the connect budget and investigate the network path.\",\n commands: [\n { label: \"Increase connect timeout\", shell: \"pg-explain run --connect-timeout 30s ...\" },\n ],\n },\n docsUrl: `${DOCS}/libpq-connect.html`,\n },\n\n PGX_PERMISSION_DENIED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Permission denied\",\n detail: \"The connecting role lacks a privilege the query needs.\",\n cause:\n \"EXPLAIN must plan the query, which requires SELECT (and any referenced privileges) on the relations.\",\n remediation: {\n summary: \"Grant the missing privilege, or connect with a role that already has it.\",\n commands: [\n { label: \"Grant SELECT (run as owner)\", sql: \"GRANT SELECT ON <table> TO <role>;\" },\n ],\n },\n docsUrl: `${DOCS}/sql-grant.html`,\n },\n\n PGX_RELATION_NOT_FOUND: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Relation does not exist\",\n detail: \"A table or view referenced by the query was not found.\",\n cause: \"The name is misspelled, or it lives in a schema that is not on the search_path.\",\n remediation: {\n summary: \"Schema-qualify the relation or set the search_path.\",\n steps: [\"Check spelling and the schema.\", \"List tables with `\\\\dt` in psql.\"],\n commands: [{ label: \"Set the search path\", sql: \"SET search_path = <schema>, public;\" }],\n },\n },\n\n PGX_STATEMENT_TIMEOUT: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Statement timeout reached\",\n detail: \"statement_timeout fired while EXPLAIN ANALYZE was executing the query.\",\n cause: \"The query genuinely takes longer than the configured statement_timeout to run.\",\n remediation: {\n summary: \"Raise the timeout, or avoid executing the query at all.\",\n steps: [\n \"Raise the per-run statement timeout.\",\n \"Or get an estimate-only plan that never executes (drop --analyze).\",\n \"Or reduce measurement overhead with --timing off.\",\n ],\n commands: [\n { label: \"Raise the timeout\", shell: \"pg-explain run --statement-timeout 60s ...\" },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-client.html#GUC-STATEMENT-TIMEOUT`,\n },\n\n PGX_LOCK_TIMEOUT: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Lock timeout reached\",\n detail: \"lock_timeout elapsed while waiting to acquire a lock on a relation.\",\n cause: \"Another transaction holds a conflicting lock on a relation the query touches.\",\n remediation: {\n summary: \"Raise the lock timeout, identify the blocker, or retry off-peak.\",\n commands: [\n { label: \"Raise the lock timeout\", shell: \"pg-explain run --lock-timeout 30s ...\" },\n {\n label: \"Find blockers\",\n sql: \"SELECT * FROM pg_locks l JOIN pg_stat_activity a USING (pid) WHERE NOT l.granted;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-client.html#GUC-LOCK-TIMEOUT`,\n },\n\n PGX_QUERY_CANCELED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"Query was canceled\",\n detail: \"The query was canceled by an administrator or a signal before completing.\",\n cause:\n \"An admin pg_cancel_backend call, a resource group, or a pool limit canceled the statement.\",\n remediation: {\n summary: \"Re-run the command; if it recurs, check for admin cancellation or pool limits.\",\n },\n },\n\n PGX_UNSUPPORTED_PG_VERSION: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"EXPLAIN option not supported by this server\",\n detail: \"A requested EXPLAIN option requires a newer PostgreSQL major version.\",\n cause:\n \"Options are version-gated (e.g. SETTINGS≥12, WAL≥13, GENERIC_PLAN≥16, SERIALIZE/MEMORY≥17).\",\n remediation: {\n summary:\n \"Drop the unsupported option, target a newer server, or let pg-explain auto-omit it.\",\n commands: [{ label: \"Auto-omit unsupported options\", shell: \"pg-explain run --compat ...\" }],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_INVALID_EXPLAIN_OPTION: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"Invalid EXPLAIN option combination\",\n detail: \"The server rejected an EXPLAIN option or a mutually-exclusive combination.\",\n cause:\n \"Some options require ANALYZE (WAL, SERIALIZE, TIMING) and GENERIC_PLAN is incompatible with ANALYZE.\",\n remediation: {\n summary: \"Fix the option combination; see `pg-explain --help` for valid combinations.\",\n steps: [\n \"WAL/SERIALIZE/TIMING require --analyze.\",\n \"GENERIC_PLAN cannot be combined with --analyze.\",\n ],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_MALFORMED_JSON: {\n severity: \"error\",\n exit: ExitCode.Parse,\n title: \"Input is not valid JSON\",\n detail: \"The plan input could not be parsed as JSON.\",\n cause: \"The input was truncated when captured, or it is not EXPLAIN (FORMAT JSON) output.\",\n remediation: {\n summary: \"Validate the input and make sure it is FORMAT JSON output.\",\n commands: [{ label: \"Validate JSON\", shell: \"jq . plan.json\" }],\n },\n },\n\n PGX_UNEXPECTED_PLAN_SHAPE: {\n severity: \"error\",\n exit: ExitCode.Parse,\n title: \"Input is not an EXPLAIN plan\",\n detail: \"The JSON parsed but does not contain a recognizable EXPLAIN plan tree.\",\n cause: \"The 'Plan' node is missing — this may be query result rows rather than a plan.\",\n remediation: {\n summary: \"Regenerate the plan with FORMAT JSON and pipe that in.\",\n commands: [\n { label: \"Capture a plan\", sql: \"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) <your query>;\" },\n ],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_EMPTY_INPUT: {\n severity: \"error\",\n exit: ExitCode.Input,\n title: \"No plan input received\",\n detail: \"stdin and the named file were both empty.\",\n cause: \"No plan was piped in and no query/file was provided.\",\n remediation: {\n summary: \"Pipe a plan, or provide SQL to run.\",\n commands: [\n { label: \"Analyze a saved plan\", shell: \"pg-explain < plan.json\" },\n { label: \"Or run a query\", shell: 'pg-explain run --query \"<sql>\" --dsn <dsn>' },\n ],\n },\n },\n\n PGX_NON_SELECT_REFUSED: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"Refusing to ANALYZE a data-modifying statement\",\n detail: \"EXPLAIN ANALYZE executes the statement, and this one would modify data.\",\n cause:\n \"INSERT/UPDATE/DELETE/MERGE/DDL run for real under ANALYZE; running it could change your data.\",\n remediation: {\n summary:\n \"Use --force to run it inside an automatically rolled-back transaction, or drop --analyze.\",\n steps: [\n \"With --force, pg-explain wraps it as `BEGIN; <stmt>; ROLLBACK;` so nothing is committed.\",\n \"Without --analyze you get an estimate-only plan that never executes.\",\n ],\n commands: [\n {\n label: \"Run safely (auto-rollback)\",\n shell: \"pg-explain run --force --file mutation.sql --dsn <dsn>\",\n },\n ],\n },\n },\n\n PGX_MULTIPLE_STATEMENTS: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"Multiple SQL statements found\",\n detail: \"The input contains more than one statement; pg-explain analyzes one at a time.\",\n cause: \"A .sql file or --query string contained several semicolon-separated statements.\",\n remediation: {\n summary: \"Select one statement, or split them into separate invocations.\",\n commands: [\n {\n label: \"Pick the Nth statement (1-based)\",\n shell: \"pg-explain run --statement 2 --file queries.sql --dsn <dsn>\",\n },\n ],\n },\n },\n\n PGX_COST_ONLY_PLAN: {\n severity: \"info\",\n exit: ExitCode.Success,\n title: \"Cost-only plan — estimate-vs-actual checks unavailable\",\n detail: \"This plan has cost estimates but no actual row/time data.\",\n cause: \"It was produced by plain EXPLAIN (without ANALYZE), so runtime behavior is unknown.\",\n remediation: {\n summary: \"Re-run with ANALYZE to unlock estimate-vs-actual, timing, and spill findings.\",\n commands: [\n { label: \"Capture actuals\", sql: \"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) <query>;\" },\n ],\n },\n docsUrl: `${DOCS}/using-explain.html#USING-EXPLAIN-ANALYZE`,\n },\n\n PGX_NO_BUFFERS: {\n severity: \"info\",\n exit: ExitCode.Success,\n title: \"No BUFFERS data — cache/I/O analysis skipped\",\n detail: \"Buffer counters are absent, so cache-hit ratio and I/O findings cannot be computed.\",\n cause: \"The plan was captured without BUFFERS.\",\n remediation: {\n summary: \"Add BUFFERS to surface shared/temp block usage and the cache-hit ratio.\",\n commands: [\n { label: \"Capture buffers\", sql: \"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) <query>;\" },\n ],\n },\n },\n\n PGX_EMPTY_PLAN: {\n severity: \"info\",\n exit: ExitCode.Success,\n title: \"Nothing to analyze\",\n detail: \"The plan has no scans or joins to evaluate (e.g. a bare Result node).\",\n cause: \"The query is trivial and has no tuning surface.\",\n remediation: { summary: \"Confirm this is the query you intended to profile.\" },\n },\n\n PGX_PG_DRIVER_MISSING: {\n severity: \"error\",\n exit: ExitCode.Usage,\n title: \"The 'pg' driver is not installed\",\n detail: \"The run command needs the PostgreSQL driver, which is an optional dependency.\",\n cause:\n \"pgexplain ships 'pg' as optional so plan-only use stays dependency-free; it isn't installed here.\",\n remediation: {\n summary:\n \"Install the pg driver, then re-run. (Plan-only analysis from a file/stdin needs no driver.)\",\n commands: [\n { label: \"with pnpm\", shell: \"pnpm add pg\" },\n { label: \"with npm\", shell: \"npm install pg\" },\n ],\n },\n },\n\n PGX_QUERY_FAILED: {\n severity: \"error\",\n exit: ExitCode.Database,\n title: \"The query could not be planned or executed\",\n detail: \"PostgreSQL returned an error while running EXPLAIN.\",\n cause:\n \"The statement has a syntax error, references something invalid, or hit a server-side limit.\",\n remediation: {\n summary:\n \"Read the server message below, fix the statement, and re-run. Test it in psql first if unsure.\",\n commands: [{ label: \"Try it directly\", shell: 'psql \"<dsn>\" -c \"EXPLAIN <your statement>\"' }],\n },\n docsUrl: `${DOCS}/sql-explain.html`,\n },\n\n PGX_INTERNAL: {\n severity: \"error\",\n exit: ExitCode.Internal,\n title: \"pg-explain hit an unexpected error\",\n detail: \"This is a bug in pg-explain, not in your query or plan.\",\n cause: \"An unhandled condition was reached.\",\n remediation: {\n summary: \"Re-run with --debug for a credential-scrubbed stack trace, then file an issue.\",\n commands: [\n { label: \"Show the trace\", shell: \"pg-explain --debug ...\" },\n { label: \"Report your version\", shell: \"pg-explain --version\" },\n ],\n },\n },\n} satisfies Record<string, OpSpec>;\n\nexport type OpCode = keyof typeof CATALOG;\n\n/** Every operational code, for iteration (docs generation, completeness tests). */\nexport const OP_CODES = Object.keys(CATALOG) as OpCode[];\n\ninterface OpOverrides {\n /** Replace the default detail with situation-specific text (will be credential-scrubbed by the caller). */\n detail?: string;\n meta?: Diagnostic[\"meta\"];\n location?: DiagnosticLocation;\n}\n\n/** Build the Diagnostic for an operational code (used for info-level, non-fatal notices). */\nexport function opDiagnostic(code: OpCode, overrides: OpOverrides = {}): Diagnostic {\n const spec: OpSpec = CATALOG[code];\n const diag: Diagnostic = {\n code,\n domain: \"operational\",\n severity: spec.severity,\n title: spec.title,\n detail: overrides.detail ?? spec.detail,\n cause: spec.cause,\n remediation: spec.remediation,\n };\n if (spec.docsUrl) diag.docsUrl = spec.docsUrl;\n if (overrides.location) diag.location = overrides.location;\n if (overrides.meta) diag.meta = overrides.meta;\n return diag;\n}\n\n/** Build a throwable AppError for an operational code, with the correct exit code. */\nexport function opError(code: OpCode, overrides: OpOverrides = {}, cause?: unknown): AppError {\n return new AppError(opDiagnostic(code, overrides), CATALOG[code].exit, cause);\n}\n\nexport function exitCodeFor(code: OpCode): ExitCode {\n return CATALOG[code].exit;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Severity, Thresholds } from \"./core/model.ts\";\nimport { opError } from \"./diagnostics/catalog.ts\";\n\nexport interface RuleConfig {\n enabled?: boolean;\n severity?: Severity;\n}\n\nexport interface PgExplainConfig {\n thresholds: Thresholds;\n /** Per-rule enable/disable and severity overrides, keyed by rule id. */\n rules: Record<string, RuleConfig>;\n}\n\nexport const DEFAULT_THRESHOLDS: Thresholds = {\n seqScanRows: 100_000,\n nestedLoopOuterRows: 10_000,\n filterDiscardRatio: 0.9,\n filterRemovedAbs: 10_000,\n misestimateFactor: 10,\n heapFetchRatio: 0.1,\n heapFetchAbs: 1_000,\n correlatedLoops: 1_000,\n jitPct: 25,\n triggerPct: 10,\n lowCacheHitRatio: 0.9,\n limitDiscardRows: 10_000,\n staleStatsModRatio: 0.2,\n};\n\nexport const DEFAULT_CONFIG: PgExplainConfig = {\n thresholds: { ...DEFAULT_THRESHOLDS },\n rules: {},\n};\n\nconst CONFIG_FILES = [\".pgexplainrc.json\", \".pgexplainrc\"];\n\n/** A partial config as it appears in a config file (all fields optional). */\ninterface PartialConfig {\n thresholds?: Partial<Thresholds>;\n rules?: Record<string, RuleConfig>;\n}\n\nfunction merge(partial: PartialConfig): PgExplainConfig {\n return {\n thresholds: { ...DEFAULT_THRESHOLDS, ...(partial.thresholds ?? {}) },\n rules: { ...(partial.rules ?? {}) },\n };\n}\n\nasync function readJson(path: string): Promise<unknown> {\n let text: string;\n try {\n text = await readFile(path, \"utf8\");\n } catch (err) {\n throw opError(\n \"PGX_EMPTY_INPUT\",\n {\n detail: `Could not read config '${path}': ${err instanceof Error ? err.message : String(err)}`,\n },\n err,\n );\n }\n try {\n return JSON.parse(text);\n } catch (err) {\n throw opError(\n \"PGX_MALFORMED_JSON\",\n {\n detail: `Config '${path}' is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n },\n err,\n );\n }\n}\n\n/**\n * Load config: an explicit --config path, else a `.pgexplainrc[.json]` or a\n * `pgExplain` key in package.json in cwd. Missing config is fine (returns defaults);\n * an unreadable/invalid explicit path is an actionable error.\n */\nexport async function loadConfig(\n explicitPath: string | undefined,\n cwd = process.cwd(),\n): Promise<PgExplainConfig> {\n if (explicitPath) return merge((await readJson(explicitPath)) as PartialConfig);\n\n for (const name of CONFIG_FILES) {\n try {\n const text = await readFile(join(cwd, name), \"utf8\");\n return merge(JSON.parse(text) as PartialConfig);\n } catch {\n // not present / unreadable — try the next source\n }\n }\n\n try {\n const pkg = JSON.parse(await readFile(join(cwd, \"package.json\"), \"utf8\")) as {\n pgExplain?: PartialConfig;\n };\n if (pkg.pgExplain) return merge(pkg.pgExplain);\n } catch {\n // no package.json or no key — fall through to defaults\n }\n\n return { ...DEFAULT_CONFIG, thresholds: { ...DEFAULT_THRESHOLDS }, rules: {} };\n}\n","/**\n * Plain-text `EXPLAIN [ANALYZE]` parser (psql / pgAdmin output).\n *\n * Ported from pev2's text parser (Dalibo, PostgreSQL license) —\n * https://github.com/dalibo/pev2 `src/services/plan-service.ts` `fromText`/`splitIntoLines`.\n * Rather than build a bespoke node type, this emits `RawPlan` objects keyed with the SAME\n * names PostgreSQL uses in `FORMAT JSON` (`\"Node Type\"`, `\"Actual Rows\"`, `\"Shared Hit Blocks\"`, …)\n * and hands them to the existing `normalizeNode` via `statementToTree` — so text and JSON plans\n * flow through one normalization path and behave identically downstream.\n *\n * Unlike pev2 (which keeps `\"Seq Scan on orders\"` as the node label), we split the scan target\n * out of the type line into `Relation Name` / `Index Name` / `Schema` / `Alias`, matching JSON,\n * so advisor rules that match `nodeType === \"Seq Scan\"` fire on text plans too.\n */\n\nimport type { RawPlan } from \"./model.ts\";\nimport type { RawStatement } from \"./parse.ts\";\n\nconst cap = (w: string): string => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n\nconst numeric = (v: string): string | number => {\n const t = v.trim();\n return /^-?\\d+(\\.\\d+)?$/.test(t) ? Number(t) : t;\n};\n\n/** Split a projection/key list on top-level commas (parenthesis-aware). */\nfunction splitList(s: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let cur = \"\";\n for (const ch of s) {\n if (ch === \"(\") depth++;\n else if (ch === \")\") depth--;\n if (ch === \",\" && depth === 0) {\n if (cur.trim()) out.push(cur.trim());\n cur = \"\";\n } else {\n cur += ch;\n }\n }\n if (cur.trim()) out.push(cur.trim());\n return out;\n}\n\n/**\n * Rejoin lines that a fixed-width terminal / pgAdmin has force-wrapped. Faithful port of pev2's\n * `splitIntoLines`: a line continues the previous one when parentheses are unbalanced, when it\n * starts with `(`, or when the previous info line ended in a comma at a different indent.\n */\nfunction splitIntoLines(text: string): string[] {\n const out: string[] = [];\n const lines = text.split(/\\r?\\n/);\n const count = (s: string, re: RegExp) => (s.match(re) || []).length;\n const closingFirst = (s: string) => {\n const c = s.indexOf(\")\");\n const o = s.indexOf(\"(\");\n return c !== -1 && c < o;\n };\n const sameIndent = (a: string, b: string) => a.search(/\\S/) === b.search(/\\S/);\n\n for (const line of lines) {\n const prev = out[out.length - 1];\n if (prev && count(prev, /\\)/g) !== count(prev, /\\(/g)) {\n out[out.length - 1] += line;\n } else if (\n /^(?:Total\\s+runtime|Planning(\\s+time)?|Execution\\s+time|Time|Filter|Output|JIT|Trigger|Settings|Serialization)/i.test(\n line,\n )\n ) {\n out.push(line);\n } else if (/^\\S/.test(line) || /^\\s*\\(/.test(line) || closingFirst(line)) {\n // A col-0 line rejoins a force-wrapped previous line — but never across a blank\n // separator, which delimits statements.\n if (prev) out[out.length - 1] += line;\n else out.push(line);\n } else if (prev && /,\\s*$/.test(prev) && !sameIndent(prev, line) && !/^\\s*->/i.test(line)) {\n out[out.length - 1] += line;\n } else {\n out.push(line);\n }\n }\n return out;\n}\n\n// ── the node line: `-> [Partial ]Type on rel (cost=… rows=… width=…) (actual …|never executed)` ──\n\nconst estimation = String.raw`\\(cost=(\\d+\\.\\d+)\\.\\.(\\d+\\.\\d+)\\s+rows=(\\d+)\\s+width=(\\d+)\\)`;\nconst actual = String.raw`(?:actual(?:\\stime=(\\d+\\.\\d+)\\.\\.(\\d+\\.\\d+))?\\srows=(\\d+(?:\\.\\d+)?)\\sloops=(\\d+)|(never\\s+executed))`;\nconst nodeRe = new RegExp(\n String.raw`^(\\s*->\\s*|\\s*)(Finalize|Simple|Partial)*\\s*([^\\r\\n\\t\\f\\v(]*?)\\s*` +\n String.raw`(?:(?:${estimation}\\s+\\(${actual}\\))|(?:${estimation})|(?:\\(${actual}\\)))\\s*$`,\n);\n// Node-line capture groups (mirrors pev2's NodeMatch): 1 prefix, 2 partial, 3 type,\n// 4-7 cost/rows/width (branch A), 8-12 actual (branch A, 12=never), 13-16 (branch B), 17-21 (branch C).\n\nconst subRe = /^((?:Sub|Init)Plan)\\s*(?:\\d+\\s*)?(?:\\(returns.*\\))?\\s*$/;\nconst cteRe = /^CTE\\s+(\\S+)\\s*$/;\nconst workerRe =\n /^Worker\\s+(\\d+):\\s+(?:actual(?:\\stime=(\\d+\\.\\d+)\\.\\.(\\d+\\.\\d+))?\\srows=(\\d+(?:\\.\\d+)?)\\sloops=(\\d+)|never\\s+executed)(.*)$/;\nconst triggerRe = /^Trigger\\s+(.*):\\s+time=(\\d+\\.\\d+)\\s+calls=(\\d+)\\s*$/;\nconst headerRe = /^(QUERY PLAN|-{2,}|#|\\(\\d+ rows?\\))/;\n\n/** Break `Index Scan using idx on public.orders o` into JSON-equivalent parts. */\nfunction splitNodeType(text: string): Partial<RawPlan> & { \"Node Type\": string } {\n let s = text.trim();\n let indexName: string | undefined;\n let relationName: string | undefined;\n let schema: string | undefined;\n let alias: string | undefined;\n\n const using = s.match(/\\susing (\\S+)/);\n if (using?.[1]) {\n indexName = using[1];\n s = s.replace(using[0] ?? \"\", \"\");\n }\n const on = s.match(/\\son (\\S+?)(?:\\s+(\\S+))?\\s*$/);\n if (on?.[1]) {\n let rel = on[1];\n alias = on[2];\n const dot = rel.lastIndexOf(\".\");\n if (dot !== -1) {\n schema = rel.slice(0, dot);\n rel = rel.slice(dot + 1);\n }\n relationName = rel;\n s = s.slice(0, on.index).trim();\n }\n // Postgres text prefixes \"Parallel \" onto the type; JSON keeps it in a separate flag. Drop it so\n // the normalized nodeType matches JSON (parallelism is still visible via Workers Planned/Launched).\n const nodeType = s.replace(/^Parallel\\s+/, \"\").trim();\n\n // For a Bitmap Index Scan the `on <x>` target is the index, not a relation.\n if (nodeType === \"Bitmap Index Scan\" && relationName && !indexName) {\n indexName = relationName;\n relationName = undefined;\n schema = undefined;\n alias = undefined;\n }\n\n const out: Partial<RawPlan> & { \"Node Type\": string } = { \"Node Type\": nodeType };\n if (relationName) out[\"Relation Name\"] = relationName;\n if (indexName) out[\"Index Name\"] = indexName;\n if (schema) out.Schema = schema;\n if (alias && alias !== relationName) out.Alias = alias;\n return out;\n}\n\n// ── detail-line parsers → set JSON-keyed fields on the current node ────────────\n\nfunction parseSort(text: string, node: RawPlan): boolean {\n const m = text.match(/^Sort Method:\\s+(.*?)\\s+(Memory|Disk):\\s+(\\S+)kB\\s*$/);\n if (!m?.[1] || !m[2] || m[3] === undefined) return false;\n node[\"Sort Method\"] = m[1].trim();\n node[\"Sort Space Type\"] = m[2];\n node[\"Sort Space Used\"] = Number(m[3]);\n return true;\n}\n\nfunction parseBuffers(text: string, node: RawPlan): boolean {\n const m = text.match(/^Buffers:\\s+(.*)$/);\n if (!m?.[1]) return false;\n for (const group of m[1].split(/,\\s+/)) {\n const g = group.match(/^(shared|temp|local)\\s+(.*)$/);\n if (!g?.[1] || g[2] === undefined) continue;\n const type = cap(g[1]);\n for (const kv of g[2].trim().split(/\\s+/)) {\n const [method, value] = kv.split(\"=\");\n if (method && value !== undefined) node[`${type} ${cap(method)} Blocks`] = Number(value);\n }\n }\n return true;\n}\n\nfunction parseWal(text: string, node: RawPlan): boolean {\n const m = text.match(/^WAL:\\s+(.*)$/);\n if (!m?.[1]) return false;\n for (const kv of m[1].trim().split(/\\s+/)) {\n const [k, value] = kv.split(\"=\");\n if (!k || value === undefined) continue;\n node[`WAL ${k === \"fpi\" ? \"FPI\" : cap(k)}`] = Number(value);\n }\n return true;\n}\n\nfunction parseIoTimings(text: string, node: RawPlan): boolean {\n const m = text.match(/^I\\/O Timings:\\s+(.*)$/);\n if (!m?.[1]) return false;\n const read = m[1].match(/(?:^|\\s)read=(\\d+(?:\\.\\d+)?)/);\n const write = m[1].match(/(?:^|\\s)write=(\\d+(?:\\.\\d+)?)/);\n if (read?.[1]) node[\"I/O Read Time\"] = Number(read[1]);\n if (write?.[1]) node[\"I/O Write Time\"] = Number(write[1]);\n return true;\n}\n\n/** `search_path = 'x', work_mem = '4MB'` → { search_path: \"x\", work_mem: \"4MB\" }. */\nfunction parseSettings(text: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const pair of splitList(text)) {\n const m = pair.match(/^(\\S+)\\s*=\\s*(.*)$/);\n if (m?.[1] && m[2] !== undefined) out[m[1]] = m[2].replace(/^'|'$/g, \"\");\n }\n return out;\n}\n\nconst LIST_KEYS = new Set([\"Output\", \"Sort Key\", \"Presorted Key\", \"Group Key\"]);\n\ninterface Frame {\n depth: number;\n node: RawPlan;\n /** Set when this frame is a Sub/Init/CTE header; children get this relationship. */\n rel?: \"SubPlan\" | \"InitPlan\";\n name?: string;\n}\n\n/**\n * Parse plain-text EXPLAIN output into one or more `RawStatement` objects (the same shape JSON\n * yields before normalization). Multiple statements separated by blank lines each start a new tree.\n */\nexport function parseTextToStatements(input: string): RawStatement[] {\n const statements: RawStatement[] = [];\n let stmt: RawStatement | null = null;\n let stack: Frame[] = [];\n let current: RawPlan | null = null; // node that trailing detail lines attach to\n let jit: Record<string, unknown> | null = null; // active `JIT:` block, if any\n\n const finish = () => {\n if (stmt?.Plan) statements.push(stmt);\n stmt = null;\n stack = [];\n current = null;\n jit = null;\n };\n\n for (let raw of splitIntoLines(input)) {\n // pgAdmin wraps each line in quotes; tabs vary. Normalize, then measure indent.\n raw = raw.replace(/\"\\s*$/, \"\").replace(/^\\s*\"/, \"\").replace(/\\t/g, \" \");\n const depth = raw.match(/^\\s*/)?.[0].length ?? 0;\n const line = raw.slice(depth);\n\n if (line === \"\" || headerRe.test(line)) {\n if (line === \"\" && stmt?.Plan) finish(); // blank line after a plan ends the statement\n continue;\n }\n\n const nodeM = nodeRe.exec(line);\n const subM = subRe.exec(line);\n const cteM = cteRe.exec(line);\n\n if (nodeM && !subM && !cteM) {\n if (!stmt) stmt = {} as RawStatement;\n jit = null;\n const node: RawPlan = { ...splitNodeType(nodeM[3] ?? \"\") };\n if (nodeM[2]) node[\"Partial Mode\"] = nodeM[2];\n\n const startup = nodeM[4] ?? nodeM[13];\n const total = nodeM[5] ?? nodeM[14];\n if (startup && total) {\n node[\"Startup Cost\"] = Number(startup);\n node[\"Total Cost\"] = Number(total);\n node[\"Plan Rows\"] = Number(nodeM[6] ?? nodeM[15]);\n node[\"Plan Width\"] = Number(nodeM[7] ?? nodeM[16]);\n }\n const st = nodeM[8] ?? nodeM[17];\n const tt = nodeM[9] ?? nodeM[18];\n if (st && tt) {\n node[\"Actual Startup Time\"] = Number(st);\n node[\"Actual Total Time\"] = Number(tt);\n }\n const rows = nodeM[10] ?? nodeM[19];\n const loops = nodeM[11] ?? nodeM[20];\n if (rows && loops) {\n node[\"Actual Rows\"] = Number(rows);\n node[\"Actual Loops\"] = Number(loops);\n }\n if (nodeM[12] ?? nodeM[21]) {\n node[\"Actual Loops\"] = 0;\n node[\"Actual Rows\"] = 0;\n }\n\n // Attach to the tree.\n stack = stack.filter((f) => f.depth < depth);\n const parent = stack[stack.length - 1];\n if (!parent) {\n stmt.Plan = node;\n } else {\n if (parent.rel) {\n node[\"Parent Relationship\"] = parent.rel;\n if (parent.name) node[\"Subplan Name\"] = parent.name;\n }\n const parentNode = parent.node;\n if (!parentNode.Plans) parentNode.Plans = [];\n parentNode.Plans.push(node);\n }\n stack.push({ depth, node });\n current = node;\n continue;\n }\n\n if (subM || cteM) {\n stack = stack.filter((f) => f.depth < depth);\n const parent = stack[stack.length - 1];\n if (!parent) continue;\n if (cteM?.[1])\n stack.push({ depth, node: parent.node, rel: \"InitPlan\", name: `CTE ${cteM[1]}` });\n else if (subM?.[1])\n stack.push({\n depth,\n node: parent.node,\n rel: subM[1] as \"SubPlan\" | \"InitPlan\",\n name: (subM[0] ?? \"\").trim(),\n });\n continue;\n }\n\n const workerM = workerRe.exec(line);\n if (workerM && current) {\n const worker: Record<string, unknown> = { \"Worker Number\": Number(workerM[1]) };\n if (workerM[2] && workerM[3]) {\n worker[\"Actual Startup Time\"] = Number(workerM[2]);\n worker[\"Actual Total Time\"] = Number(workerM[3]);\n }\n if (workerM[4] && workerM[5]) {\n worker[\"Actual Rows\"] = Number(workerM[4]);\n worker[\"Actual Loops\"] = Number(workerM[5]);\n }\n if (!Array.isArray(current.Workers)) current.Workers = [];\n (current.Workers as Record<string, unknown>[]).push(worker);\n continue;\n }\n\n const trigM = triggerRe.exec(line);\n if (trigM && stmt) {\n if (!Array.isArray(stmt.Triggers)) stmt.Triggers = [];\n (stmt.Triggers as unknown[]).push({\n \"Trigger Name\": trigM[1],\n Time: Number(trigM[2]),\n Calls: Number(trigM[3]),\n });\n continue;\n }\n\n // key: value detail / statement-level line\n const kv = line.match(/^([^:]+):\\s*(.*)$/);\n if (!kv?.[1]) continue;\n const key = kv[1].trim();\n const value = (kv[2] ?? \"\").trim();\n\n if (key === \"JIT\") {\n jit = {};\n if (stmt) stmt.JIT = jit;\n continue;\n }\n if (jit) {\n if (key === \"Functions\") jit.Functions = Number(value);\n else if (key === \"Timing\") {\n const timing: Record<string, unknown> = {};\n for (const part of value.split(/,\\s*/)) {\n const t = part.match(/^(\\S+)\\s+(\\d+\\.\\d+)\\s*ms/);\n if (t?.[1]) timing[t[1]] = Number(t[2]);\n }\n jit.Timing = timing;\n }\n continue;\n }\n\n if (key === \"Planning Time\") {\n if (stmt) stmt[\"Planning Time\"] = parseFloat(value);\n continue;\n }\n if (key === \"Execution Time\" || key === \"Total runtime\") {\n if (stmt) stmt[\"Execution Time\"] = parseFloat(value);\n continue;\n }\n if (key === \"Settings\") {\n if (stmt) stmt.Settings = parseSettings(value);\n continue;\n }\n\n if (!current) continue;\n if (\n parseSort(line, current) ||\n parseBuffers(line, current) ||\n parseWal(line, current) ||\n parseIoTimings(line, current)\n ) {\n continue;\n }\n current[key] = LIST_KEYS.has(key) ? splitList(value) : numeric(value);\n }\n\n finish();\n return statements;\n}\n","import { z } from \"zod\";\n\n/**\n * Version-tolerant validation for EXPLAIN (FORMAT JSON) output.\n *\n * We only assert the *shape* we depend on (\"Node Type\" + recursive \"Plans\"); every\n * other field is accepted and preserved via looseObject so plans from PG 14 → 18\n * validate identically. Field access happens against the original parsed JSON (the\n * `raw` node), so unknown/new fields are never lost.\n */\nconst PlanNodeSchema = z.looseObject({\n \"Node Type\": z.string(),\n get Plans() {\n return z.array(PlanNodeSchema).optional();\n },\n});\n\nconst StatementSchema = z.looseObject({\n Plan: PlanNodeSchema,\n \"Planning Time\": z.number().optional(),\n \"Execution Time\": z.number().optional(),\n Triggers: z.array(z.looseObject({})).optional(),\n JIT: z.looseObject({}).optional(),\n Settings: z.record(z.string(), z.unknown()).optional(),\n});\n\n/** EXPLAIN FORMAT JSON is an array of statements (usually one). */\nexport const ExplainOutputSchema = z.array(StatementSchema).min(1);\n\nexport type ExplainOutput = z.infer<typeof ExplainOutputSchema>;\nexport type ExplainStatement = z.infer<typeof StatementSchema>;\n","import { opError } from \"../diagnostics/catalog.ts\";\nimport type { JitInfo, PlanNode, PlanTree, RawPlan, TriggerInfo, WorkerStat } from \"./model.ts\";\nimport { parseTextToStatements } from \"./parse-text.ts\";\nimport { ExplainOutputSchema } from \"./schema.ts\";\n\n// ── safe field readers ────────────────────────────────────────────────────────\n\nfunction num(raw: RawPlan, key: string): number | undefined {\n const v = raw[key];\n return typeof v === \"number\" ? v : undefined;\n}\n\nfunction str(raw: RawPlan, key: string): string | undefined {\n const v = raw[key];\n return typeof v === \"string\" ? v : undefined;\n}\n\nfunction strArray(raw: RawPlan, key: string): string[] | undefined {\n const v = raw[key];\n if (Array.isArray(v) && v.every((x) => typeof x === \"string\")) return v as string[];\n if (typeof v === \"string\") return [v];\n return undefined;\n}\n\n// ── JSON parse with line/column for actionable malformed-input errors ─────────\n\nfunction parseJsonWithLocation(input: string): unknown {\n try {\n return JSON.parse(input);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n let line: number | undefined;\n let col: number | undefined;\n\n const lc = message.match(/line (\\d+) column (\\d+)/i);\n if (lc?.[1] && lc[2]) {\n line = Number(lc[1]);\n col = Number(lc[2]);\n } else {\n const pos = message.match(/position (\\d+)/i);\n if (pos?.[1]) {\n const offset = Number(pos[1]);\n const before = input.slice(0, offset);\n line = before.split(\"\\n\").length;\n col = offset - before.lastIndexOf(\"\\n\");\n }\n }\n\n const where = line && col ? ` (line ${line}, col ${col})` : \"\";\n throw opError(\n \"PGX_MALFORMED_JSON\",\n {\n detail: `The plan input could not be parsed as JSON${where}: ${message}`,\n location: line && col ? { kind: \"input\", line, col } : { kind: \"input\" },\n },\n err,\n );\n }\n}\n\n// ── normalization ─────────────────────────────────────────────────────────────\n\nfunction normalizeNode(raw: RawPlan, nextId: () => number): PlanNode {\n const node: PlanNode = {\n id: nextId(),\n nodeType: raw[\"Node Type\"],\n planRows: num(raw, \"Plan Rows\") ?? 0,\n children: [],\n metrics: {},\n raw,\n };\n\n assign(node, {\n parentRelationship: str(raw, \"Parent Relationship\"),\n subplanName: str(raw, \"Subplan Name\"),\n relationName: str(raw, \"Relation Name\"),\n schema: str(raw, \"Schema\"),\n alias: str(raw, \"Alias\"),\n indexName: str(raw, \"Index Name\"),\n planWidth: num(raw, \"Plan Width\"),\n startupCost: num(raw, \"Startup Cost\"),\n totalCost: num(raw, \"Total Cost\"),\n actualRows: num(raw, \"Actual Rows\"),\n actualLoops: num(raw, \"Actual Loops\"),\n actualStartupTime: num(raw, \"Actual Startup Time\"),\n actualTotalTime: num(raw, \"Actual Total Time\"),\n filter: str(raw, \"Filter\"),\n rowsRemovedByFilter: num(raw, \"Rows Removed by Filter\"),\n indexCond: str(raw, \"Index Cond\"),\n recheckCond: str(raw, \"Recheck Cond\"),\n rowsRemovedByIndexRecheck: num(raw, \"Rows Removed by Index Recheck\"),\n heapFetches: num(raw, \"Heap Fetches\"),\n hashCond: str(raw, \"Hash Cond\"),\n joinType: str(raw, \"Join Type\"),\n joinFilter: str(raw, \"Join Filter\"),\n rowsRemovedByJoinFilter: num(raw, \"Rows Removed by Join Filter\"),\n output: strArray(raw, \"Output\"),\n sortMethod: str(raw, \"Sort Method\"),\n sortSpaceType: str(raw, \"Sort Space Type\"),\n sortSpaceUsed: num(raw, \"Sort Space Used\"),\n sortKey: strArray(raw, \"Sort Key\"),\n hashBuckets: num(raw, \"Hash Buckets\"),\n originalHashBuckets: num(raw, \"Original Hash Buckets\"),\n hashBatches: num(raw, \"Hash Batches\"),\n originalHashBatches: num(raw, \"Original Hash Batches\"),\n peakMemoryUsage: num(raw, \"Peak Memory Usage\"),\n diskUsage: num(raw, \"Disk Usage\"),\n exactHeapBlocks: num(raw, \"Exact Heap Blocks\"),\n lossyHeapBlocks: num(raw, \"Lossy Heap Blocks\"),\n cacheHits: num(raw, \"Cache Hits\"),\n cacheMisses: num(raw, \"Cache Misses\"),\n cacheEvictions: num(raw, \"Cache Evictions\"),\n cacheOverflows: num(raw, \"Cache Overflows\"),\n sharedHitBlocks: num(raw, \"Shared Hit Blocks\"),\n sharedReadBlocks: num(raw, \"Shared Read Blocks\"),\n sharedDirtiedBlocks: num(raw, \"Shared Dirtied Blocks\"),\n sharedWrittenBlocks: num(raw, \"Shared Written Blocks\"),\n localHitBlocks: num(raw, \"Local Hit Blocks\"),\n localReadBlocks: num(raw, \"Local Read Blocks\"),\n tempReadBlocks: num(raw, \"Temp Read Blocks\"),\n tempWrittenBlocks: num(raw, \"Temp Written Blocks\"),\n ioReadTime: num(raw, \"I/O Read Time\"),\n ioWriteTime: num(raw, \"I/O Write Time\"),\n workersPlanned: num(raw, \"Workers Planned\"),\n workersLaunched: num(raw, \"Workers Launched\"),\n walRecords: num(raw, \"WAL Records\"),\n walBytes: num(raw, \"WAL Bytes\"),\n walFpi: num(raw, \"WAL FPI\"),\n });\n\n const workers = parseWorkers(raw.Workers);\n if (workers.length) node.workers = workers;\n\n const childPlans = raw.Plans;\n if (Array.isArray(childPlans)) {\n for (const child of childPlans) {\n node.children.push(normalizeNode(child, nextId));\n }\n }\n return node;\n}\n\n/** Copy only the defined keys, so optional fields stay absent (not `undefined`). */\nfunction assign<T extends object>(target: T, fields: Partial<T>): void {\n for (const [k, v] of Object.entries(fields)) {\n if (v !== undefined) (target as Record<string, unknown>)[k] = v;\n }\n}\n\nfunction parseWorkers(raw: unknown): WorkerStat[] {\n if (!Array.isArray(raw)) return [];\n const out: WorkerStat[] = [];\n for (const w of raw) {\n const r = w as RawPlan;\n const number = num(r, \"Worker Number\");\n if (number === undefined) continue;\n const stat: WorkerStat = { number };\n assign(stat, {\n actualRows: num(r, \"Actual Rows\"),\n actualLoops: num(r, \"Actual Loops\"),\n actualStartupTime: num(r, \"Actual Startup Time\"),\n actualTotalTime: num(r, \"Actual Total Time\"),\n });\n out.push(stat);\n }\n return out;\n}\n\nfunction parseTriggers(raw: unknown): TriggerInfo[] {\n if (!Array.isArray(raw)) return [];\n return raw.map((t) => {\n const r = t as RawPlan;\n const info: TriggerInfo = {};\n assign(info, {\n name: str(r, \"Trigger Name\"),\n constraintName: str(r, \"Constraint Name\"),\n relation: str(r, \"Relation\"),\n calls: num(r, \"Calls\"),\n time: num(r, \"Time\"),\n });\n return info;\n });\n}\n\nfunction parseJit(raw: unknown): JitInfo | undefined {\n if (!raw || typeof raw !== \"object\") return undefined;\n const r = raw as RawPlan;\n const timing = r.Timing as RawPlan | undefined;\n const jit: JitInfo = {};\n const functions = num(r, \"Functions\");\n if (functions !== undefined) jit.functions = functions;\n if (timing && typeof timing === \"object\") {\n jit.timing = {\n total: num(timing, \"Total\"),\n generation: num(timing, \"Generation\"),\n inlining: num(timing, \"Inlining\"),\n optimization: num(timing, \"Optimization\"),\n emission: num(timing, \"Emission\"),\n };\n }\n return jit;\n}\n\n/** One EXPLAIN statement, before normalization — the JSON `[{ \"Plan\": … }]` shape. */\nexport interface RawStatement {\n Plan: RawPlan;\n \"Planning Time\"?: number;\n \"Execution Time\"?: number;\n Triggers?: unknown;\n JIT?: unknown;\n Settings?: unknown;\n [key: string]: unknown;\n}\n\n/** Build a normalized PlanTree from one statement object (JSON- or text-parsed). */\nexport function statementToTree(stmt: RawStatement): PlanTree {\n let id = 0;\n const root = normalizeNode(stmt.Plan, () => id++);\n const hasAnalyze = root.actualLoops !== undefined || stmt[\"Execution Time\"] !== undefined;\n const hasBuffers = root.sharedHitBlocks !== undefined || root.sharedReadBlocks !== undefined;\n\n const tree: PlanTree = {\n root,\n triggers: parseTriggers(stmt.Triggers),\n hasAnalyze,\n hasBuffers,\n raw: stmt.Plan,\n };\n if (typeof stmt[\"Planning Time\"] === \"number\") tree.planningTime = stmt[\"Planning Time\"];\n if (typeof stmt[\"Execution Time\"] === \"number\") tree.executionTime = stmt[\"Execution Time\"];\n const serialization = stmt.Serialization;\n if (serialization && typeof serialization === \"object\") {\n const t = num(serialization as RawPlan, \"Time\");\n if (t !== undefined) tree.serializationTime = t;\n }\n const jit = parseJit(stmt.JIT);\n if (jit) tree.jit = jit;\n if (stmt.Settings) tree.settings = stmt.Settings as Record<string, string>;\n return tree;\n}\n\n/**\n * Parse EXPLAIN input into one PlanTree per statement, auto-detecting the format:\n * JSON (`[`/`{`) → parseExplainJson, otherwise plain-text `EXPLAIN` output.\n */\nexport function parseExplain(input: string): PlanTree[] {\n return /^\\s*[[{]/.test(input) ? parseExplainJson(input) : parseExplainText(input);\n}\n\n/** Parse plain-text `EXPLAIN [ANALYZE]` output (psql/pgAdmin) into PlanTrees. */\nexport function parseExplainText(input: string): PlanTree[] {\n return parseTextToStatements(input).map(statementToTree);\n}\n\n/**\n * Parse EXPLAIN (FORMAT JSON) text into one PlanTree per statement.\n * Accepts the standard `[{ \"Plan\": … }]`, a bare statement object, or a bare plan node.\n * Throws AppError(PGX_MALFORMED_JSON | PGX_UNEXPECTED_PLAN_SHAPE) with a location.\n */\nexport function parseExplainJson(input: string): PlanTree[] {\n const json = parseJsonWithLocation(input);\n\n // Normalize the accepted shapes into the canonical array-of-statements.\n let candidate: unknown = json;\n if (json && typeof json === \"object\" && !Array.isArray(json)) {\n const obj = json as Record<string, unknown>;\n candidate = \"Plan\" in obj ? [obj] : \"Node Type\" in obj ? [{ Plan: obj }] : json;\n }\n\n const result = ExplainOutputSchema.safeParse(candidate);\n if (!result.success) {\n throw opError(\"PGX_UNEXPECTED_PLAN_SHAPE\", {\n detail: `The JSON is valid but is not an EXPLAIN plan: ${result.error.issues[0]?.message ?? \"missing 'Plan' node\"}.`,\n location: { kind: \"input\" },\n });\n }\n\n return result.data.map((stmt) => statementToTree(stmt as unknown as RawStatement));\n}\n\n/** Depth-first pre-order walk (root first). Used by metrics and the advisor. */\nexport function walk(node: PlanNode, visit: (n: PlanNode) => void): void {\n visit(node);\n for (const child of node.children) walk(child, visit);\n}\n\n/** Flatten a tree to an array in pre-order. */\nexport function flatten(node: PlanNode): PlanNode[] {\n const out: PlanNode[] = [];\n walk(node, (n) => out.push(n));\n return out;\n}\n","import type { PlanNode, PlanTree } from \"./model.ts\";\nimport { flatten, walk } from \"./parse.ts\";\n\n/**\n * Fill `node.metrics` for every node. All row/time figures are PER-LOOP corrected:\n * Postgres reports \"Actual Rows\"/\"Actual Total Time\" as the average of a single loop,\n * so the true total is `× \"Actual Loops\"`. Buffer counters are already cumulative and\n * are NOT multiplied. No-ops cleanly on cost-only plans (leaves metrics empty).\n */\nexport function computeMetrics(tree: PlanTree): void {\n // Pass 1 — per-node quantities that don't depend on siblings/children.\n walk(tree.root, (node) => {\n const { actualRows, actualLoops, actualTotalTime } = node;\n\n if (actualRows !== undefined && actualLoops !== undefined) {\n node.metrics.totalRows = actualRows * actualLoops;\n }\n if (actualTotalTime !== undefined && actualLoops !== undefined) {\n node.metrics.inclusiveMs = actualTotalTime * actualLoops;\n }\n\n // Estimate vs actual (only meaningful with actuals).\n if (node.metrics.totalRows !== undefined) {\n const est = Math.max(node.planRows, 1);\n const act = Math.max(node.metrics.totalRows, 1);\n node.metrics.estimateFactor = est >= act ? est / act : act / est;\n node.metrics.estimateDirection =\n node.planRows > node.metrics.totalRows\n ? \"over\"\n : node.metrics.totalRows > node.planRows\n ? \"under\"\n : \"accurate\";\n }\n\n // Cache-hit ratio from shared buffers (cumulative — no ×loops).\n const hit = node.sharedHitBlocks ?? 0;\n const read = node.sharedReadBlocks ?? 0;\n node.metrics.cacheHitRatio = hit + read > 0 ? hit / (hit + read) : null;\n\n // Filter discard ratio (per-loop corrected).\n if (node.rowsRemovedByFilter !== undefined && actualLoops !== undefined) {\n const removed = node.rowsRemovedByFilter * actualLoops;\n const kept = node.metrics.totalRows ?? 0;\n const denom = removed + kept;\n if (denom > 0) node.metrics.filterDiscardRatio = removed / denom;\n }\n\n // Bitmap lossy ratio.\n if (node.lossyHeapBlocks !== undefined) {\n const lossy = node.lossyHeapBlocks;\n const exact = node.exactHeapBlocks ?? 0;\n const denom = lossy + exact;\n if (denom > 0) node.metrics.lossyRatio = lossy / denom;\n }\n });\n\n // Pass 2 — self time = inclusive − Σ(children inclusive), clamped ≥ 0.\n walk(tree.root, (node) => {\n if (node.metrics.inclusiveMs === undefined) return;\n let childrenMs = 0;\n for (const child of node.children) childrenMs += child.metrics.inclusiveMs ?? 0;\n node.metrics.selfMs = Math.max(node.metrics.inclusiveMs - childrenMs, 0);\n });\n\n // Pass 3 — % of total execution time.\n const totalMs = executionMs(tree);\n if (totalMs && totalMs > 0) {\n walk(tree.root, (node) => {\n if (node.metrics.selfMs !== undefined) {\n node.metrics.pctOfTotal = (100 * node.metrics.selfMs) / totalMs;\n }\n });\n }\n}\n\n/** Total execution time in ms: prefer the reported value, else the root's inclusive time. */\nexport function executionMs(tree: PlanTree): number | undefined {\n return tree.executionTime ?? tree.root.metrics.inclusiveMs;\n}\n\n/** Top N nodes by self time (the real bottlenecks), descending. */\nexport function bottlenecks(tree: PlanTree, n = 5): PlanNode[] {\n return flatten(tree.root)\n .filter((node) => node.metrics.selfMs !== undefined)\n .sort((a, b) => (b.metrics.selfMs ?? 0) - (a.metrics.selfMs ?? 0))\n .slice(0, n);\n}\n\nexport interface StatGroup {\n key: string;\n count: number;\n /** Summed exclusive (self) time across nodes in this group. */\n selfMs: number;\n /** Share of total execution time. */\n pctOfTotal: number;\n}\nexport interface PlanStats {\n byNodeType: StatGroup[];\n byRelation: StatGroup[];\n byIndex: StatGroup[];\n}\n\n/** Roll up exclusive time by node type / relation / index (pev2-style Stats tab). */\nexport function aggregateStats(tree: PlanTree): PlanStats {\n const total = executionMs(tree) ?? 0;\n const groupBy = (keyOf: (n: PlanNode) => string | undefined): StatGroup[] => {\n const acc = new Map<string, { count: number; selfMs: number }>();\n for (const n of flatten(tree.root)) {\n const key = keyOf(n);\n if (!key) continue;\n const e = acc.get(key) ?? { count: 0, selfMs: 0 };\n e.count++;\n e.selfMs += n.metrics.selfMs ?? 0;\n acc.set(key, e);\n }\n return [...acc.entries()]\n .map(([key, e]) => ({\n key,\n count: e.count,\n selfMs: e.selfMs,\n pctOfTotal: total > 0 ? (100 * e.selfMs) / total : 0,\n }))\n .sort((a, b) => b.selfMs - a.selfMs || b.count - a.count);\n };\n return {\n byNodeType: groupBy((n) => n.nodeType),\n byRelation: groupBy((n) => n.relationName),\n byIndex: groupBy((n) => n.indexName),\n };\n}\n\n/** A short human label for a node, e.g. \"Seq Scan on orders\". */\nexport function nodeLabel(node: PlanNode): string {\n let label = node.nodeType;\n if (node.indexName && node.relationName)\n label += ` using ${node.indexName} on ${node.relationName}`;\n else if (node.relationName) label += ` on ${node.relationName}`;\n if (node.alias && node.alias !== node.relationName) label += ` (${node.alias})`;\n return label;\n}\n","/** Locale-aware, unit-consistent formatting shared by every renderer. */\n\n/** Postgres default block size; buffer counters are in blocks. */\nconst BLOCK_BYTES = 8192;\n\nexport function fmtInt(n: number): string {\n return Math.round(n).toLocaleString(\"en-US\");\n}\n\n/** Times are milliseconds throughout. */\nexport function fmtMs(ms: number): string {\n if (ms < 1) return `${ms.toFixed(3)} ms`;\n if (ms < 1000) return `${ms.toFixed(1)} ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(2)} s`;\n const min = Math.floor(ms / 60_000);\n const sec = ((ms % 60_000) / 1000).toFixed(0);\n return `${min}m ${sec}s`;\n}\n\nexport function fmtPct(fraction0to100: number): string {\n return `${fraction0to100.toFixed(1)}%`;\n}\n\n/** Postgres reports sort/hash space in KiB. */\nexport function fmtKiB(kib: number): string {\n return fmtBytes(kib * 1024);\n}\n\n/** Buffer counters are in 8 KiB blocks. */\nexport function fmtBlocks(blocks: number): string {\n return `${fmtInt(blocks)} blk (${fmtBytes(blocks * BLOCK_BYTES)})`;\n}\n\nexport function fmtBytes(bytes: number): string {\n const units = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\"];\n let v = bytes;\n let i = 0;\n while (v >= 1024 && i < units.length - 1) {\n v /= 1024;\n i++;\n }\n const s = i === 0 ? String(Math.round(v)) : v.toFixed(1);\n return `${s} ${units[i]}`;\n}\n\n/** Round a KiB value up to the next whole MiB (work_mem recommendations). */\nexport function roundUpMiB(kib: number, stepMiB = 4): string {\n const mib = Math.ceil(kib / 1024 / stepMiB) * stepMiB;\n return `${Math.max(mib, stepMiB)}MB`;\n}\n\nexport interface TreeGlyphs {\n branch: string;\n last: string;\n vert: string;\n space: string;\n}\n\nexport const UNICODE_TREE: TreeGlyphs = { branch: \"├─ \", last: \"└─ \", vert: \"│ \", space: \" \" };\nexport const ASCII_TREE: TreeGlyphs = { branch: \"+- \", last: \"`- \", vert: \"| \", space: \" \" };\n","import type {\n AnalysisContext,\n Diagnostic,\n DiagnosticLocation,\n PlanNode,\n Remediation,\n Rule,\n Severity,\n} from \"../../core/model.ts\";\n\nexport const DOCS = \"https://www.postgresql.org/docs/current\";\n\nexport function locationOf(node: PlanNode): DiagnosticLocation {\n const loc: DiagnosticLocation = { kind: \"node\", nodeId: node.id, nodeType: node.nodeType };\n if (node.relationName) loc.relation = node.relationName;\n return loc;\n}\n\n/**\n * Build a plan finding. The Diagnostic `code` is the rule id (a PGX_* code), severity\n * is resolved through config overrides, and the location points at the offending node.\n * Every rule goes through here so all findings carry remediation + a node location.\n */\nexport function makeFinding(\n rule: Rule,\n ctx: AnalysisContext,\n node: PlanNode,\n parts: {\n title: string;\n detail: string;\n cause: string;\n remediation: Remediation;\n docsUrl?: string;\n meta?: Diagnostic[\"meta\"];\n /** Per-finding severity fallback (e.g. underestimate→warn); config still wins. */\n severity?: Severity;\n },\n): Diagnostic {\n const d: Diagnostic = {\n code: rule.id,\n domain: \"plan\",\n severity: ctx.severityOf(rule.id, parts.severity ?? rule.defaultSeverity),\n title: parts.title,\n detail: parts.detail,\n cause: parts.cause,\n remediation: parts.remediation,\n location: locationOf(node),\n };\n if (parts.docsUrl) d.docsUrl = parts.docsUrl;\n if (parts.meta) d.meta = parts.meta;\n return d;\n}\n\n/** First child is the outer (driving) side of a join. */\nexport function outerChild(node: PlanNode): PlanNode | undefined {\n return node.children[0];\n}\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Bitmap heap scan whose bitmap exceeded work_mem and degraded to page granularity.\n * When the per-tuple bitmap won't fit, Postgres stores only the heap *page* numbers\n * (\"lossy\" blocks) and re-checks the index condition against every tuple on those\n * pages, reading more heap and re-evaluating the predicate. Raising work_mem keeps the\n * bitmap exact; a more selective index also shrinks it.\n */\nexport const bitmapLossy: Rule = {\n id: \"PGX_BITMAP_LOSSY\",\n title: \"Lossy bitmap heap scan\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Bitmap Heap Scan\") return [];\n\n const lossy = node.lossyHeapBlocks ?? 0;\n if (lossy <= 0) return [];\n\n const exact = node.exactHeapBlocks ?? 0;\n const rel = node.relationName ?? \"the table\";\n const rechecked = node.rowsRemovedByIndexRecheck ?? 0;\n const recheckNote =\n rechecked > 0\n ? ` The recheck discarded ${fmtInt(rechecked)} extra rows that the lossy bitmap could not exclude.`\n : \"\";\n\n return [\n makeFinding(bitmapLossy, ctx, node, {\n title: `Lossy bitmap heap scan on ${rel} (${fmtInt(lossy)} lossy blocks)`,\n detail: `The bitmap for ${rel} held ${fmtInt(lossy)} lossy (page-granularity) blocks alongside ${fmtInt(\n exact,\n )} exact blocks, so Postgres re-checked the index condition against every tuple on the lossy pages.${recheckNote}`,\n cause:\n \"The exact (per-tuple) bitmap did not fit in work_mem, so Postgres fell back to storing whole heap pages and recheck the index condition while reading them — more heap I/O and CPU than an exact bitmap.\",\n remediation: {\n summary: `Raise work_mem for this session so the bitmap stays exact (no lossy blocks, no rechecks) on ${rel}; alternatively make the index condition more selective or add a composite index so the bitmap is smaller.`,\n steps: [\n \"Increase work_mem for the session, then re-run EXPLAIN (ANALYZE) and confirm Lossy Heap Blocks drops to 0.\",\n \"If raising work_mem is undesirable, make the index condition more selective (a more selective leading column or a composite index over the filtered columns) so fewer heap pages enter the bitmap.\",\n ],\n commands: [\n {\n label: \"Give this session more work_mem\",\n sql: \"SET work_mem = '<X>MB';\",\n },\n {\n label: \"Or shrink the bitmap with a more selective index\",\n sql: `CREATE INDEX ON ${rel} (<more selective / composite columns>);`,\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-WORK-MEM`,\n meta: { lossyBlocks: lossy, exactBlocks: exact },\n }),\n ];\n },\n};\n","import type { PlanNode, Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/** Measured rows if available, else the planner estimate. */\nfunction rowsOf(node: PlanNode): number {\n return node.metrics.totalRows ?? node.planRows;\n}\n\n/**\n * Nested Loop with no join predicate anywhere — neither a Join Filter on the loop\n * nor an Index Cond / Recheck Cond on the inner side. Every outer row is paired with\n * every inner row, so the result is the cross product (rows ≈ outer × inner). This is\n * almost always a forgotten ON / WHERE join condition; precision is kept high by\n * requiring both sides to actually produce rows.\n */\nexport const cartesianProduct: Rule = {\n id: \"PGX_CARTESIAN_PRODUCT\",\n title: \"Cartesian product (missing join condition)\",\n defaultSeverity: \"error\",\n check(node, ctx) {\n if (node.nodeType !== \"Nested Loop\") return [];\n if (node.joinFilter) return [];\n\n let inner = node.children[1];\n if (!inner) return [];\n // Memoize/Materialize wrap the real inner scan — the join predicate lives below them.\n while (\n (inner.nodeType === \"Memoize\" || inner.nodeType === \"Materialize\") &&\n inner.children[0]\n ) {\n inner = inner.children[0];\n }\n // A join key on the inner side (index lookup) means there IS a predicate.\n if (inner.indexCond || inner.recheckCond) return [];\n\n const outer = node.children[0];\n if (!outer) return [];\n\n const outerRows = rowsOf(outer);\n const innerRows = rowsOf(inner);\n // Single-row sides are legitimately matched against everything (e.g. a LIMIT 1\n // or aggregate); a cross product is only meaningful when both sides are sets.\n if (outerRows <= 1 || innerRows <= 1) return [];\n\n const estimated = node.metrics.totalRows === undefined;\n const product = fmtInt(outerRows * innerRows);\n\n return [\n makeFinding(cartesianProduct, ctx, node, {\n title: `Cartesian product: Nested Loop with no join condition (~${product}${estimated ? \" est.\" : \"\"} rows)`,\n detail: `The Nested Loop has no Join Filter and the inner side has no Index Cond or Recheck Cond, so each of ${fmtInt(\n outerRows,\n )} outer rows is paired with every one of ${fmtInt(innerRows)} inner rows${\n estimated ? \" (estimated — run with ANALYZE for actuals)\" : \"\"\n }.`,\n cause:\n \"No predicate links the two relations, so Postgres can only emit the full cross product. This usually means an ON or WHERE join condition was omitted (e.g. a comma join across tables).\",\n remediation: {\n summary:\n \"Add the missing join condition linking the two tables on their key columns (e.g. ON a.id = b.a_id). If a cross product is truly intended, make it explicit with CROSS JOIN and bound it with a LIMIT or aggregation.\",\n steps: [\n \"Find the two relations feeding this Nested Loop in your query.\",\n \"Add an ON (or WHERE) clause matching their key columns so the loop becomes selective.\",\n \"If you really want every combination, write CROSS JOIN explicitly and cap the size with LIMIT or an aggregate.\",\n ],\n commands: [\n {\n label: \"Add the join predicate\",\n sql: \"SELECT ...\\nFROM <outer_table> a\\nJOIN <inner_table> b ON a.<key> = b.<key>;\",\n },\n {\n label: \"Or make the cross join explicit and bounded\",\n sql: \"SELECT ...\\nFROM <outer_table> a\\nCROSS JOIN <inner_table> b\\nLIMIT <n>;\",\n },\n ],\n },\n docsUrl: `${DOCS}/queries-table-expressions.html#QUERIES-JOIN`,\n meta: { outerRows: Math.round(outerRows), innerRows: Math.round(innerRows) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A correlated subquery surfaces as a SubPlan node whose `actualLoops` equals the\n * number of outer rows: the planner re-executes it once per row instead of running\n * it once. Above the loop threshold this dominates execution time. The fix is to\n * de-correlate it — rewrite as a JOIN/LATERAL or hoist into a CTE evaluated once.\n */\nexport const correlatedSubplan: Rule = {\n id: \"PGX_CORRELATED_SUBPLAN\",\n title: \"Correlated subplan re-executed per row\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n const isSubplan =\n node.parentRelationship === \"SubPlan\" || (node.subplanName?.startsWith(\"SubPlan\") ?? false);\n if (!isSubplan) return [];\n\n const loops = node.actualLoops ?? 0;\n if (loops <= ctx.thresholds.correlatedLoops) return [];\n\n const name = node.subplanName ?? \"the subplan\";\n\n return [\n makeFinding(correlatedSubplan, ctx, node, {\n title: `Correlated ${name} re-executed ${fmtInt(loops)} times`,\n detail: `${name} ran ${fmtInt(loops)} times — once per outer row — instead of being evaluated a single time.`,\n cause:\n \"The subquery references a column from the enclosing query, so the planner cannot pull it out of the per-row loop and re-runs the whole subplan for every outer row.\",\n remediation: {\n summary: `De-correlate the subquery: rewrite it as a JOIN or LATERAL join, or hoist it into a CTE/derived table evaluated once, then index the correlation key so the rewrite stays cheap.`,\n steps: [\n \"Identify the outer column the subquery references (the correlation key).\",\n \"For a scalar subquery in SELECT/WHERE, rewrite it as a LEFT JOIN to a grouped derived table, or a LATERAL join when it returns per-row results.\",\n \"For EXISTS/IN, prefer the semi-join form (EXISTS / = ANY) the planner can de-correlate into a single hash/merge join.\",\n \"Add an index on the correlation key so the resulting JOIN does not fall back to the same per-row cost.\",\n // Before (correlated, runs once per outer row):\n // SELECT o.id, (SELECT count(*) FROM events e WHERE e.order_id = o.id) AS n FROM orders o;\n // After (evaluated once, joined):\n // SELECT o.id, COALESCE(e.n, 0) AS n\n // FROM orders o\n // LEFT JOIN (SELECT order_id, count(*) AS n FROM events GROUP BY order_id) e\n // ON e.order_id = o.id;\n \"See the before/after sketch: SELECT (SELECT count(*) FROM events e WHERE e.order_id = o.id) becomes a LEFT JOIN to (SELECT order_id, count(*) FROM events GROUP BY order_id).\",\n ],\n commands: [\n {\n label: \"Index the correlation key so the de-correlated JOIN stays cheap\",\n sql: \"CREATE INDEX ON <subquery table> (<correlation key column>);\",\n },\n ],\n },\n docsUrl: `${DOCS}/queries-table-expressions.html#QUERIES-LATERAL`,\n meta: { loops },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Hint: an Index Scan that projects only a few columns and applies no residual\n * filter (the whole predicate lives in the Index Cond) MIGHT qualify for an\n * Index Only Scan if the index covers every selected column. We cannot see the\n * index definition from EXPLAIN, so this is low-confidence — phrased as a\n * suggestion and kept at `info`. Requires VERBOSE for the Output column list.\n */\nexport const couldBeIndexOnly: Rule = {\n id: \"PGX_COULD_BE_INDEX_ONLY\",\n title: \"Index scan may be eligible for index-only\",\n defaultSeverity: \"info\",\n check(node, ctx) {\n if (node.nodeType !== \"Index Scan\") return [];\n if (!node.indexName) return [];\n // A residual Filter means columns beyond the index are needed for the\n // predicate, so it cannot become index-only — skip those.\n if (node.filter) return [];\n // Need VERBOSE output to know which columns are projected.\n if (!node.output || node.output.length === 0) return [];\n // Only hint for a small, plausibly-coverable column set.\n if (node.output.length > 4) return [];\n\n const rel = node.relationName ?? \"the table\";\n const cols = node.output;\n const colList = cols.join(\", \");\n const includeCols = cols.join(\", \");\n\n return [\n makeFinding(couldBeIndexOnly, ctx, node, {\n title: `Index Scan using ${node.indexName} on ${rel} may be eligible for index-only`,\n detail: `This Index Scan projects only ${cols.length} column${\n cols.length === 1 ? \"\" : \"s\"\n } (${colList}) and applies no residual filter, so its predicate is fully resolved by ${node.indexName}. If that index also covers the selected columns, Postgres could use an Index Only Scan and skip the heap entirely.`,\n cause:\n \"An Index Scan still visits the table heap to fetch the projected columns. When every selected column is contained in the index (as a key or INCLUDE column) and the visibility map is current, Postgres can answer from the index alone (Index Only Scan).\",\n remediation: {\n summary: `Add the selected columns (${includeCols}) to ${node.indexName} as INCLUDE columns so it covers the query, then keep the visibility map current with VACUUM so Postgres can switch ${rel} to an Index Only Scan.`,\n steps: [\n \"Confirm which columns the index already covers (\\\\d <index> in psql) — this hint assumes VERBOSE Output and cannot read the index definition.\",\n \"If any projected column is missing, recreate the index with those columns as INCLUDE (non-key) columns.\",\n \"Run VACUUM so the visibility map is set; Index Only Scans fall back to heap fetches on pages not marked all-visible.\",\n ],\n commands: [\n {\n label: \"Create a covering index\",\n sql: `CREATE INDEX ON ${rel} (<key columns from the Index Cond>) INCLUDE (${includeCols});`,\n },\n {\n label: \"Keep the visibility map current\",\n sql: `VACUUM ${rel};`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-index-only-scans.html`,\n meta: { outputColumns: cols.length },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * An index/bitmap scan that still applies a residual Filter after the index lookup.\n * The Filter is evaluated on every heap row the index returned; folding those columns\n * into the index lets Postgres apply them as an Index Cond during traversal, skipping\n * the rows entirely. This is a hint (severity info): a non-sargable predicate cannot be\n * indexed, so the fix is phrased around making the filter index-friendly.\n */\nexport const filterCouldBeIndexCond: Rule = {\n id: \"PGX_FILTER_COULD_BE_INDEX_COND\",\n title: \"Filter could be an index condition\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n const indexed =\n node.nodeType === \"Index Scan\" ||\n node.nodeType === \"Index Only Scan\" ||\n node.nodeType === \"Bitmap Heap Scan\";\n if (!indexed) return [];\n if (!node.filter) return [];\n if (!node.indexCond && !node.recheckCond) return [];\n if ((node.rowsRemovedByFilter ?? 0) <= 0) return [];\n\n const rel = node.relationName ?? \"the table\";\n const cond = node.indexCond ?? node.recheckCond ?? \"\";\n const loops = node.actualLoops ?? 1;\n const removed = (node.rowsRemovedByFilter ?? 0) * loops;\n\n return [\n makeFinding(filterCouldBeIndexCond, ctx, node, {\n title: `Residual filter on ${rel} could be an index condition`,\n detail: `${node.nodeType} on ${rel} used the index for ${cond} but then applied Filter ${node.filter} to the fetched rows, discarding ${fmtInt(removed)} of them.`,\n cause: `The Filter columns are not part of the index, so Postgres must fetch each row the index matched and re-check the predicate in the executor instead of skipping non-matching entries during the index traversal.`,\n remediation: {\n summary: `Extend the index on ${rel} to include the Filter columns from ${node.filter} as trailing key columns, so the predicate is applied as an Index Cond during traversal instead of as a post-fetch Filter.`,\n steps: [\n `Confirm the Filter ${node.filter} is sargable — no functions or implicit casts wrapping the column.`,\n \"Append the filter columns after the existing key columns so the index still serves the original lookup.\",\n \"Re-run EXPLAIN (ANALYZE) and check the Filter moved into the Index Cond with no Rows Removed by Filter.\",\n ],\n commands: [\n {\n label: \"Extend the index with the filter columns\",\n sql: `CREATE INDEX ON ${rel} (<existing key columns>, <filter columns>);`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-multicolumn.html`,\n meta: { rowsRemovedByFilter: Math.round(removed) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt, fmtKiB, roundUpMiB } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A Hash node split its build side into multiple batches, meaning the hash table did\n * not fit in work_mem and spilled to disk. The ideal is a single batch; more batches\n * than originally planned (hashBatches > originalHashBatches) means Postgres also had\n * to re-partition at runtime after under-sizing the build side.\n */\nexport const hashSpillDisk: Rule = {\n id: \"PGX_HASH_SPILL_DISK\",\n title: \"Hash join spilled to disk\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Hash\") return [];\n\n const hashBatches = node.hashBatches ?? 1;\n if (hashBatches <= 1) return [];\n\n const originalHashBatches = node.originalHashBatches ?? hashBatches;\n const repartitioned = hashBatches > originalHashBatches;\n\n // Size work_mem to hold the whole build side (peak memory + what spilled) with headroom.\n const peakKiB = node.peakMemoryUsage ?? 0;\n const diskKiB = node.diskUsage ?? 0;\n const workMemRecommended = roundUpMiB((peakKiB + diskKiB) * 1.2);\n\n return [\n makeFinding(hashSpillDisk, ctx, node, {\n title: `Hash build side spilled to disk (${fmtInt(hashBatches)} batches)`,\n detail: `The hash table was split into ${fmtInt(hashBatches)} batches${\n repartitioned ? ` (up from ${fmtInt(originalHashBatches)} planned)` : \"\"\n }, so the build side did not fit in work_mem and overflowed to temporary files${\n diskKiB > 0 ? ` (${fmtKiB(diskKiB)} written to disk)` : \"\"\n }.`,\n cause: repartitioned\n ? \"Postgres had to add batches at runtime because the build side was larger than estimated — usually a row underestimate sized work_mem too small.\"\n : \"The build (hash) side was larger than work_mem, forcing the hash join to partition it across disk-backed batches.\",\n remediation: {\n summary: `Raise work_mem to about ${workMemRecommended} so the build side fits in a single batch, and make sure the SMALLER input is the hash/build side (a wrong build side usually comes from a row underestimate — fix the stats). Reducing build-side rows also avoids the spill.`,\n steps: [\n `Set work_mem high enough to hold the build side in one batch (~${workMemRecommended} here) at session or role scope, not globally — every sort/hash node can use work_mem, so a global bump can exhaust memory.`,\n \"Confirm the smaller relation is on the build (Hash) side; if Postgres chose the larger side, a row underestimate is likely — re-run ANALYZE or raise statistics targets so the planner picks the smaller build side.\",\n \"Alternatively, filter or aggregate the build side earlier so fewer rows need to be hashed.\",\n ],\n commands: [\n {\n label: \"Raise work_mem for this session\",\n sql: `SET work_mem = '${workMemRecommended}';`,\n },\n {\n label: \"Or set it for a specific role\",\n sql: `ALTER ROLE <role> SET work_mem = '${workMemRecommended}';`,\n },\n {\n label: \"Refresh planner statistics on the build-side table\",\n sql: \"ANALYZE <build_side_table>;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-WORK-MEM`,\n meta: { hashBatches, workMemRecommended },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A node reads many rows then throws most of them away via a post-read Filter. The\n * discarded rows were still fetched and examined, so the work is wasted. Pushing the\n * predicate into an index turns the Filter into an Index Cond, letting Postgres skip\n * the non-matching rows entirely instead of reading and rejecting them.\n */\nexport const highFilterDiscard: Rule = {\n id: \"PGX_HIGH_FILTER_DISCARD\",\n title: \"Filter discards most rows read\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n const ratio = node.metrics.filterDiscardRatio;\n if (ratio === undefined || ratio <= ctx.thresholds.filterDiscardRatio) return [];\n\n const removed = (node.rowsRemovedByFilter ?? 0) * (node.actualLoops ?? 1);\n if (removed <= ctx.thresholds.filterRemovedAbs) return [];\n\n const rel = node.relationName ?? \"the table\";\n const kept = node.metrics.totalRows ?? 0;\n const discardPct = ratio * 100;\n const filter = node.filter ?? \"the filter predicate\";\n\n return [\n makeFinding(highFilterDiscard, ctx, node, {\n title: `Filter on ${rel} discards ${fmtPct(discardPct)} of rows read`,\n detail: `Postgres read this node's rows then dropped ${fmtInt(removed)} of them (${fmtPct(\n discardPct,\n )}), keeping only ${fmtInt(kept)}, via the post-read filter ${filter}.`,\n cause: `The predicate ${filter} is evaluated as a Filter after the rows are fetched, so every discarded row was still read and examined — work no index condition narrowed.`,\n remediation: {\n summary: `Move ${filter} into an index on ${rel} so the predicate becomes an Index Cond instead of a post-read Filter, letting Postgres skip the non-matching rows. For a low-cardinality predicate, a partial index keyed on the discarded condition is smaller and faster.`,\n steps: [\n \"Identify the column(s) referenced by the filter above.\",\n \"Ensure the predicate is sargable (no function-wrapping or implicit casts on the indexed column).\",\n \"Use a plain index when the columns are selective across queries; use a partial index when the same constant predicate is always applied.\",\n ],\n commands: [\n {\n label: \"Index the filter columns\",\n sql: `CREATE INDEX ON ${rel} (<filter columns>);`,\n },\n {\n label: \"Or a partial index for a fixed low-cardinality predicate\",\n sql: `CREATE INDEX ON ${rel} (<filter columns>) WHERE <predicate>;`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-partial.html`,\n meta: { discardPct: Math.round(discardPct) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Index-only scan that still hit the heap. Each heap fetch means the visibility map\n * marked that page as not all-visible, so Postgres had to read the table row to check\n * visibility — defeating the index-only optimization. The usual cause is a table that\n * has not been vacuumed recently enough relative to its write rate.\n */\nexport const indexOnlyHeapFetches: Rule = {\n id: \"PGX_INDEX_ONLY_HEAP_FETCHES\",\n title: \"Index-only scan with heap fetches\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Index Only Scan\") return [];\n\n const heapFetches = node.heapFetches ?? 0;\n if (heapFetches <= 0) return [];\n\n const rows = Math.max(node.metrics.totalRows ?? 1, 1);\n const ratio = heapFetches / rows;\n if (ratio <= ctx.thresholds.heapFetchRatio && heapFetches <= ctx.thresholds.heapFetchAbs) {\n return [];\n }\n\n const rel = node.relationName ?? \"the table\";\n\n return [\n makeFinding(indexOnlyHeapFetches, ctx, node, {\n title: `Index-only scan on ${rel} did ${fmtInt(heapFetches)} heap fetches`,\n detail: `The index-only scan on ${rel} fell back to the heap ${fmtInt(heapFetches)} times for ${fmtInt(\n rows,\n )} rows produced. Each fetch is an extra table page read the index-only path was meant to avoid.`,\n cause: `Heap fetches happen when the visibility map does not mark the pages as all-visible, so Postgres must read the table row to confirm visibility. This usually means ${rel} has not been vacuumed recently enough for its write/update rate.`,\n remediation: {\n summary: `Run VACUUM (or VACUUM ANALYZE) on ${rel} to refresh the visibility map so the index-only scan can skip the heap. For a high-churn table, lower autovacuum_vacuum_scale_factor so autovacuum keeps the map current.`,\n steps: [\n `VACUUM ${rel} to update the visibility map; add ANALYZE if statistics are also stale.`,\n \"If heap fetches keep returning, the table is updated faster than autovacuum runs — make autovacuum more aggressive on it.\",\n \"Confirm the scan stays index-only afterwards by re-running EXPLAIN (ANALYZE) and checking Heap Fetches drops toward 0.\",\n ],\n commands: [\n {\n label: \"Refresh the visibility map\",\n sql: `VACUUM (ANALYZE) ${rel};`,\n },\n {\n label: \"Keep the map current on a high-churn table\",\n sql: `ALTER TABLE ${rel} SET (autovacuum_vacuum_scale_factor = 0.02);`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-index-only-scans.html`,\n meta: { heapFetches },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding, outerChild } from \"./util.ts\";\n\n/**\n * A Limit node whose input produced far more rows than it emitted — the classic\n * `LIMIT n OFFSET m` pagination pattern. Postgres must generate and throw away the\n * whole skipped prefix, so page N costs O(N). Keyset pagination stays O(1).\n */\nexport const limitLargeOffset: Rule = {\n id: \"PGX_LIMIT_LARGE_OFFSET\",\n title: \"LIMIT discards a large prefix (OFFSET pagination)\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Limit\") return [];\n\n const child = outerChild(node);\n const emitted = node.metrics.totalRows;\n const produced = child?.metrics.totalRows;\n if (emitted === undefined || produced === undefined) return [];\n\n const discarded = produced - emitted;\n if (discarded < ctx.thresholds.limitDiscardRows) return [];\n\n const rel = child?.relationName ?? \"the input\";\n\n return [\n makeFinding(limitLargeOffset, ctx, node, {\n title: `LIMIT discarded ${fmtInt(discarded)} rows before returning ${fmtInt(emitted)}`,\n detail: `The plan produced ${fmtInt(produced)} rows from ${rel} but the Limit node returned only ${fmtInt(emitted)} — ${fmtInt(discarded)} rows were generated just to be skipped.`,\n cause:\n \"OFFSET-style pagination makes Postgres compute and discard every row before the requested page, so deep pages get progressively slower (page N costs O(N)).\",\n remediation: {\n summary:\n \"Switch to keyset (seek) pagination: filter on the last-seen sort key instead of skipping rows, and keep an index on the sort key so each page is a direct index seek.\",\n steps: [\n \"Order by a unique (or tie-broken) key, e.g. ORDER BY created_at, id.\",\n \"Pass the last row's key from the previous page instead of an OFFSET.\",\n \"Index the sort key so the WHERE clause seeks directly to the page start.\",\n ],\n commands: [\n {\n label: \"Keyset pagination instead of OFFSET\",\n sql: \"SELECT … FROM t WHERE (created_at, id) > ($last_created_at, $last_id) ORDER BY created_at, id LIMIT 50;\",\n },\n ],\n },\n docsUrl: `${DOCS}/queries-limit.html`,\n meta: { discarded: Math.round(discarded), emitted: Math.round(emitted) },\n }),\n ];\n },\n};\n","import { nodeLabel } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtBlocks, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/** Below this many disk-read blocks the cold-cache noise outweighs any real signal. */\nconst MIN_READ_BLOCKS = 1000;\n\n/**\n * Low shared-buffer cache hit ratio: the node fetched many pages from disk rather\n * than from PostgreSQL's buffer cache. This is often just a cold cache on the first\n * run, so the finding is informational and leads with \"re-run to confirm\" before\n * suggesting shared_buffers sizing or a more selective index.\n */\nexport const lowCacheHit: Rule = {\n id: \"PGX_LOW_CACHE_HIT\",\n title: \"Low cache hit ratio (heavy disk reads)\",\n defaultSeverity: \"info\",\n requiresBuffers: true,\n check(node, ctx) {\n const ratio = node.metrics.cacheHitRatio;\n const readBlocks = node.sharedReadBlocks ?? 0;\n if (ratio == null) return [];\n if (ratio >= ctx.thresholds.lowCacheHitRatio) return [];\n if (readBlocks <= MIN_READ_BLOCKS) return [];\n\n const label = nodeLabel(node);\n const rel = node.relationName;\n const ratioPct = ratio * 100;\n\n return [\n makeFinding(lowCacheHit, ctx, node, {\n title: `Low cache hit ratio at ${label} (${fmtPct(ratioPct)})`,\n detail: `${label} served only ${fmtPct(ratioPct)} of its shared-buffer accesses from cache, reading ${fmtBlocks(readBlocks)} from disk.`,\n cause:\n \"The pages this node needed were not resident in shared_buffers, so PostgreSQL had to read them from disk. On a first run this is an expected cold cache; if it persists, the working set is larger than the cache or the scan touches more pages than necessary.\",\n remediation: {\n summary: `Re-run the query to check whether this is just a cold cache — the ratio should climb on a warm run. If it stays low, the working set exceeds shared_buffers: size shared_buffers/effective_cache_size to your RAM, or add a selective index on ${rel ?? \"the scanned relation\"} so far fewer pages are read.`,\n steps: [\n \"Run the same EXPLAIN (ANALYZE, BUFFERS) a second time; a much higher hit ratio means the first run was a cold cache and no action is needed.\",\n \"If the ratio stays low, check whether shared_buffers (and effective_cache_size for planner costing) are sized to the machine's RAM.\",\n \"If the node reads far more pages than the rows it returns, add a selective index so only matching pages are fetched.\",\n ],\n commands: [\n {\n label: \"Inspect current buffer-cache sizing\",\n sql: \"SHOW shared_buffers; SHOW effective_cache_size;\",\n },\n {\n label: \"Reduce pages read with a selective index\",\n sql: `CREATE INDEX ON ${rel ?? \"<table>\"} (<predicate columns>);`,\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-SHARED-BUFFERS`,\n meta: { cacheHitPct: Math.round(ratioPct * 10) / 10, readBlocks },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A Memoize node whose cache is thrashing: entries are evicted faster than they\n * are reused, or single entries overflow the cache entirely. The planner chose\n * Memoize expecting repeated key lookups to hit the cache; when work_mem is too\n * small for the key space, the node pays cache maintenance overhead for nothing.\n * ponytail: self-normalizing condition (evictions > hits, or any overflow) — no\n * config threshold; a thrashing cache is bad at any absolute size.\n */\nexport const memoizeEvictions: Rule = {\n id: \"PGX_MEMOIZE_EVICTIONS\",\n title: \"Memoize cache is thrashing\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Memoize\") return [];\n\n const hits = node.cacheHits ?? 0;\n const evictions = node.cacheEvictions ?? 0;\n const overflows = node.cacheOverflows ?? 0;\n const thrashing = evictions > hits;\n if (!thrashing && overflows === 0) return [];\n\n return [\n makeFinding(memoizeEvictions, ctx, node, {\n title:\n overflows > 0\n ? `Memoize cache overflowed ${fmtInt(overflows)} time(s)`\n : `Memoize evicted ${fmtInt(evictions)} entries against ${fmtInt(hits)} hits`,\n detail: `The Memoize cache recorded ${fmtInt(hits)} hits, ${fmtInt(node.cacheMisses ?? 0)} misses, ${fmtInt(evictions)} evictions, and ${fmtInt(overflows)} overflows — entries are being thrown away before they can be reused.`,\n cause:\n \"The distinct key values do not fit in the memory Memoize is allowed (derived from work_mem × hash_mem_multiplier), so the cache churns and the node degenerates into a slower re-executing inner side.\",\n remediation: {\n summary:\n \"Give the session more cache memory (work_mem / hash_mem_multiplier) so the key space fits, or reduce the number of distinct keys flowing into the Memoize.\",\n steps: [\n \"Estimate the distinct keys: the planner sizes the cache from ndistinct of the join key.\",\n \"Raise work_mem (or hash_mem_multiplier on PG 15+) for this workload and re-run.\",\n \"If the key space is genuinely huge, an index on the inner side may beat Memoize — compare with enable_memoize = off.\",\n ],\n commands: [\n { label: \"More cache memory for this session\", sql: \"SET work_mem = '64MB';\" },\n {\n label: \"Compare the plan without Memoize\",\n sql: \"SET enable_memoize = off; EXPLAIN ANALYZE <query>;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html`,\n meta: { hits, evictions, overflows },\n }),\n ];\n },\n};\n","import { nodeLabel } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding, outerChild } from \"./util.ts\";\n\n/**\n * Nested loop whose outer (driving) side produced many rows. A nested loop runs the\n * inner subtree once per outer row, so a large outer side multiplies the inner cost.\n * The planner usually picks this only when it expects few outer rows — so the root\n * cause is normally a cardinality misestimate. Fix the estimate first (so it switches\n * to a hash/merge join); if the estimate is right, index the inner join key.\n */\nexport const nestedLoopLargeOuter: Rule = {\n id: \"PGX_NESTED_LOOP_LARGE_OUTER\",\n title: \"Nested loop with a large outer side\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Nested Loop\") return [];\n\n const outer = outerChild(node);\n const outerRows = outer?.metrics.totalRows;\n if (outerRows === undefined || outerRows <= ctx.thresholds.nestedLoopOuterRows) return [];\n\n const outerLabel = outer ? nodeLabel(outer) : \"the outer side\";\n const inner = node.children[1];\n const innerLabel = inner ? nodeLabel(inner) : \"the inner side\";\n const innerCond = inner?.indexCond ?? inner?.joinFilter ?? inner?.filter ?? node.joinFilter;\n const misestimated = outer?.metrics.estimateDirection === \"under\";\n\n return [\n makeFinding(nestedLoopLargeOuter, ctx, node, {\n title: `Nested loop driven by ${fmtInt(outerRows)} outer rows (${outerLabel})`,\n detail: `The nested loop's outer side (${outerLabel}) produced ${fmtInt(\n outerRows,\n )} rows, so its inner side (${innerLabel}) is re-executed roughly that many times.`,\n cause: misestimated\n ? `The planner expected far fewer outer rows than the ${fmtInt(\n outerRows,\n )} that actually came back, so it chose a per-row nested loop where a single hash/merge join would have been cheaper.`\n : `A nested loop probes the inner side once per outer row; with ${fmtInt(\n outerRows,\n )} outer rows that is ${fmtInt(outerRows)} inner executions.`,\n remediation: {\n summary: `Fix the outer-side row estimate first — re-ANALYZE ${\n outer?.relationName ?? \"the driving table\"\n }, raise its column statistics, or add extended statistics — so the planner switches to a hash or merge join. If the estimate is already accurate, add an index on the inner join key (${\n innerCond ?? \"<inner join column>\"\n }) so each of the ${fmtInt(outerRows)} probes is cheap.`,\n steps: [\n \"Compare the outer node's estimated vs actual rows: a large gap means the estimate is the real problem.\",\n \"Refresh statistics so the planner sees the true cardinality and can prefer a hash/merge join.\",\n \"If columns are correlated, create extended (multivariate) statistics on them.\",\n \"If estimates are already correct, index the inner join key so each probe is an index lookup, not a scan.\",\n \"As a last resort to confirm the diagnosis, test with `SET enable_nestloop = off` for this query only.\",\n ],\n commands: [\n {\n label: \"Refresh planner statistics on the driving table\",\n sql: `ANALYZE ${outer?.relationName ?? \"<outer table>\"};`,\n },\n {\n label: \"Increase statistics target on the misestimated column, then re-ANALYZE\",\n sql: `ALTER TABLE ${\n outer?.relationName ?? \"<outer table>\"\n } ALTER COLUMN <column> SET STATISTICS 1000;\\nANALYZE ${\n outer?.relationName ?? \"<outer table>\"\n };`,\n },\n {\n label: \"Add extended statistics for correlated columns\",\n sql: `CREATE STATISTICS ${\n outer?.relationName ?? \"<outer table>\"\n }_stats (dependencies, ndistinct) ON <col_a>, <col_b> FROM ${\n outer?.relationName ?? \"<outer table>\"\n };\\nANALYZE ${outer?.relationName ?? \"<outer table>\"};`,\n },\n {\n label: \"If estimates are correct, index the inner join key\",\n sql: `CREATE INDEX ON ${\n inner?.relationName ?? \"<inner table>\"\n } (<inner join column>);`,\n },\n {\n label: \"Confirm the diagnosis by disabling nested loops for this query only\",\n sql: \"SET enable_nestloop = off;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-query.html`,\n meta: { outerRows: Math.round(outerRows) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * The planner's row estimate is wildly off from the actual row count. Bad estimates\n * cascade into bad join/sort/memory choices, so a large factor — especially an\n * underestimate feeding a nested loop or hash — is a leading cause of slow plans.\n * Usually it means statistics are stale or too coarse for the predicate.\n */\nexport const rowMisestimate: Rule = {\n id: \"PGX_ROW_MISESTIMATE\",\n title: \"Row count misestimate\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n const { estimateFactor, estimateDirection, totalRows } = node.metrics;\n if (estimateFactor === undefined) return [];\n if (estimateFactor < ctx.thresholds.misestimateFactor) return [];\n if (estimateDirection === undefined || estimateDirection === \"accurate\") return [];\n\n // Cut noise: a 20× error on 3 rows is irrelevant; only care at real volume.\n const rows = Math.max(totalRows ?? 0, node.planRows);\n if (rows < 100) return [];\n\n const factor = Math.round(estimateFactor);\n const rel = node.relationName;\n const onRel = rel ? ` on ${rel}` : \"\";\n const target = rel ?? \"the underlying table\";\n const under = estimateDirection === \"under\";\n const direction = under ? \"underestimate\" : \"overestimate\";\n\n const actual = totalRows ?? 0;\n const detail = `Postgres estimated ${fmtInt(node.planRows)} rows but ${fmtInt(actual)} were produced — a ${fmtInt(factor)}x ${direction}${onRel}.`;\n\n return [\n makeFinding(rowMisestimate, ctx, node, {\n // Severity: underestimates are the dangerous ones (under-sized joins/memory).\n severity: under ? \"warn\" : \"info\",\n title: `${fmtInt(factor)}x row ${direction}${onRel}`,\n detail,\n cause:\n \"The planner's row estimate is based on statistics that are stale, missing, or too coarse for this predicate (e.g. correlated columns the planner treats as independent).\",\n remediation: {\n summary: `Refresh and sharpen statistics for ${target}: run ANALYZE ${rel ?? \"<relation>\"}, raise per-column statistics targets on the predicate columns, and add extended statistics for correlated columns so the planner estimates rows correctly.${\n under\n ? \" Underestimates feeding a nested loop or hash join are the highest priority — fix these first.\"\n : \"\"\n }`,\n steps: [\n `Refresh table statistics first; this alone often fixes the estimate.`,\n `If the column has a skewed/uneven distribution, raise its statistics target and re-ANALYZE.`,\n `If the predicate spans multiple correlated columns, create extended statistics so the planner stops assuming independence.`,\n ],\n commands: [\n {\n label: \"Refresh statistics\",\n sql: `ANALYZE ${rel ?? \"<relation>\"};`,\n },\n {\n label: \"Raise per-column statistics target\",\n sql: `ALTER TABLE ${rel ?? \"<relation>\"} ALTER COLUMN <column> SET STATISTICS 1000;\\nANALYZE ${rel ?? \"<relation>\"};`,\n },\n {\n label: \"Add extended statistics for correlated columns\",\n sql: `CREATE STATISTICS <stats_name> (dependencies, ndistinct) ON <col_a>, <col_b> FROM ${rel ?? \"<relation>\"};\\nANALYZE ${rel ?? \"<relation>\"};`,\n },\n ],\n },\n docsUrl: `${DOCS}/planner-stats.html`,\n meta: {\n estimatedRows: Math.round(node.planRows),\n actualRows: Math.round(actual),\n factor,\n direction: estimateDirection,\n },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Sequential scan reading a large relation. Often an index would let Postgres skip\n * most of the table. If the scan genuinely needs most rows it is correct, so the fix\n * is phrased around the predicate.\n */\nexport const seqScanLarge: Rule = {\n id: \"PGX_SEQ_SCAN_LARGE\",\n title: \"Sequential scan on a large table\",\n defaultSeverity: \"warn\",\n check(node, ctx) {\n if (node.nodeType !== \"Seq Scan\") return [];\n\n // Prefer measured rows; fall back to the estimate on cost-only plans.\n const rows = node.metrics.totalRows ?? node.planRows;\n if (rows < ctx.thresholds.seqScanRows) return [];\n\n const rel = node.relationName ?? \"the table\";\n const estimated = node.metrics.totalRows === undefined;\n const filterCols = node.filter ? ` matching ${node.filter}` : \"\";\n\n return [\n makeFinding(seqScanLarge, ctx, node, {\n title: `Sequential scan on ${rel} (${fmtInt(rows)}${estimated ? \" est.\" : \"\"} rows)`,\n detail: `Postgres read ${rel} sequentially, scanning roughly ${fmtInt(rows)} rows${\n estimated ? \" (estimated — run with ANALYZE for actuals)\" : \"\"\n }.`,\n cause: node.filter\n ? `A row filter (${node.filter}) is applied after reading every row, so no index narrowed the scan.`\n : \"No index condition narrowed the scan, so the whole relation was read.\",\n remediation: {\n summary: `Add an index covering the WHERE/JOIN predicate on ${rel} so Postgres can skip non-matching rows. If the query genuinely needs most of the table, the seq scan is correct — reduce the rows touched instead.`,\n steps: [\n \"Identify the selective columns in the WHERE/JOIN predicate.\",\n \"Ensure they are sargable (no function-wrapping or implicit casts on the column).\",\n \"If selectivity is low, a partial index (WHERE …) may be better.\",\n ],\n commands: [\n {\n label: \"Index the predicate columns\",\n sql: `CREATE INDEX ON ${rel} (<predicate columns>)${filterCols ? \" -- columns from the filter above\" : \"\"};`,\n },\n ],\n },\n docsUrl: `${DOCS}/indexes-intro.html`,\n meta: { rows: Math.round(rows) },\n }),\n ];\n },\n};\n","import { executionMs } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtMs, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * JIT compilation time dominates total execution. Common on short queries whose plan\n * cost crossed `jit_above_cost`: the one-off cost of generating/optimizing machine code\n * outweighs the runtime it saves, so the query would have been faster with JIT off.\n * Tree-level rule — only acts at the root.\n */\nexport const significantJit: Rule = {\n id: \"PGX_SIGNIFICANT_JIT\",\n title: \"JIT compilation dominates execution\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node !== ctx.tree.root) return [];\n\n const t = ctx.tree.jit?.timing;\n const jitTotal =\n t?.total ??\n (t?.generation ?? 0) + (t?.inlining ?? 0) + (t?.optimization ?? 0) + (t?.emission ?? 0);\n const execMs = executionMs(ctx.tree);\n if (!execMs || jitTotal <= 0) return [];\n\n const jitPct = (100 * jitTotal) / execMs;\n if (jitPct <= ctx.thresholds.jitPct) return [];\n\n return [\n makeFinding(significantJit, ctx, node, {\n title: `JIT compilation took ${fmtMs(jitTotal)} (${fmtPct(jitPct)} of execution)`,\n detail: `JIT spent ${fmtMs(jitTotal)} generating, optimizing, and emitting machine code, out of ${fmtMs(\n execMs,\n )} total execution time. The compilation overhead outweighs the runtime it saved.`,\n cause:\n \"The plan's estimated cost crossed jit_above_cost, so Postgres JIT-compiled the query — but the query is too short for compilation to pay off, often because a row overestimate inflated the cost.\",\n remediation: {\n summary:\n \"Raise jit_above_cost (and jit_inline_above_cost / jit_optimize_above_cost) so short queries skip JIT, or disable JIT for this session with SET jit = off. Then investigate why the cost estimate is high enough to trigger JIT — frequently a row overestimate fixable with ANALYZE.\",\n steps: [\n \"Confirm the query is consistently short-running before tuning — JIT pays off on long, CPU-bound queries.\",\n \"Raise jit_above_cost above this plan's total cost so similar queries skip JIT entirely.\",\n \"If only inlining/optimization are expensive, raise jit_inline_above_cost / jit_optimize_above_cost instead of disabling JIT.\",\n \"Check the planner's row estimates against actuals — an overestimate that inflates cost is the usual reason a cheap query triggers JIT; run ANALYZE on the relations involved.\",\n ],\n commands: [\n { label: \"Disable JIT for this session\", sql: \"SET jit = off;\" },\n {\n label: \"Raise the JIT cost thresholds\",\n sql: \"SET jit_above_cost = <above this plan's total cost>;\\nSET jit_inline_above_cost = <higher>;\\nSET jit_optimize_above_cost = <higher>;\",\n },\n {\n label: \"Refresh statistics if the cost is driven by a row overestimate\",\n sql: \"ANALYZE <table>;\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-query.html#GUC-JIT-ABOVE-COST`,\n meta: { jitMs: Math.round(jitTotal), jitPct: Math.round(jitPct) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtKiB, roundUpMiB } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A Sort node spilled to disk because it exceeded work_mem. External merge sorts do\n * extra temp-file I/O and are far slower than an in-memory quicksort. Either raise\n * work_mem for this query, or feed the sort pre-ordered rows via a matching index.\n */\nexport const sortSpillDisk: Rule = {\n id: \"PGX_SORT_SPILL_DISK\",\n title: \"Sort spilled to disk\",\n defaultSeverity: \"warn\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Sort\") return [];\n\n const onDisk =\n node.sortSpaceType === \"Disk\" ||\n (node.sortMethod !== undefined && /external/i.test(node.sortMethod));\n if (!onDisk) return [];\n\n // Recommend ~2.2× the disk footprint (sort overhead vs. raw data) rounded up to MiB.\n const usedKiB = node.sortSpaceUsed ?? 0;\n const workMemRecommended = roundUpMiB(usedKiB > 0 ? usedKiB * 2.2 : 0);\n const usedText = usedKiB > 0 ? ` using ${fmtKiB(usedKiB)} of temp space` : \"\";\n const method = node.sortMethod ? ` (${node.sortMethod})` : \"\";\n const orderBy =\n node.sortKey && node.sortKey.length > 0 ? node.sortKey.join(\", \") : \"<ORDER BY columns>\";\n\n const summary =\n usedKiB > 0\n ? `Raise work_mem for this query so the sort stays in memory, e.g. SET work_mem = '${workMemRecommended}' at session or role scope (do NOT raise it globally without accounting for max_connections — each connection can allocate work_mem several times over). Alternatively, add an index on (${orderBy}) so rows arrive pre-sorted and the Sort node disappears.`\n : `Raise work_mem for this query so the sort stays in memory, e.g. SET work_mem = '64MB' at session or role scope (do NOT raise it globally without accounting for max_connections — each connection can allocate work_mem several times over). Alternatively, add an index on (${orderBy}) so rows arrive pre-sorted and the Sort node disappears.`;\n\n return [\n makeFinding(sortSpillDisk, ctx, node, {\n title: `Sort spilled to disk${usedText}`,\n detail: `The Sort node ran an external merge sort on disk${method}${usedText}, because the data exceeded work_mem.`,\n cause:\n \"work_mem was too small to hold the sort set, so Postgres wrote sorted runs to temporary files and merged them — adding temp-file I/O that an in-memory sort avoids.\",\n remediation: {\n summary,\n steps: [\n \"Set work_mem at session or role scope for this workload, not cluster-wide.\",\n `Size it above the spilled footprint${usedKiB > 0 ? ` (~${fmtKiB(usedKiB)}); ${workMemRecommended} leaves headroom` : \"\"}.`,\n `Or add an index on (${orderBy}) so the sort is satisfied by an ordered scan and removed entirely.`,\n ],\n commands: [\n {\n label: \"Raise work_mem for this session\",\n sql: `SET work_mem = '${usedKiB > 0 ? workMemRecommended : \"64MB\"}';`,\n },\n {\n label: \"Or set it per role\",\n sql: `ALTER ROLE <role> SET work_mem = '${usedKiB > 0 ? workMemRecommended : \"64MB\"}';`,\n },\n {\n label: \"Or add an index matching the sort key\",\n sql: `CREATE INDEX ON <table> (${orderBy});`,\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-WORK-MEM`,\n meta: { sortSpaceUsedKiB: Math.round(usedKiB), workMemRecommended },\n }),\n ];\n },\n};\n","import { executionMs } from \"../../core/metrics.ts\";\nimport type { Rule } from \"../../core/model.ts\";\nimport { fmtMs, fmtPct } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * Triggers consume a significant fraction of execution time. Trigger work (FK\n * constraint checks, AFTER triggers, etc.) runs outside the plan tree, so it is\n * invisible in the node timings and easy to miss. We surface it when the summed\n * trigger time crosses `triggerPct` of total execution time.\n */\nexport const triggerTime: Rule = {\n id: \"PGX_TRIGGER_TIME\",\n title: \"Triggers consume significant time\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n // Tree-level rule — act only at the root.\n if (node !== ctx.tree.root) return [];\n\n const triggers = ctx.tree.triggers;\n const execMs = executionMs(ctx.tree);\n const triggerTotal = triggers.reduce((s, t) => s + (t.time ?? 0), 0);\n if (!triggers.length || !execMs || triggerTotal <= 0) return [];\n\n const pct = (100 * triggerTotal) / execMs;\n if (pct <= ctx.thresholds.triggerPct) return [];\n\n // Name the heaviest trigger so the message is concrete.\n const worst = triggers.reduce((a, b) => ((b.time ?? 0) > (a.time ?? 0) ? b : a));\n const worstLabel = worst.name ?? worst.constraintName ?? \"a trigger\";\n const onRel = worst.relation ? ` on ${worst.relation}` : \"\";\n\n return [\n makeFinding(triggerTime, ctx, node, {\n title: `Triggers consumed ${fmtMs(triggerTotal)} (${fmtPct(pct)} of execution)`,\n detail: `Trigger execution took ${fmtMs(triggerTotal)} of the ${fmtMs(\n execMs,\n )} total — ${fmtPct(pct)} of the time is spent outside the plan tree (heaviest: \"${worstLabel}\"${onRel}).`,\n cause:\n \"Time spent firing triggers (often foreign-key constraint checks or AFTER triggers) is not attributed to any plan node, so it is invisible in the node timings even though it dominates the statement.\",\n remediation: {\n summary: `Index the foreign-key columns involved in the constraint checks so each row's lookup is cheap, and review the trigger function bodies for per-row inefficiency. For bulk loads, defer constraints (SET CONSTRAINTS ALL DEFERRED) or disable and replay triggers around the batch.`,\n steps: [\n \"Confirm both the referencing and referenced FK columns are indexed — an FK check does a lookup on the referenced key for every row, and a missing index makes it a full scan per row.\",\n \"Inspect each trigger function body for per-row work that could be batched or removed.\",\n \"For bulk INSERT/UPDATE/COPY, defer FK constraints until commit, or temporarily disable user triggers and replay the work once after the batch.\",\n ],\n commands: [\n {\n label: \"Index the referencing FK column(s) so constraint checks are cheap\",\n sql: `CREATE INDEX ON <referencing_table> (<fk_columns>);`,\n },\n {\n label: \"Defer FK constraint checks to commit for a bulk load\",\n sql: `BEGIN;\\nSET CONSTRAINTS ALL DEFERRED;\\n-- bulk INSERT/UPDATE/COPY here\\nCOMMIT;`,\n },\n {\n label: \"Disable user triggers around a batch, then re-enable\",\n sql: `ALTER TABLE <table> DISABLE TRIGGER USER;\\n-- bulk work here\\nALTER TABLE <table> ENABLE TRIGGER USER;`,\n },\n ],\n },\n docsUrl: `${DOCS}/sql-createtrigger.html`,\n meta: { triggerMs: Math.round(triggerTotal), triggerPct: Math.round(pct) },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { fmtInt } from \"../../util/format.ts\";\nimport { DOCS, makeFinding } from \"./util.ts\";\n\n/**\n * A Gather / Gather Merge node asked for more parallel workers than it got. Postgres\n * caps the total number of background workers globally (max_worker_processes /\n * max_parallel_workers), so a busy server can starve a query of the workers it planned\n * for, leaving the parallel plan running mostly serial. This is informational: if the\n * plan was not actually faster in parallel, fewer workers may be fine.\n */\nexport const workersNotLaunched: Rule = {\n id: \"PGX_WORKERS_NOT_LAUNCHED\",\n title: \"Parallel workers planned but not launched\",\n defaultSeverity: \"info\",\n requiresAnalyze: true,\n check(node, ctx) {\n if (node.nodeType !== \"Gather\" && node.nodeType !== \"Gather Merge\") return [];\n if (node.workersPlanned === undefined || node.workersLaunched === undefined) return [];\n if (node.workersLaunched >= node.workersPlanned) return [];\n\n const planned = node.workersPlanned;\n const launched = node.workersLaunched;\n const shortfall = planned - launched;\n\n return [\n makeFinding(workersNotLaunched, ctx, node, {\n title: `${node.nodeType} got ${fmtInt(launched)} of ${fmtInt(planned)} planned workers`,\n detail: `This ${node.nodeType} planned for ${fmtInt(planned)} parallel worker${\n planned === 1 ? \"\" : \"s\"\n } but only ${fmtInt(launched)} were launched (${fmtInt(shortfall)} short), so part of the work ran serially.`,\n cause:\n \"The global background-worker pool was exhausted: max_worker_processes or max_parallel_workers was already saturated (often by other concurrent parallel queries) when this node tried to start its workers.\",\n remediation: {\n summary: `Raise max_parallel_workers and max_worker_processes so the pool can supply the ${fmtInt(\n planned,\n )} workers this query plans for, and confirm max_parallel_workers_per_gather permits them. If parallelism is not actually speeding this query up, the shortfall is harmless.`,\n steps: [\n \"Check current limits: max_worker_processes, max_parallel_workers, max_parallel_workers_per_gather.\",\n \"max_parallel_workers must be <= max_worker_processes; raise both together (max_worker_processes change needs a restart).\",\n \"Look for other concurrent parallel queries saturating the shared pool during peak load.\",\n \"If a serial plan is no slower here, leave the settings alone — this is informational.\",\n ],\n commands: [\n {\n label: \"Enlarge the global parallel-worker pool\",\n sql: \"ALTER SYSTEM SET max_parallel_workers = '<N>';\\nALTER SYSTEM SET max_worker_processes = '<N+>';\\nSELECT pg_reload_conf();\",\n },\n {\n label: \"Allow more workers per Gather\",\n sql: \"ALTER SYSTEM SET max_parallel_workers_per_gather = '<N>';\\nSELECT pg_reload_conf();\",\n },\n {\n label: \"Inspect the current settings\",\n sql: \"SELECT name, setting FROM pg_settings WHERE name IN ('max_worker_processes', 'max_parallel_workers', 'max_parallel_workers_per_gather');\",\n },\n ],\n },\n docsUrl: `${DOCS}/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS`,\n meta: { planned, launched },\n }),\n ];\n },\n};\n","import type { Rule } from \"../../core/model.ts\";\nimport { bitmapLossy } from \"./bitmap-lossy.ts\";\nimport { cartesianProduct } from \"./cartesian-product.ts\";\nimport { correlatedSubplan } from \"./correlated-subplan.ts\";\nimport { couldBeIndexOnly } from \"./could-be-index-only.ts\";\nimport { filterCouldBeIndexCond } from \"./filter-could-be-index-cond.ts\";\nimport { hashSpillDisk } from \"./hash-spill-disk.ts\";\nimport { highFilterDiscard } from \"./high-filter-discard.ts\";\nimport { indexOnlyHeapFetches } from \"./index-only-heap-fetches.ts\";\nimport { limitLargeOffset } from \"./limit-large-offset.ts\";\nimport { lowCacheHit } from \"./low-cache-hit.ts\";\nimport { memoizeEvictions } from \"./memoize-evictions.ts\";\nimport { nestedLoopLargeOuter } from \"./nested-loop-large-outer.ts\";\nimport { rowMisestimate } from \"./row-misestimate.ts\";\nimport { seqScanLarge } from \"./seq-scan-large.ts\";\nimport { significantJit } from \"./significant-jit.ts\";\nimport { sortSpillDisk } from \"./sort-spill-disk.ts\";\nimport { triggerTime } from \"./trigger-time.ts\";\nimport { workersNotLaunched } from \"./workers-not-launched.ts\";\n\n/**\n * Every advisor rule, in display order (most actionable structural issues first).\n * Rule ids ARE the PGX_* diagnostic codes (greppable, config-keyed). One file per rule.\n */\nexport const ALL_RULES: Rule[] = [\n cartesianProduct,\n seqScanLarge,\n nestedLoopLargeOuter,\n highFilterDiscard,\n limitLargeOffset,\n sortSpillDisk,\n hashSpillDisk,\n memoizeEvictions,\n correlatedSubplan,\n rowMisestimate,\n filterCouldBeIndexCond,\n couldBeIndexOnly,\n indexOnlyHeapFetches,\n bitmapLossy,\n workersNotLaunched,\n lowCacheHit,\n significantJit,\n triggerTime,\n];\n","import { DEFAULT_CONFIG, type PgExplainConfig } from \"../config.ts\";\nimport { bottlenecks, executionMs, nodeLabel } from \"../core/metrics.ts\";\nimport type {\n AnalysisContext,\n AnalysisResult,\n Diagnostic,\n PlanTree,\n Severity,\n} from \"../core/model.ts\";\nimport { flatten } from \"../core/parse.ts\";\nimport { bySeverity, maxSeverity } from \"../diagnostics/diagnostic.ts\";\nimport { fmtMs } from \"../util/format.ts\";\nimport { ALL_RULES } from \"./rules/index.ts\";\n\n/**\n * Run every enabled rule over the tree and assemble the result. Assumes\n * computeMetrics(tree) has already run. Rules that need data the plan lacks\n * (ANALYZE/BUFFERS) are skipped so cost-only plans degrade gracefully.\n */\nexport function runAdvisor(\n tree: PlanTree,\n config: PgExplainConfig = DEFAULT_CONFIG,\n): AnalysisResult {\n const ctx: AnalysisContext = {\n tree,\n thresholds: config.thresholds,\n severityOf: (id, fallback) => config.rules[id]?.severity ?? fallback,\n isEnabled: (id) => config.rules[id]?.enabled !== false,\n };\n\n const nodes = flatten(tree.root);\n const diagnostics: Diagnostic[] = [];\n\n for (const rule of ALL_RULES) {\n if (!ctx.isEnabled(rule.id)) continue;\n if (rule.requiresAnalyze && !tree.hasAnalyze) continue;\n if (rule.requiresBuffers && !tree.hasBuffers) continue;\n for (const node of nodes) {\n for (const finding of rule.check(node, ctx)) diagnostics.push(finding);\n }\n }\n\n diagnostics.sort(bySeverity);\n\n let worst: Severity | null = null;\n for (const d of diagnostics) worst = worst === null ? d.severity : maxSeverity(worst, d.severity);\n\n const bn = bottlenecks(tree, 5);\n return {\n tree,\n diagnostics,\n bottlenecks: bn,\n verdict: buildVerdict(tree, diagnostics, bn),\n worstSeverity: worst,\n };\n}\n\nfunction buildVerdict(\n tree: PlanTree,\n diagnostics: Diagnostic[],\n bn: AnalysisResult[\"bottlenecks\"],\n): string {\n const counts: Record<Severity, number> = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity]++;\n\n const parts: string[] = [];\n if (counts.error) parts.push(`${counts.error} critical`);\n if (counts.warn) parts.push(`${counts.warn} warning${counts.warn > 1 ? \"s\" : \"\"}`);\n if (counts.info) parts.push(`${counts.info} note${counts.info > 1 ? \"s\" : \"\"}`);\n const findings = parts.length ? parts.join(\", \") : \"no issues found\";\n\n const top = bn[0];\n let bottleneck = \"\";\n if (top?.metrics.selfMs !== undefined) {\n const pct =\n top.metrics.pctOfTotal !== undefined\n ? ` (${top.metrics.pctOfTotal.toFixed(0)}% of time)`\n : \"\";\n bottleneck = ` — top cost: ${nodeLabel(top)}${pct}`;\n }\n\n const ms = executionMs(tree);\n const timing = ms !== undefined ? ` Total ${fmtMs(ms)}.` : \" Cost-only plan (no timing).\";\n return `${findings}${bottleneck}.${timing}`;\n}\n","import type { PlanNode, PlanTree } from \"../core/model.ts\";\nimport { walk } from \"../core/parse.ts\";\n\n/**\n * Strip literal values out of a plan so a shared report or CI artifact can't leak\n * real data. VERBOSE output and filter/condition expressions embed constants\n * (e.g. `status = 'shipped'`, `amount > 1000`) — those become `'?'` / `N`.\n *\n * ponytail: regex over expression strings, not a SQL parser. Catches string and\n * numeric literals, which is where real values live; identifiers/operators stay.\n */\nexport function redactExpression(expr: string): string {\n return expr\n .replace(/'(?:[^']|'')*'/g, \"'?'\") // string literals (with '' escapes)\n .replace(/\\b\\d+(?:\\.\\d+)?\\b/g, \"N\"); // numeric literals\n}\n\nconst EXPR_FIELDS = [\n \"filter\",\n \"indexCond\",\n \"recheckCond\",\n \"hashCond\",\n \"joinFilter\",\n] as const satisfies readonly (keyof PlanNode)[];\n\nfunction redactNode(node: PlanNode): void {\n for (const field of EXPR_FIELDS) {\n const value = node[field];\n if (typeof value === \"string\") (node[field] as string) = redactExpression(value);\n }\n if (node.output) node.output = node.output.map(redactExpression);\n if (node.sortKey) node.sortKey = node.sortKey.map(redactExpression);\n}\n\n/** Redact every expression field in the tree, in place. */\nexport function redactPlanTree(tree: PlanTree): void {\n walk(tree.root, redactNode);\n}\n","import type { Diagnostic, PlanNode, PlanTree, Severity } from \"../core/model.ts\";\nimport { walk } from \"../core/parse.ts\";\n\nconst DOCS = \"https://www.postgresql.org/docs/current\";\n\n/**\n * Static lock analysis from the SQL text (+ optional plan). PostgreSQL's EXPLAIN\n * does not show locks, so these findings come from the statement shape and node\n * types. Each is an actionable Diagnostic with a PGX_LOCK_* code.\n */\nexport function analyzeLocks(sql: string, tree?: PlanTree): Diagnostic[] {\n const code = stripSql(sql);\n const upper = code.toUpperCase();\n const kw = (code.trim().split(/\\s+/)[0] ?? \"\").toUpperCase();\n const out: Diagnostic[] = [];\n\n const add = (\n id: string,\n severity: Severity,\n parts: {\n title: string;\n detail: string;\n cause: string;\n fix: string;\n commands?: { label?: string; sql?: string; shell?: string }[];\n },\n ): void => {\n out.push({\n code: id,\n domain: \"plan\",\n severity,\n title: parts.title,\n detail: parts.detail,\n cause: parts.cause,\n remediation: { summary: parts.fix, commands: parts.commands },\n docsUrl: `${DOCS}/explicit-locking.html`,\n });\n };\n\n // Table-rewriting operations → ACCESS EXCLUSIVE for the whole rewrite.\n if (\n /\\bVACUUM\\s+FULL\\b/.test(upper) ||\n /\\bCLUSTER\\b/.test(upper) ||\n /\\bALTER\\s+TABLE\\b[\\s\\S]*\\b(TYPE|SET\\s+DATA\\s+TYPE)\\b/.test(upper)\n ) {\n add(\"PGX_LOCK_TABLE_REWRITE\", \"error\", {\n title: \"Operation rewrites the table under an ACCESS EXCLUSIVE lock\",\n detail:\n \"VACUUM FULL / CLUSTER / a column-type change rewrites the whole table and holds ACCESS EXCLUSIVE for the duration.\",\n cause:\n \"ACCESS EXCLUSIVE blocks every reader and writer until the rewrite finishes — an outage on a busy table.\",\n fix: \"Avoid the full rewrite: use pg_repack for bloat instead of VACUUM FULL/CLUSTER; for type changes, add a new column, backfill in batches, and swap. Always do rewrites off-peak with a lock_timeout.\",\n commands: [{ label: \"Bound the wait\", sql: \"SET lock_timeout = '3s';\" }],\n });\n }\n\n // CREATE/DROP INDEX without CONCURRENTLY.\n if (/\\bCREATE\\s+(UNIQUE\\s+)?INDEX\\b/.test(upper) && !/\\bCONCURRENTLY\\b/.test(upper)) {\n add(\"PGX_DDL_NO_CONCURRENTLY\", \"warn\", {\n title: \"CREATE INDEX without CONCURRENTLY blocks writes\",\n detail:\n \"A plain CREATE INDEX takes a SHARE lock, blocking all writes to the table until the build completes.\",\n cause:\n \"On a large or busy table the build can take minutes, during which inserts/updates/deletes are blocked.\",\n fix: \"Build the index online with CONCURRENTLY (note: it cannot run inside a transaction and may leave an INVALID index on failure, which you then drop and recreate).\",\n commands: [{ label: \"Build online\", sql: \"CREATE INDEX CONCURRENTLY ON <table> (<cols>);\" }],\n });\n }\n if (/\\bDROP\\s+INDEX\\b/.test(upper) && !/\\bCONCURRENTLY\\b/.test(upper)) {\n add(\"PGX_DROP_INDEX_NO_CONCURRENTLY\", \"warn\", {\n title: \"DROP INDEX without CONCURRENTLY takes ACCESS EXCLUSIVE\",\n detail: \"A plain DROP INDEX locks the table with ACCESS EXCLUSIVE.\",\n cause: \"Readers and writers block until the drop completes.\",\n fix: \"Use DROP INDEX CONCURRENTLY to avoid blocking.\",\n commands: [{ label: \"Drop online\", sql: \"DROP INDEX CONCURRENTLY <index>;\" }],\n });\n }\n\n // TRUNCATE / LOCK TABLE.\n if (/\\bTRUNCATE\\b/.test(upper)) {\n add(\"PGX_LOCK_TRUNCATE\", \"info\", {\n title: \"TRUNCATE takes an ACCESS EXCLUSIVE lock\",\n detail: \"TRUNCATE briefly locks the table with ACCESS EXCLUSIVE.\",\n cause:\n \"It is fast (no row scan) but still blocks all access while it runs and is transactional.\",\n fix: \"Fine for maintenance windows; on a hot table, set a lock_timeout so it fails fast instead of queueing behind/ahead of other transactions.\",\n commands: [{ label: \"Bound the wait\", sql: \"SET lock_timeout = '3s';\" }],\n });\n }\n if (/\\bLOCK\\s+TABLE\\b/.test(upper)) {\n add(\"PGX_LOCK_TABLE_EXPLICIT\", \"info\", {\n title: \"Explicit LOCK TABLE\",\n detail:\n \"An explicit LOCK TABLE acquires the named lock mode for the rest of the transaction.\",\n cause: \"Holding a strong lock longer than necessary blocks other sessions.\",\n fix: \"Use the lowest lock mode that suffices and keep the transaction short.\",\n });\n }\n\n // SELECT … FOR UPDATE/SHARE without a LIMIT → locks every matched row.\n if (\n /\\bFOR\\s+(UPDATE|SHARE|NO\\s+KEY\\s+UPDATE|KEY\\s+SHARE)\\b/.test(upper) &&\n !/\\bLIMIT\\b/.test(upper)\n ) {\n add(\"PGX_SELECT_FOR_UPDATE_UNBOUNDED\", \"warn\", {\n title: \"Row-locking SELECT without a LIMIT\",\n detail:\n \"SELECT … FOR UPDATE/SHARE locks every row it matches, held until the transaction ends.\",\n cause:\n \"Locking an unbounded set increases contention and deadlock risk with concurrent updaters.\",\n fix: \"Bound the set with a deterministic ORDER BY + LIMIT (and process in batches); a consistent lock order also avoids deadlocks.\",\n commands: [{ label: \"Bound + order\", sql: \"SELECT … ORDER BY id FOR UPDATE LIMIT 100;\" }],\n });\n }\n\n // UPDATE/DELETE risks.\n if (kw === \"UPDATE\" || kw === \"DELETE\") {\n if (!/\\bWHERE\\b/.test(upper)) {\n add(\"PGX_WRITE_NO_WHERE\", \"warn\", {\n title: `${kw} without a WHERE clause locks every row`,\n detail: `This ${kw} touches the whole table, taking a row lock on every row until commit.`,\n cause:\n \"All rows are locked for the transaction's duration, blocking concurrent writers and bloating the table.\",\n fix: \"Add a WHERE clause; for large rewrites, update in batches (e.g. by primary-key ranges) and commit between batches.\",\n });\n } else if (tree && hasSeqScanOnTarget(tree, targetTable(code, kw))) {\n const rel = targetTable(code, kw);\n add(\"PGX_UPDATE_UNINDEXED_PREDICATE\", \"warn\", {\n title: `${kw} scans ${rel ?? \"the table\"} sequentially to find rows`,\n detail: `The plan uses a Seq Scan on ${rel ?? \"the target table\"}, so the ${kw} reads (and locks the touched rows of) the whole table.`,\n cause:\n \"An unindexed predicate means more rows scanned and locked, and the locks are held until commit.\",\n fix: `Index the ${kw}'s WHERE columns so it finds rows via an index and locks only what it changes.`,\n commands: [\n {\n label: \"Index the predicate\",\n sql: `CREATE INDEX ON ${rel ?? \"<table>\"} (<where columns>);`,\n },\n ],\n });\n }\n }\n\n // Generic DDL → recommend a lock_timeout so a blocked DDL can't queue and block everything behind it.\n if (\n /^(ALTER|CREATE|DROP)\\b/.test(kw) &&\n !/\\bCONCURRENTLY\\b/.test(upper) &&\n !/\\bSET\\s+LOCK_TIMEOUT\\b/.test(upper)\n ) {\n add(\"PGX_DDL_NO_LOCK_TIMEOUT\", \"warn\", {\n title: \"DDL without a lock_timeout can stall the whole table\",\n detail:\n \"This DDL needs a strong lock; if it waits behind a long transaction, every query that arrives after it also queues behind the DDL.\",\n cause:\n \"A blocked ACCESS EXCLUSIVE request sits at the head of the lock queue and blocks new readers/writers too.\",\n fix: \"Set a short lock_timeout before the DDL and retry, so it fails fast instead of forming a queue.\",\n commands: [\n {\n label: \"Fail fast, then retry\",\n sql: \"SET lock_timeout = '3s';\\n-- run the DDL; on timeout, retry later\",\n },\n ],\n });\n }\n\n // Attach a node location to the seq-scan finding where we can.\n return out;\n}\n\n// ── helpers ───────────────────────────────────────────────────────────────────\n\n/** Remove comments, string literals, and quoted identifiers so keyword regexes only see code. */\nfunction stripSql(sql: string): string {\n return sql\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \")\n .replace(/--[^\\n]*/g, \" \")\n .replace(/'(?:[^']|'')*'/g, \"''\")\n .replace(/\"(?:[^\"]|\"\")*\"/g, '\"x\"');\n}\n\nfunction targetTable(code: string, kw: string): string | undefined {\n const re =\n kw === \"DELETE\"\n ? /\\bDELETE\\s+FROM\\s+([A-Za-z_][\\w.]*)/i\n : /\\bUPDATE\\s+(?:ONLY\\s+)?([A-Za-z_][\\w.]*)/i;\n const m = re.exec(code);\n return m?.[1];\n}\n\nfunction hasSeqScanOnTarget(tree: PlanTree, table?: string): boolean {\n let found = false;\n walk(tree.root, (n: PlanNode) => {\n if (n.nodeType === \"Seq Scan\" && (!table || n.relationName === bareName(table))) found = true;\n });\n return found;\n}\n\nfunction bareName(qualified: string): string {\n const parts = qualified.split(\".\");\n return parts[parts.length - 1] ?? qualified;\n}\n","import { executionMs, nodeLabel } from \"../core/metrics.ts\";\nimport type { PlanNode, PlanTree } from \"../core/model.ts\";\nimport { fmtInt, fmtMs, type TreeGlyphs } from \"../util/format.ts\";\n\nexport interface TreeLine {\n node: PlanNode;\n /** Indentation + branch glyphs already applied. */\n prefix: string;\n}\n\n/** Lay out the plan as indented lines. Shared by the markdown/terminal/text renderers. */\nexport function treeLines(tree: PlanTree, glyphs: TreeGlyphs): TreeLine[] {\n const lines: TreeLine[] = [];\n const recurse = (node: PlanNode, indent: string, isLast: boolean, isRoot: boolean): void => {\n const connector = isRoot ? \"\" : isLast ? glyphs.last : glyphs.branch;\n lines.push({ node, prefix: indent + connector });\n const childIndent = isRoot ? \"\" : indent + (isLast ? glyphs.space : glyphs.vert);\n node.children.forEach((child, i) => {\n recurse(child, childIndent, i === node.children.length - 1, false);\n });\n };\n recurse(tree.root, \"\", true, true);\n return lines;\n}\n\n/** A compact, plain-text metric summary for one node (no color). */\nexport function nodeSummary(node: PlanNode): string {\n const m = node.metrics;\n const parts: string[] = [];\n\n if (m.totalRows !== undefined) {\n let rows = `rows=${fmtInt(m.totalRows)}`;\n if (\n m.estimateFactor !== undefined &&\n m.estimateFactor >= 2 &&\n m.estimateDirection !== \"accurate\"\n ) {\n rows += ` (est ${fmtInt(node.planRows)}, ${m.estimateFactor.toFixed(0)}× ${m.estimateDirection})`;\n }\n parts.push(rows);\n } else {\n parts.push(`rows≈${fmtInt(node.planRows)} est`);\n }\n\n if (m.selfMs !== undefined) {\n let t = `self ${fmtMs(m.selfMs)}`;\n if (m.pctOfTotal !== undefined && m.pctOfTotal >= 1) t += ` (${m.pctOfTotal.toFixed(0)}%)`;\n parts.push(t);\n }\n\n if (node.metrics.cacheHitRatio != null) {\n parts.push(`cache ${(node.metrics.cacheHitRatio * 100).toFixed(0)}%`);\n }\n\n return parts.join(\" · \");\n}\n\nexport { executionMs, nodeLabel };\n","import { aggregateStats, executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, PlanNode, Severity } from \"../core/model.ts\";\nimport { flatten } from \"../core/parse.ts\";\nimport { nodeLabel } from \"./tree.ts\";\n\n/** Bump on any breaking change to the JSON shape. Consumers can assert on it. */\nexport const JSON_SCHEMA_VERSION = 1;\n\n/** Stable, machine-readable report for CI and tooling. */\nexport function renderJson(result: AnalysisResult, pretty = true): string {\n return JSON.stringify(buildReport(result), null, pretty ? 2 : 0);\n}\n\n/** The report object behind `renderJson` — used directly by the Studio HTTP API. */\nexport function buildReport(result: AnalysisResult): Record<string, unknown> {\n const { tree, diagnostics, bottlenecks } = result;\n\n const counts: Record<Severity, number> = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity]++;\n\n return {\n schemaVersion: JSON_SCHEMA_VERSION,\n verdict: result.verdict,\n worstSeverity: result.worstSeverity,\n summary: {\n planningTimeMs: tree.planningTime ?? null,\n executionTimeMs: executionMs(tree) ?? null,\n serializationTimeMs: tree.serializationTime ?? null,\n hasAnalyze: tree.hasAnalyze,\n hasBuffers: tree.hasBuffers,\n nodeCount: flatten(tree.root).length,\n findings: counts,\n },\n triggers: tree.triggers,\n jit: tree.jit ?? null,\n settings: tree.settings ?? null,\n diagnostics,\n bottlenecks: bottlenecks\n .filter((n) => (n.metrics.selfMs ?? 0) > 0)\n .map((n) => ({\n id: n.id,\n label: nodeLabel(n),\n nodeType: n.nodeType,\n relation: n.relationName ?? null,\n selfMs: n.metrics.selfMs ?? null,\n pctOfTotal: n.metrics.pctOfTotal ?? null,\n totalRows: n.metrics.totalRows ?? null,\n })),\n stats: aggregateStats(tree),\n plan: serializeNode(tree.root),\n };\n}\n\n/** Slim node for JSON: normalized fields + metrics + children, never the raw blob. */\nexport function serializeNode(node: PlanNode): Record<string, unknown> {\n const { children, metrics, raw, ...fields } = node;\n void raw;\n return { ...fields, metrics, children: children.map(serializeNode) };\n}\n","import { executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, Severity } from \"../core/model.ts\";\nimport { fmtMs, UNICODE_TREE } from \"../util/format.ts\";\nimport { nodeLabel, nodeSummary, treeLines } from \"./tree.ts\";\n\nconst SEV: Record<Severity, { label: string; cls: string }> = {\n error: { label: \"Critical\", cls: \"sev-error\" },\n warn: { label: \"Warning\", cls: \"sev-warn\" },\n info: { label: \"Note\", cls: \"sev-info\" },\n};\n\nfunction esc(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\n/** A single self-contained HTML file: inline CSS, no external assets, safe to email. */\nexport function renderHtml(result: AnalysisResult): string {\n const { tree, diagnostics } = result;\n const ms = executionMs(tree);\n\n const treeHtml = treeLines(tree, UNICODE_TREE)\n .map(({ node, prefix }) => {\n const pct = node.metrics.pctOfTotal ?? 0;\n const heat = pct >= 50 ? \"hot\" : pct >= 20 ? \"warm\" : pct >= 5 ? \"\" : \"cold\";\n return `<div class=\"node ${heat}\"><span class=\"glyph\">${esc(prefix)}</span><span class=\"label\">${esc(nodeLabel(node))}</span> <span class=\"meta\">${esc(nodeSummary(node))}</span></div>`;\n })\n .join(\"\\n\");\n\n const findingsHtml = diagnostics.length\n ? diagnostics.map(findingHtml).join(\"\\n\")\n : '<p class=\"ok\">No anti-patterns detected. 🎉</p>';\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>pg-explain report</title>\n<style>\n :root { color-scheme: light dark; }\n body { font: 15px/1.5 -apple-system, system-ui, sans-serif; margin: 0; padding: 2rem; max-width: 980px; margin-inline: auto; }\n h1 { font-size: 1.4rem; } h2 { font-size: 1.1rem; margin-top: 2rem; border-bottom: 1px solid #8884; padding-bottom: .3rem; }\n .verdict { padding: .75rem 1rem; border-left: 4px solid #888; background: #8881; border-radius: 4px; }\n .verdict.sev-error { border-color: #e5484d; } .verdict.sev-warn { border-color: #f5a623; } .verdict.sev-info { border-color: #4493f8; }\n table { border-collapse: collapse; width: 100%; } td, th { text-align: left; padding: .3rem .6rem; border-bottom: 1px solid #8883; }\n .tree { overflow-x: auto; } .node { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre; font-size: 13px; }\n .glyph { color: #8888; } .meta { color: #888; }\n .node.hot .label { color: #e5484d; font-weight: 700; } .node.warm .label { color: #f5a623; } .node.cold .label { opacity: .6; }\n .finding { border: 1px solid #8883; border-radius: 6px; padding: 1rem; margin: 1rem 0; }\n .finding .tag { font-size: .75rem; font-weight: 700; padding: .1rem .5rem; border-radius: 3px; color: #fff; }\n .sev-error .tag { background: #e5484d; } .sev-warn .tag { background: #f5a623; } .sev-info .tag { background: #4493f8; }\n .finding code, pre { font-family: ui-monospace, monospace; font-size: 13px; }\n pre { background: #8881; padding: .6rem .8rem; border-radius: 4px; overflow-x: auto; }\n .label-cmd { color: #888; font-size: .85rem; margin-top: .5rem; }\n .ok { color: #2e7d32; }\n</style>\n</head>\n<body>\n<h1>pg-explain report</h1>\n<div class=\"verdict ${result.worstSeverity ? SEV[result.worstSeverity].cls : \"\"}\">${esc(result.verdict)}</div>\n\n<h2>Summary</h2>\n<table>\n ${tree.planningTime !== undefined ? `<tr><th>Planning time</th><td>${esc(fmtMs(tree.planningTime))}</td></tr>` : \"\"}\n ${ms !== undefined ? `<tr><th>Execution time</th><td>${esc(fmtMs(ms))}</td></tr>` : \"\"}\n ${!tree.hasAnalyze ? \"<tr><th>Mode</th><td>cost-only (no ANALYZE)</td></tr>\" : \"\"}\n <tr><th>Findings</th><td>${diagnostics.length}</td></tr>\n</table>\n\n<h2>Plan tree</h2>\n<div class=\"tree\">\n${treeHtml}\n</div>\n\n<h2>Findings</h2>\n${findingsHtml}\n</body>\n</html>\n`;\n}\n\nfunction findingHtml(d: Diagnostic): string {\n const sev = SEV[d.severity];\n const steps = d.remediation.steps?.length\n ? `<ul>${d.remediation.steps.map((s) => `<li>${esc(s)}</li>`).join(\"\")}</ul>`\n : \"\";\n const cmds = (d.remediation.commands ?? [])\n .map((c) => {\n const body = c.sql ?? c.shell ?? \"\";\n const label = c.label ? `<div class=\"label-cmd\">${esc(c.label)}</div>` : \"\";\n return `${label}<pre><code>${esc(body)}</code></pre>`;\n })\n .join(\"\");\n const docs = d.docsUrl ? `<p>📖 <a href=\"${esc(d.docsUrl)}\">PostgreSQL docs</a></p>` : \"\";\n const meta = d.location?.relation\n ? ` <span class=\"meta\">on ${esc(d.location.relation)}</span>`\n : \"\";\n\n return `<div class=\"finding ${sev.cls}\">\n <p><span class=\"tag\">${sev.label}</span> <strong>${esc(d.title)}</strong> <code>${esc(d.code)}</code>${meta}</p>\n <p><strong>What:</strong> ${esc(d.detail)}</p>\n <p><strong>Why:</strong> ${esc(d.cause)}</p>\n <p><strong>Fix:</strong> ${esc(d.remediation.summary)}</p>\n ${steps}\n ${cmds}\n ${docs}\n</div>`;\n}\n","import { executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, Severity } from \"../core/model.ts\";\nimport { fmtInt, fmtMs, UNICODE_TREE } from \"../util/format.ts\";\nimport { nodeLabel, nodeSummary, treeLines } from \"./tree.ts\";\n\nconst SEV_LABEL: Record<Severity, string> = {\n error: \"🔴 Critical\",\n warn: \"🟠 Warning\",\n info: \"🔵 Note\",\n};\n\nexport interface MarkdownOptions {\n tldr?: boolean;\n}\n\n/** The headline deliverable: a shareable Markdown report. */\nexport function renderMarkdown(result: AnalysisResult, opts: MarkdownOptions = {}): string {\n const { tree, diagnostics, bottlenecks } = result;\n const out: string[] = [];\n\n out.push(\"# pg-explain report\", \"\");\n out.push(`> **Verdict:** ${result.verdict}`, \"\");\n\n // Summary.\n out.push(\"## Summary\", \"\");\n const ms = executionMs(tree);\n out.push(\"| Metric | Value |\", \"| --- | --- |\");\n if (tree.planningTime !== undefined) out.push(`| Planning time | ${fmtMs(tree.planningTime)} |`);\n if (ms !== undefined) out.push(`| Execution time | ${fmtMs(ms)} |`);\n if (!tree.hasAnalyze) out.push(\"| Mode | cost-only (no ANALYZE) |\");\n out.push(`| Findings | ${summarizeCounts(diagnostics)} |`, \"\");\n\n if (opts.tldr) {\n out.push(...renderFindings(diagnostics, true));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n }\n\n // Plan tree.\n out.push(\"## Plan tree\", \"\", \"```\");\n for (const { node, prefix } of treeLines(tree, UNICODE_TREE)) {\n out.push(`${prefix}${nodeLabel(node)} — ${nodeSummary(node)}`);\n }\n out.push(\"```\", \"\");\n\n // Bottlenecks.\n const ranked = bottlenecks.filter((n) => (n.metrics.selfMs ?? 0) > 0);\n if (ranked.length) {\n out.push(\"## Bottlenecks (by self time)\", \"\");\n out.push(\"| # | Node | Self time | % of total | Rows |\", \"| --- | --- | --- | --- | --- |\");\n ranked.forEach((node, i) => {\n const pct =\n node.metrics.pctOfTotal !== undefined ? `${node.metrics.pctOfTotal.toFixed(1)}%` : \"—\";\n const rows = node.metrics.totalRows !== undefined ? fmtInt(node.metrics.totalRows) : \"—\";\n out.push(\n `| ${i + 1} | ${nodeLabel(node)} | ${fmtMs(node.metrics.selfMs ?? 0)} | ${pct} | ${rows} |`,\n );\n });\n out.push(\"\");\n }\n\n // Findings.\n out.push(...renderFindings(diagnostics, false));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n}\n\nfunction renderFindings(diagnostics: Diagnostic[], tldr: boolean): string[] {\n const out: string[] = [\"## Findings\", \"\"];\n if (diagnostics.length === 0) {\n out.push(\"No anti-patterns detected. 🎉\", \"\");\n return out;\n }\n\n for (const d of diagnostics) {\n out.push(`### ${SEV_LABEL[d.severity]} — ${d.title}`, \"\");\n out.push(`\\`${d.code}\\``, \"\");\n out.push(`**What:** ${d.detail}`, \"\");\n out.push(`**Why:** ${d.cause}`, \"\");\n out.push(`**Fix:** ${d.remediation.summary}`, \"\");\n if (!tldr) {\n if (d.remediation.steps?.length) {\n for (const step of d.remediation.steps) out.push(`- ${step}`);\n out.push(\"\");\n }\n for (const cmd of d.remediation.commands ?? []) {\n const body = cmd.sql ?? cmd.shell ?? \"\";\n const lang = cmd.sql ? \"sql\" : \"sh\";\n if (cmd.label) out.push(`_${cmd.label}:_`);\n out.push(\"```\" + lang, body, \"```\", \"\");\n }\n if (d.docsUrl) out.push(`📖 [PostgreSQL docs](${d.docsUrl})`, \"\");\n }\n }\n return out;\n}\n\nfunction summarizeCounts(diagnostics: Diagnostic[]): string {\n const counts: Record<Severity, number> = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity]++;\n if (diagnostics.length === 0) return \"none\";\n return `${counts.error} critical, ${counts.warn} warning(s), ${counts.info} note(s)`;\n}\n","// picocolors is CommonJS; import the default export and destructure (named ESM\n// imports fail at runtime). tsup keeps it external, so this resolves to the CJS module.\nimport pc from \"picocolors\";\n\nconst { createColors, isColorSupported } = pc;\n\ntype Colors = ReturnType<typeof createColors>;\n\n// picocolors already honors NO_COLOR / FORCE_COLOR / TTY. configureColor lets the\n// CLI override that with --color/--no-color.\nlet active: Colors = createColors(isColorSupported);\n\nexport function configureColor(mode: \"auto\" | \"always\" | \"never\"): void {\n active = createColors(mode === \"always\" || (mode === \"auto\" && isColorSupported));\n}\n\n/** Current color functions. Renderers call this so --no-color takes effect. */\nexport function colors(): Colors {\n return active;\n}\n","import { executionMs } from \"../core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, PlanNode, Severity } from \"../core/model.ts\";\nimport { colors } from \"../util/color.ts\";\nimport { ASCII_TREE, fmtMs, UNICODE_TREE } from \"../util/format.ts\";\nimport { nodeLabel, nodeSummary, treeLines } from \"./tree.ts\";\n\nexport interface TerminalOptions {\n /** ASCII tree glyphs + no bars; suitable for logs / screen readers. */\n ascii?: boolean;\n bars?: boolean;\n tldr?: boolean;\n}\n\nconst SEV_TAG: Record<Severity, string> = { error: \"CRITICAL\", warn: \"WARNING\", info: \"NOTE\" };\n\nfunction sevColor(sev: Severity, text: string): string {\n const c = colors();\n if (sev === \"error\") return c.red(c.bold(text));\n if (sev === \"warn\") return c.yellow(text);\n return c.cyan(text);\n}\n\n/** Heat the node label by its share of total time. */\nfunction heat(node: PlanNode, text: string): string {\n const c = colors();\n const pct = node.metrics.pctOfTotal;\n if (pct === undefined) return text;\n if (pct >= 50) return c.red(c.bold(text));\n if (pct >= 20) return c.yellow(text);\n if (pct >= 5) return text;\n return c.dim(text);\n}\n\nfunction bar(pct: number, width = 8): string {\n const filled = Math.round((pct / 100) * width);\n return \"▇\".repeat(Math.min(filled, width)) + \"▁\".repeat(Math.max(width - filled, 0));\n}\n\nexport function renderTerminal(result: AnalysisResult, opts: TerminalOptions = {}): string {\n const c = colors();\n const { tree, diagnostics, bottlenecks } = result;\n const glyphs = opts.ascii ? ASCII_TREE : UNICODE_TREE;\n const out: string[] = [];\n\n out.push(c.bold(\"pg-explain report\"));\n out.push(`${c.bold(\"Verdict:\")} ${verdictColored(result)}`);\n out.push(\"\");\n\n if (opts.tldr) {\n out.push(...findingsBlock(diagnostics, opts));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n }\n\n // Plan tree.\n out.push(c.bold(\"Plan tree\"));\n for (const { node, prefix } of treeLines(tree, glyphs)) {\n const heatBar =\n opts.bars !== false && node.metrics.pctOfTotal !== undefined\n ? ` ${c.dim(bar(node.metrics.pctOfTotal))}`\n : \"\";\n out.push(\n `${c.dim(prefix)}${heat(node, nodeLabel(node))}${heatBar} ${c.dim(nodeSummary(node))}`,\n );\n }\n out.push(\"\");\n\n // Bottlenecks.\n const ranked = bottlenecks.filter((n) => (n.metrics.selfMs ?? 0) > 0);\n if (ranked.length) {\n out.push(c.bold(\"Bottlenecks (by self time)\"));\n ranked.forEach((node, i) => {\n const pct =\n node.metrics.pctOfTotal !== undefined ? `${node.metrics.pctOfTotal.toFixed(0)}%` : \"—\";\n out.push(\n ` ${i + 1}. ${heat(node, nodeLabel(node))} — ${fmtMs(node.metrics.selfMs ?? 0)} (${pct})`,\n );\n });\n out.push(\"\");\n }\n\n out.push(...findingsBlock(diagnostics, opts));\n const ms = executionMs(tree);\n if (ms !== undefined) out.push(c.dim(`Total execution time: ${fmtMs(ms)}`));\n return `${out.join(\"\\n\").trimEnd()}\\n`;\n}\n\nfunction verdictColored(result: AnalysisResult): string {\n if (result.worstSeverity === null) return colors().green(result.verdict);\n return sevColor(result.worstSeverity, result.verdict);\n}\n\nfunction findingsBlock(diagnostics: Diagnostic[], opts: TerminalOptions): string[] {\n const c = colors();\n const out: string[] = [c.bold(\"Findings\")];\n if (diagnostics.length === 0) {\n out.push(` ${c.green(\"No anti-patterns detected.\")}`, \"\");\n return out;\n }\n for (const d of diagnostics) {\n out.push(\"\");\n out.push(\n `${sevColor(d.severity, `[${SEV_TAG[d.severity]}]`)} ${c.bold(d.title)} ${c.dim(d.code)}`,\n );\n out.push(` ${c.dim(\"What:\")} ${d.detail}`);\n out.push(` ${c.dim(\"Why: \")} ${d.cause}`);\n out.push(` ${c.dim(\"Fix: \")} ${d.remediation.summary}`);\n if (!opts.tldr) {\n for (const step of d.remediation.steps ?? []) out.push(` - ${step}`);\n for (const cmd of d.remediation.commands ?? []) {\n const body = cmd.sql ?? cmd.shell ?? \"\";\n const label = cmd.label ? `${c.dim(`${cmd.label}:`)} ` : \"\";\n out.push(` ${label}${c.green(body)}`);\n }\n if (d.docsUrl) out.push(` ${c.dim(`docs: ${d.docsUrl}`)}`);\n }\n }\n out.push(\"\");\n return out;\n}\n","import type { AnalysisResult } from \"../core/model.ts\";\nimport { renderHtml } from \"./html.ts\";\nimport { renderJson } from \"./json.ts\";\nimport { renderMarkdown } from \"./markdown.ts\";\nimport { renderTerminal } from \"./terminal.ts\";\n\nexport type Format = \"terminal\" | \"markdown\" | \"json\" | \"html\" | \"text\";\n\nexport const FORMATS: Format[] = [\"terminal\", \"markdown\", \"json\", \"html\", \"text\"];\n\nexport function isFormat(s: string): s is Format {\n return (FORMATS as string[]).includes(s);\n}\n\nexport interface RenderOptions {\n format: Format;\n /** Summary + findings only, no plan tree. */\n tldr?: boolean;\n /** ASCII tree glyphs (terminal/text). */\n ascii?: boolean;\n /** Pretty-print JSON. */\n pretty?: boolean;\n}\n\n/** Render an analysis result to the requested format. Color is configured by the caller. */\nexport function render(result: AnalysisResult, opts: RenderOptions): string {\n switch (opts.format) {\n case \"markdown\":\n return renderMarkdown(result, { tldr: opts.tldr });\n case \"json\":\n return renderJson(result, opts.pretty ?? true);\n case \"html\":\n return renderHtml(result);\n case \"text\":\n // Plain text: ASCII tree, no bars. Caller disables color for this format.\n return renderTerminal(result, { ascii: true, bars: false, tldr: opts.tldr });\n default:\n return renderTerminal(result, { ascii: opts.ascii, tldr: opts.tldr });\n }\n}\n","/**\n * Public library API. Consumers can parse, analyze, and render plans programmatically:\n *\n * import { analyze, render } from \"pgexplain\";\n * const result = analyze(explainJsonText);\n * console.log(render(result, { format: \"markdown\" }));\n */\nimport { runAdvisor } from \"./advisor/index.ts\";\nimport { DEFAULT_CONFIG, type PgExplainConfig } from \"./config.ts\";\nimport { computeMetrics } from \"./core/metrics.ts\";\nimport type { AnalysisResult, Diagnostic, PlanTree, Severity } from \"./core/model.ts\";\nimport { flatten, parseExplain } from \"./core/parse.ts\";\nimport { opDiagnostic, opError } from \"./diagnostics/catalog.ts\";\nimport { bySeverity, maxSeverity } from \"./diagnostics/diagnostic.ts\";\nimport { redactPlanTree } from \"./input/redact.ts\";\nimport { analyzeLocks } from \"./locks/advisor.ts\";\n\nexport interface AnalyzeOptions {\n config?: PgExplainConfig;\n /** 1-based statement index when the input holds more than one. */\n statement?: number;\n /** Strip literal values from expressions before analysis (no data leaks downstream). */\n redact?: boolean;\n /** The originating SQL — enables lock analysis (PGX_LOCK_* findings). */\n sql?: string;\n}\n\n/** Parse → (redact) → compute metrics → run advisor (+lock advisor) → attach notices. */\nexport function analyze(input: string, options: AnalyzeOptions = {}): AnalysisResult {\n const trees = parseExplain(input);\n const tree = selectStatement(trees, options.statement);\n if (options.redact) redactPlanTree(tree);\n computeMetrics(tree);\n\n const result = runAdvisor(tree, options.config ?? DEFAULT_CONFIG);\n\n const extra: Diagnostic[] = planNotices(tree);\n if (options.sql) extra.push(...analyzeLocks(options.sql, tree));\n if (extra.length) {\n result.diagnostics = [...result.diagnostics, ...extra].sort(bySeverity);\n result.worstSeverity = result.diagnostics.reduce<Severity | null>(\n (worst, d) => (worst === null ? d.severity : maxSeverity(worst, d.severity)),\n null,\n );\n }\n return result;\n}\n\nfunction selectStatement(trees: PlanTree[], statement?: number): PlanTree {\n if (statement !== undefined) {\n const tree = trees[statement - 1];\n if (!tree) {\n throw opError(\"PGX_MULTIPLE_STATEMENTS\", {\n detail: `--statement ${statement} is out of range; the input has ${trees.length} statement(s).`,\n });\n }\n return tree;\n }\n const first = trees[0];\n if (!first) throw opError(\"PGX_UNEXPECTED_PLAN_SHAPE\"); // schema guarantees ≥1, defensive\n return first;\n}\n\n/** Informational diagnostics about the plan's completeness (cost-only, no buffers, …). */\nfunction planNotices(tree: PlanTree): Diagnostic[] {\n const notices: Diagnostic[] = [];\n if (!tree.hasAnalyze) notices.push(opDiagnostic(\"PGX_COST_ONLY_PLAN\"));\n else if (!tree.hasBuffers) notices.push(opDiagnostic(\"PGX_NO_BUFFERS\"));\n\n const nodes = flatten(tree.root);\n const trivial = nodes.length === 1 && /^(Result|Values? Scan)$/.test(tree.root.nodeType);\n if (trivial) notices.push(opDiagnostic(\"PGX_EMPTY_PLAN\"));\n\n return notices;\n}\n\nexport { runAdvisor } from \"./advisor/index.ts\";\nexport { DEFAULT_CONFIG, DEFAULT_THRESHOLDS, type PgExplainConfig } from \"./config.ts\";\nexport { bottlenecks, computeMetrics, executionMs, nodeLabel } from \"./core/metrics.ts\";\nexport type * from \"./core/model.ts\";\nexport { flatten, parseExplain, parseExplainJson, walk } from \"./core/parse.ts\";\nexport { AppError, scrubCredentials, severityAtLeast } from \"./diagnostics/diagnostic.ts\";\nexport { analyzeLocks } from \"./locks/advisor.ts\";\nexport { JSON_SCHEMA_VERSION } from \"./report/json.ts\";\nexport { FORMATS, type Format, isFormat, type RenderOptions, render } from \"./report/render.ts\";\nexport { ExitCode } from \"./util/exit.ts\";\n"]}