From 73c07fdf68461a1de768b162263fc035a6ea0f24 Mon Sep 17 00:00:00 2001 From: 7487 <1042653432@qq.com> Date: Tue, 8 Sep 2026 02:24:13 +0800 Subject: [PATCH] docs(postgres): cite code by name, not by line postgres.md pinned 17 citations to line numbers in postgres.ts, sql-base.ts and query-limiter.ts, and every checkable one was stale: validate() cited :264 is declared at :1005, getCapabilities() cited :250 at :955, and the three sql-base.ts methods missed by -16, +3 and +3. Each now names the declaration and links the file the way mssql.md, mysql.md, oracle.md and mongodb.md already do; the two range citations name the CTE_*_INFO consts the ranges used to cover. The doc joins NAMED_CITATIONS in the guard, so it can carry no `.ts:` and every method it names must really be declared in postgres.ts. Reverting the doc alone fails 1 of 29. Fixes #589 Co-Authored-By: Claude Fable 5.1 --- docs/providers/postgres.md | 39 ++++++++++--------- ...provider-docs-monitoring-citations.test.ts | 15 +++++++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/docs/providers/postgres.md b/docs/providers/postgres.md index fda75621..e797ec25 100644 --- a/docs/providers/postgres.md +++ b/docs/providers/postgres.md @@ -79,11 +79,11 @@ rather than reimplementing them: | Member | Purpose | |--------|---------| -| `escapeIdentifier()` ([sql-base.ts:33](../../src/lib/db/providers/sql/sql-base.ts)) | Dialect-aware quoting — `"ident"` for Postgres, `` `ident` `` for MySQL, `[ident]` for MSSQL; doubles embedded quote chars | +| `escapeIdentifier()` ([`sql-base.ts`](../../src/lib/db/providers/sql/sql-base.ts)) | Dialect-aware quoting — `"ident"` for Postgres, `` `ident` `` for MySQL, `[ident]` for MSSQL; doubles embedded quote chars | | `positionalPlaceholder()` ([values.ts](../../src/lib/sql/values.ts), shared rather than inherited) | `$1`-style placeholders for Postgres (`?` for MySQL/SQLite/Druid, `:n` Oracle, `@pn` MSSQL, `$n` Couchbase) | -| `shouldEnableSSL()` ([sql-base.ts:75](../../src/lib/db/providers/sql/sql-base.ts)) | Auto-enables SSL for known cloud hosts (supabase, neon, render, planetscale, aws, azure, gcp, …) | -| `getDefaultSchema()` ([sql-base.ts:91](../../src/lib/db/providers/sql/sql-base.ts)) | `public` for Postgres | -| `prepareQuery()` ([sql-base.ts:137](../../src/lib/db/providers/sql/sql-base.ts)) | Injects `LIMIT` into bare `SELECT`s — see [§5.2](#52-automatic-limit-injection) | +| `shouldEnableSSL()` ([`sql-base.ts`](../../src/lib/db/providers/sql/sql-base.ts)) | Auto-enables SSL for known cloud hosts (supabase, neon, render, planetscale, aws, azure, gcp, …) | +| `getDefaultSchema()` ([`sql-base.ts`](../../src/lib/db/providers/sql/sql-base.ts)) | `public` for Postgres | +| `prepareQuery()` ([`sql-base.ts`](../../src/lib/db/providers/sql/sql-base.ts)) | Injects `LIMIT` into bare `SELECT`s — see [§5.2](#52-automatic-limit-injection) | ### 2.3 Registration & lifecycle @@ -111,7 +111,8 @@ These are the non-obvious choices. Read this section before changing the provide ### 3.1 `MATERIALIZED` CTEs for schema introspection This is the single most important detail in the file. All schema-introspection CTEs are declared -`AS MATERIALIZED` ([postgres.ts:86–177](../../src/lib/db/providers/sql/postgres.ts)). PostgreSQL 12+ +`AS MATERIALIZED` (the `CTE_*_INFO` consts in +[`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)). PostgreSQL 12+ *inlines* single-reference CTEs by default, which lets the planner re-execute these `information_schema`-based CTEs inside nested-loop joins (it estimates `rows=1` for them). On a large schema (100+ tables/constraints/indexes) that explodes into minutes of planning/execution. @@ -307,7 +308,7 @@ default. ### 3.2 Schema SQL hoisted to module scope `SCHEMA_FULL_SQL`, `SCHEMA_LIST_SQL`, and `SCHEMA_RELATIONS_SQL` are module-level `const`s, not -inline template literals inside the methods ([postgres.ts:86–226](../../src/lib/db/providers/sql/postgres.ts)). +inline template literals inside the methods ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)). This is a **coverage** workaround: `bun`'s coverage instruments the interior lines of a multi-line template literal *in a function body* as 0-hit in any test process that imports the file but does not exercise that method, and the merged lcov then reports those SQL lines as uncovered. Evaluated @@ -333,9 +334,9 @@ N+1 pattern of `1 + N*4` queries). The two-phase split is the path the UI actual Tables in the `public` schema are shown by bare name; tables in any other schema are prefixed (`reporting.invoices`). The same rule is applied to **foreign-key referenced tables**, so a FK that -points across schemas renders correctly. The FK introspection CTE joins -`constraint_column_usage` on **both** `constraint_name` and `constraint_schema` -([postgres.ts:148–150](../../src/lib/db/providers/sql/postgres.ts)) — joining on name alone +points across schemas renders correctly. The FK introspection CTE (`CTE_FK_INFO`, +[`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)) joins `constraint_column_usage` on +**both** `constraint_name` and `constraint_schema` — joining on name alone mis-resolves same-named constraints in different schemas (this was a real bug; there is a regression test for it). @@ -376,7 +377,7 @@ Monitoring never hard-fails on a missing optional feature: ### 3.6 Safe maintenance targets -`qualifyMaintenanceTarget()` ([postgres.ts:751](../../src/lib/db/providers/sql/postgres.ts)) quotes +`qualifyMaintenanceTarget()` ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)) quotes maintenance targets through `escapeIdentifier()`: a bare name defaults to the `public` schema; a `schema.table` target is quoted per-part. This prevents identifier injection in `VACUUM`/`ANALYZE`/ `REINDEX` statements (which cannot use bind parameters for object names). @@ -387,7 +388,7 @@ maintenance targets through `escapeIdentifier()`: a bare name defaults to the `p ### 4.1 Configuration -Two forms are accepted (`validate()`, [postgres.ts:264](../../src/lib/db/providers/sql/postgres.ts)). +Two forms are accepted (`validate()`, [`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)). `validate()` requires `host` **and** `database` only when no `connectionString` is given — it does **not** reject supplying both. If both are present the **connection string wins**: `buildPoolConfig()` uses it and ignores the discrete fields. @@ -448,7 +449,7 @@ server. Paste the certificate content instead. ### 4.2 Connection pooling -`connect()` builds a `pg.Pool` ([postgres.ts:281](../../src/lib/db/providers/sql/postgres.ts)) and +`connect()` builds a `pg.Pool` ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)) and validates it by acquiring and releasing one client. Pool **sizing** comes from `ProviderOptions.pool` merged over `DEFAULT_POOL_CONFIG`: @@ -487,7 +488,7 @@ oracledb expose no pool-level `error` event at all, which is recorded at each pr ### 4.3 SSL -`buildSSLConfig()` ([postgres.ts:342](../../src/lib/db/providers/sql/postgres.ts)) resolves SSL with +`buildSSLConfig()` ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)) resolves SSL with this precedence: 1. **Explicit `connection.ssl`** (`SSLConfig`, mode = `disable` | `require` | `verify-system` | @@ -511,7 +512,7 @@ this precedence: ### 5.1 Execution -`query(sql, params?, queryId?)` ([postgres.ts:378](../../src/lib/db/providers/sql/postgres.ts)) +`query(sql, params?, queryId?)` ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)) acquires a pooled client, optionally records its backend PID for cancellation, runs the (optionally parameterized — `$1`, `$2`, …) statement, and returns the standard envelope: @@ -526,7 +527,7 @@ timeout → `TimeoutError`, etc.). ### 5.2 Automatic `LIMIT` injection `prepareQuery()` (inherited from `SQLBaseProvider`) protects the UI from runaway result sets. It -runs the query through `analyzeQuery()` ([query-limiter.ts:88](../../src/lib/db/utils/query-limiter.ts)) +runs the query through `analyzeQuery()` ([`query-limiter.ts`](../../src/lib/db/utils/query-limiter.ts)) and, **only for `SELECT`/CTE-`SELECT` queries that don't already have a `LIMIT`**, appends one via `applyQueryLimit()`: @@ -617,7 +618,7 @@ comment-led final `SELECT`; it now reads `isSelectQuery()` from the same classif ### 5.3 Query cancellation A query issued with a `queryId` records its backend PID in a `Map`. `cancelQuery(queryId)` -([postgres.ts:412](../../src/lib/db/providers/sql/postgres.ts)) looks the PID up and calls +([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)) looks the PID up and calls `pg_cancel_backend(pid)` on a fresh pooled client, returning whether the cancel signalled. Exposed via `POST /api/db/cancel`. @@ -756,7 +757,7 @@ the client is not returned to the pool until commit/rollback. Surfaced via `POST | Method | Behaviour | |--------|-----------| -| `beginTransaction()` | Acquires a client, runs `BEGIN`, arms a **5-minute auto-rollback** timer ([postgres.ts:461](../../src/lib/db/providers/sql/postgres.ts), duration set by `TX_TIMEOUT_MS`). Throws if one is already active. | +| `beginTransaction()` | Acquires a client, runs `BEGIN`, arms a **5-minute auto-rollback** timer ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts), duration set by `TX_TIMEOUT_MS`). Throws if one is already active. | | `queryInTransaction(sql, params?)` | Runs on the transaction's client. Throws if none active. | | `commitTransaction()` / `rollbackTransaction()` | Ends the transaction, clears the timer, releases the client. Throws if none active. | | `expireTransaction()` | The timeout callback — auto-`ROLLBACK` to prevent leaked locks if a transaction is abandoned. | @@ -775,7 +776,7 @@ connection — including the ten providers that answer HTTP 400. ## 9. Maintenance -`runMaintenance(type, target?)` ([postgres.ts:762](../../src/lib/db/providers/sql/postgres.ts)), +`runMaintenance(type, target?)` ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)), with targets quoted via [§3.6](#36-safe-maintenance-targets): | Type | With target | Without target | @@ -819,7 +820,7 @@ really means `vacuum` here, so `vacuumActionOperation` stays absent. ## 10. Capabilities & labels -### `getCapabilities()` ([postgres.ts:250](../../src/lib/db/providers/sql/postgres.ts)) +### `getCapabilities()` ([`postgres.ts`](../../src/lib/db/providers/sql/postgres.ts)) Overrides the SQL base defaults: diff --git a/tests/unit/provider-docs-monitoring-citations.test.ts b/tests/unit/provider-docs-monitoring-citations.test.ts index 44130bb8..fb402fa3 100644 --- a/tests/unit/provider-docs-monitoring-citations.test.ts +++ b/tests/unit/provider-docs-monitoring-citations.test.ts @@ -148,6 +148,21 @@ const NAMED_CITATIONS = [ "getActiveSessions", ], }, + { + doc: "docs/providers/postgres.md", + source: "src/lib/db/providers/sql/postgres.ts", + methods: [ + "getCapabilities", + "qualifyMaintenanceTarget", + "validate", + "connect", + "buildSSLConfig", + "query", + "cancelQuery", + "beginTransaction", + "runMaintenance", + ], + }, ] as const; const SEARCH_DOCS = ["docs/providers/elasticsearch.md", "docs/providers/opensearch.md"] as const;