Skip to content

feat(postgres-adapter): implement IDbAdapter contract (Phase 3a) - #7

Closed
ihistand wants to merge 1 commit into
adapter/postgres-proto-additionsfrom
adapter/postgres-skeleton
Closed

feat(postgres-adapter): implement IDbAdapter contract (Phase 3a)#7
ihistand wants to merge 1 commit into
adapter/postgres-proto-additionsfrom
adapter/postgres-skeleton

Conversation

@ihistand

Copy link
Copy Markdown
Collaborator

Summary

Phase 3a of `adapter/postgres-first-class` per `docs/postgres_first_class_design.md` §6 + the assessment doc Phase 3 / Phase 5.

Rewrites `cli/api/dbadapters/postgres.ts` so it compiles against the modern `IDbAdapter` interface, and wires the BUILD targets so the file is part of `//cli/api` again (drops the Phase 2 excludes).

Interface alignment

Item Change
credentials type `sqlanvil.IJDBC` → `sqlanvil.IPostgresConnection` (from Phase 3c)
`execute()` returns `IExecutionResult { rows, metadata }` — was raw `any[]`
`executeRaw()` new — `IExecutionResultRaw { rows, schema, metadata }` (schema empty; catalog query path is what callers use for shape)
`withClientLock()` callback receives an `IDbClient` with both `execute()` and `executeRaw()` shimmed over the underlying `pg` pool client
`schemas(database)` now takes the `database` arg (ignored — Postgres is db-scoped), filters `pg_*` + `information_schema`
`tables(database, schema?)` returns `ITableMetadata[]` (was `ITarget[]`); hydrates full metadata per row; optional schema filter
`deleteTable(target)` new — `drop table|view if exists ... cascade` keyed on the actual catalog type
`setMetadata()` guards against null `actualMetadata` instead of crashing

Modernization (assessment doc §Phase 5)

  • Drop `SSHTunnelProxy` — Supabase + managed Postgres serve TLS on a public TCP port; SSH tunnel is no longer needed. `SSHTunnelProxy` was deleted upstream in commit `b4d2b2f2`.
  • Drop `parseRedshiftEvalError` — replaced with `parsePostgresEvalError` in `cli/api/utils/error_parsing.ts`. `pg` errors carry `.position` (byte offset) but not line/column, so we preserve the message only.
  • Drop `preview()` — wasn't in `IDbAdapter`.

SSL handling

`ssl_mode` Behavior
`disable` no TLS
`verify-ca` / `verify-full` strict cert verification
``` (empty) / `require` / `prefer` / `allow` TLS with `rejectUnauthorized=false` (matches default Supabase / RDS UX)

BUILD wiring

`cli/api/BUILD`:

  • Drop `dbadapters/postgres.ts` exclude
  • Add `@npm//pg`, `@npm//@types/pg` deps

`cli/api/utils/BUILD`:

  • Drop `postgres.ts` exclude
  • Add `@npm//pg`, `@npm//@types/pg`, `@npm//pg-query-stream` deps

Verification

```bash
./scripts/docker-bazel build //cli/api/... # → 8 targets, success
./scripts/docker-bazel build //... # → 139 targets, success
./scripts/docker-bazel test //... # → 38/41 pass
```

Same 3 pre-existing failures (2× missing BQ creds, 1× projects.spec `warehouse` validation) — none regressed by this PR.

Stack

Stacked on PR #6 (`adapter/postgres-proto-additions`). Merge order: #1#2#3#4#5#6 → this.

Next

Phase 3b — Postgres SQL generator under `core/compilation_sql/postgres/` with golden-output tests per action type.

Test plan

  • `./scripts/docker-bazel build //cli/api/...`
  • `./scripts/docker-bazel build //...`
  • `./scripts/docker-bazel test //...` (38/41 — no regressions)
  • Integration tests against a real Postgres (Phase 6)

🤖 Generated with Claude Code

Rewrites cli/api/dbadapters/postgres.ts so it compiles against the
modern IDbAdapter interface, and wires the BUILD targets so the file
is part of the //cli/api library again (drops the Phase 2 excludes).

Interface alignment per docs/postgres_first_class_design.md §6 +
docs/postgres_reintegration_assessment.md §Phase 3:

- credentials              sqlanvil.IJDBC → sqlanvil.IPostgresConnection
                           (new proto from Phase 3c)
- execute()                returns IExecutionResult { rows, metadata }
                           — was raw any[]
- executeRaw()             new, returns IExecutionResultRaw { rows,
                           schema, metadata } — schema kept empty (we
                           lean on the catalog query path for shape)
- withClientLock()         callback receives an IDbClient with both
                           execute() and executeRaw() shimmed over the
                           underlying pg pool client
- schemas(database)        now takes the database arg (ignored, since
                           Postgres is database-scoped), and filters
                           pg_catalog / pg_toast / pg_internal /
                           information_schema
- tables(database, schema) returns ITableMetadata[] (was ITarget[]) —
                           hydrates full metadata per row. Optional
                           schema filter is supported.
- deleteTable(target)      new — transactional `drop table|view if exists
                           ... cascade` keyed on the actual catalog type
- setMetadata()            guards against null actualMetadata (table
                           doesn't exist yet) instead of crashing

Modernization (assessment doc §Phase 5):

- Drop SSHTunnelProxy block — Supabase + most managed Postgres serve
  TLS on a public TCP port; SSH tunnel is no longer needed. The
  SSHTunnelProxy class was deleted upstream in commit b4d2b2f.
- Drop parseRedshiftEvalError — replaced with parsePostgresEvalError in
  cli/api/utils/error_parsing.ts. pg errors carry `.position` (byte
  offset) but not line/column, so we preserve the message only.
- Drop preview() — wasn't in IDbAdapter.

SSL handling tightened:
  ssl_mode = "disable"         → no TLS
  ssl_mode = "verify-ca"|"verify-full" → strict cert verification
  ssl_mode = "" | "require" | "prefer" | "allow"
                               → TLS with rejectUnauthorized=false
                               (matches default Supabase / RDS UX)

BUILD wiring:
- cli/api/BUILD: drop `dbadapters/postgres.ts` exclude; add `@npm//pg`
  and `@npm//@types/pg` deps.
- cli/api/utils/BUILD: drop `postgres.ts` exclude; add `@npm//pg`,
  `@npm//@types/pg`, `@npm//pg-query-stream` deps.

Verified:
  ./scripts/docker-bazel build //cli/api/...   → 8 targets, success
  ./scripts/docker-bazel build //...           → 139 targets, success
  ./scripts/docker-bazel test  //...           → 38/41 pass (same 3
    pre-existing failures: 2× missing BQ creds, 1× projects.spec
    `warehouse` validation issue — none regressed by this PR)

Next phase (Phase 3b): Postgres SQL generator under
core/compilation_sql/postgres/ — one generator per action type with
golden-output tests.
@ihistand

ihistand commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded: the Postgres reintegration + Dataform→SQLAnvil rename landed on main directly, and the docs moved to the SQLAnvil/docs repo. Closing as part of #12 (stale-branch prune). The one un-migrated draft, gcp_test_project_setup.md, was migrated to SQLAnvil/docs.

@ihistand ihistand closed this Jun 7, 2026
@ihistand
ihistand deleted the adapter/postgres-skeleton branch June 7, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant