Skip to content

fix: add foreign-table coverage to pg_advisor and pg_describe_table#18

Open
HighviewOne wants to merge 2 commits into
mainfrom
fix/foreign-table-coverage
Open

fix: add foreign-table coverage to pg_advisor and pg_describe_table#18
HighviewOne wants to merge 2 commits into
mainfrom
fix/foreign-table-coverage

Conversation

@HighviewOne

Copy link
Copy Markdown
Collaborator

Closes #10.

What

Two gaps in foreign-table (relkind='f') coverage:

  1. pg_advisor.tables_without_primary_key filtered relkind IN ('r', 'p') and silently skipped foreign tables. A foreign table without a defined PK is the same design-drift signal — the constraint isn't enforced by the FDW but it communicates schema intent.

  2. pg_describe_table already had the 'foreign_table' branch in its CASE expression but no fixture exercised it, leaving that branch untested.

Changes

src/tools/admin.ts

  • relkind IN ('r', 'p')relkind IN ('r', 'p', 'f') in pg_advisor
  • Description updated to mention foreign tables

src/integration/fixtures.ts

  • setupFdwFixture(): best-effort self-referential postgres_fdw setup. Parses DATABASE_URL, creates a SERVER, USER MAPPING, and remote_users foreign table pointing back at the same cluster. Returns false when postgres_fdw is unavailable so dependent assertions skip gracefully.
  • fdwFixtureAvailable(): exported flag read by tests
  • setupFixtures() calls setupFdwFixture() at the end; teardownFixtures() drops the cluster-level SERVER (schema CASCADE handles the foreign table itself)

Integration tests

  • pg_advisor: remote_users (no defined PK) appears in tables_without_primary_key
  • pg_describe_table: remote_users has kind='foreign_table' with correct columns
  • pg_list_tables: hardcoded name list updated to include remote_users when FDW is available

All 88 integration tests pass (87 existing + 1 new pg_describe_table test). FDW-dependent assertions skip cleanly when postgres_fdw is unavailable.

🤖 Generated with Claude Code

Closes #10.

pg_advisor.tables_without_primary_key filtered relkind IN ('r','p') and
silently missed foreign tables (relkind='f'). A foreign table without a
defined PK is the same design-drift signal as a heap table -- the PK is
not enforced by the FDW but it communicates schema intent. Expand to
relkind IN ('r','p','f').

pg_describe_table already had the 'foreign_table' branch in its CASE
expression but no fixture exercised it, leaving that branch untested.

Fixture additions (fixtures.ts):
- setupFdwFixture(): best-effort self-referential postgres_fdw setup that
  parses DATABASE_URL and creates a SERVER, USER MAPPING, and foreign table
  remote_users pointing back at the same cluster. Returns false when
  postgres_fdw is unavailable so dependent tests skip gracefully.
- fdwFixtureAvailable(): exported flag read by tests to skip FDW assertions.
- setupFixtures() calls setupFdwFixture() at the end; teardownFixtures()
  drops the cluster-level SERVER (schema CASCADE handles the foreign table).

New tests:
- pg_advisor: remote_users (no defined PK) appears in tables_without_primary_key
- pg_describe_table: remote_users has kind='foreign_table' with columns
- pg_list_tables: assertion updated to include remote_users when FDW is available

88 integration tests pass (87 existing + 1 new).
@jeffyaw

jeffyaw commented Jun 11, 2026

Copy link
Copy Markdown
Member

Review punch list for this PR. Item 1 is the blocker; the FDW fixture work itself is solid (best-effort setup, OPTIONS values escaped, cluster-level SERVER cleaned up in teardown) and the pg_describe_table foreign-table test is a good add.

  1. src/tools/admin.ts (relkind IN ('r', 'p', 'f')) -- blocker: PostgreSQL does not allow PRIMARY KEY (or UNIQUE) constraints on foreign tables at all -- verified against the PG 18 CREATE FOREIGN TABLE docs, which permit only NOT NULL / CHECK / DEFAULT / GENERATED. So every foreign table in every database permanently lands in tables_without_primary_key with no possible remediation, and the new description text "Foreign table PKs are metadata-only (not enforced by the FDW) but still worth declaring" recommends something the server rejects with an error. Fix: drop 'f' from the no-PK check; if surfacing FDW tables is genuinely wanted, give them their own informational category instead of polluting an actionable lint with a finding that can never be cleared.

  2. src/integration/admin.integration.test.ts (new remote_users assertion) -- pins the unactionable behavior from item 1 (asserts the foreign table appears in tables_without_primary_key); remove it along with the fix, or repoint it at whatever informational category replaces it.

  3. src/integration/fixtures.ts setupFdwFixture() -- minor: any statement failure returns false silently, so when the FDW leg mysteriously skips on some host there's no breadcrumb for why. One console.error naming the failing statement (password redacted) before returning false would make that debuggable. Related nit: when DATABASE_URL has no password the user mapping is still created with password '' -- omitting the option entirely is friendlier to trust-auth setups.

🤖 Generated with Claude Code

PostgreSQL forbids PRIMARY KEY (and UNIQUE) constraints on foreign tables
entirely, so including relkind='f' in tables_without_primary_key produced
permanently unresolvable findings with no remediation path.

- admin.ts: drop 'f' from relkind IN ('r', 'p', 'f'); add comment
  explaining the exclusion; update tool description accordingly
- admin.integration.test.ts: flip assertion -- remote_users (foreign
  table) must NOT appear in tables_without_primary_key
- fixtures.ts: add console.error on FDW statement failure so skips are
  debuggable; omit password option entirely for trust-auth setups

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@HighviewOne

Copy link
Copy Markdown
Collaborator Author

Addressed all review points. Blocker resolved:

  1. Blocker fixed — dropped 'f' from relkind IN ('r', 'p', 'f'). PostgreSQL forbids PRIMARY KEY (and UNIQUE) constraints on foreign tables entirely, so they would permanently appear in tables_without_primary_key with no possible remediation. Added a comment in the SQL explaining the exclusion; description updated to match.
  2. Integration test — flipped the remote_users assertion: the foreign table must NOT appear in tables_without_primary_key (was asserting the opposite).
  3. setupFdwFixture() — added console.error naming the failing statement before returning false; omit password option entirely when DATABASE_URL has no password (friendlier to trust-auth setups).

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.

Foreign-table coverage across tools (pg_advisor, fixture)

2 participants