Skip to content

fix: batch per-row inspector lookups into the schema queries (#644, #654) - #656

Merged
tianzhou merged 1 commit into
mainfrom
fix/batch-inspector-lookups-644
Oct 15, 2026
Merged

tianzhou merged 1 commit into
mainfrom
fix/batch-inspector-lookups-644

Conversation

@tianzhou

Copy link
Copy Markdown
Contributor

Summary

dump and plan were slow over high-latency connections because the inspector did one round trip per privilege row (role name), per constraint column (position in the key), per owned sequence (identity flag) and per view (column list). Each value now comes back from the batched query it belongs to, so introspection is a fixed ~30 queries regardless of schema size.

before after
200-table reproduction from #644 (dump, one inspection) 4,028 queries 30 queries
employee fixture with grants to two roles 164 queries 30 queries

Counts from the --debug query tree (#655). plan inspects twice, so the user-facing saving doubles. Dump output is byte-identical before and after on both databases.

Query changes (ir/queries/queries.sql)

  • GetPrivilegesForSchema, GetColumnPrivilegesForSchema: the aclexplode rows move into a CTE and LEFT JOIN pg_roles on the grantee; grantee_name is PUBLIC for oid 0 and empty when the role no longer exists, which keeps today's skip behavior.
  • GetConstraintsForSchema: constraint_position = array_position(conkey, attnum) for PK / UNIQUE / FK, 0 otherwise. Same value information_schema.key_column_usage.ordinal_position gave.
  • GetSequencesForSchema: owned_by_identity from the owning column's attidentity.
  • GetViewsForSchema: column_names aggregated from pg_attribute in attnum order.
  • GetIndexesForSchema: COALESCE on parent_index / parent_index_schema. The checked-in generated code had drifted from what sqlc v1.30.0 produces for these two columns; with the coalesce, regeneration yields the nullable type the inspector already uses.

Correctness fix

The old position lookup keyed on (schema, constraint name, column) without the table. Foreign key names are only unique per table, so two tables with a same-named FK on the same columns could get each other's column order:

CREATE TABLE p (a int, b int, PRIMARY KEY (a, b), UNIQUE (b, a));
CREATE TABLE c1 (a int, b int, CONSTRAINT fk_p FOREIGN KEY (a, b) REFERENCES p (a, b));
CREATE TABLE c2 (a int, b int, CONSTRAINT fk_p FOREIGN KEY (b, a) REFERENCES p (b, a));

c2 was dumped as FOREIGN KEY (a, b) REFERENCES p (a, b), pointing at the primary key instead of the (b, a) unique constraint. New fixture testdata/dump/issue_644_fk_column_order fails before this change and passes after.

Fixes #644
Fixes #654 (closed as duplicate)

Test plan

  • go test ./cmd/dump (full dump fixture suite, including the new TestDumpCommand_Issue644FKColumnOrder; red before the fix)
  • go test ./internal/diff -run TestDiffFromFiles
  • go test ./ir/...
  • PGSCHEMA_TEST_FILTER=<category>/ go test ./cmd -run TestPlanAndApply for privilege/, create_sequence/, create_view/, create_materialized_view/, create_table/
  • go vet ./ir/...
  • Manual: old vs new binary dump of employee and the 200-table reproduction are identical; query counts as in the table above

🤖 Generated with Claude Code

)

The inspector issued one query per privilege row to resolve the grantee
name, one per constraint column for its position in the key, one per owned
sequence for the identity flag, and one per view for its column list. Over
a high-latency connection that made dump and plan take minutes: the 200-table
reproduction in #644 needed 4,028 queries per inspection, and plan inspects
twice.

Each value now comes back from the batched query it belongs to:
- GetPrivilegesForSchema / GetColumnPrivilegesForSchema LEFT JOIN pg_roles
  on the aclexplode grantee and return grantee_name ('PUBLIC' for oid 0,
  empty when the role is gone, which keeps the skip behavior).
- GetConstraintsForSchema returns array_position(conkey, attnum) as
  constraint_position for PK/UNIQUE/FK constraints.
- GetSequencesForSchema returns owned_by_identity from the owning column's
  attidentity.
- GetViewsForSchema returns column_names aggregated from pg_attribute.

The reproduction drops from 4,028 to 30 queries; the employee fixture from
164 to 30. Dump output is unchanged on both.

This also fixes a correctness bug: the old position lookup keyed on
(schema, constraint name, column) without the table, so two tables with a
same-named foreign key on the same columns could get each other's column
order. New dump fixture issue_644_fk_column_order covers it.

GetIndexesForSchema coalesces parent_index / parent_index_schema so that
regenerating with sqlc v1.30.0 yields the nullable type the inspector
already uses; the generated code had drifted from the generator.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 15, 2026 16:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The queries and inspector consumers are consistent, the ordering fix has regression coverage, and no blocking issues remain.

0 open findings

What changed in this PR

Reduces database round trips during dump and plan by batching inspector metadata lookups, addressing slow remote introspection.

Changes:

  • Fetches privilege names, constraint positions, sequence identity flags, and view columns in existing queries.
  • Updates generated bindings and removes per-row inspector queries.
  • Fixes same-named foreign key column ordering with regression coverage.
File Description
testdata/​dump/​issue_644_fk_column_order/​raw.sql Reproduces conflicting foreign key column orders.
testdata/​dump/​issue_644_fk_column_order/​pgschema.sql Records expected pgschema output.
testdata/​dump/​issue_644_fk_column_order/​pgdump.sql Provides reference PostgreSQL output.
testdata/​dump/​issue_644_fk_column_order/​manifest.json Documents the regression fixture.
ir/​queries/​queries.sql.go Updates generated query bindings.
ir/​queries/​queries.sql Batches metadata lookups.
ir/​inspector.go Consumes batched metadata.
cmd/​dump/​dump_integration_test.go Registers the ordering regression test.
Files not reviewed (1)
  • ir/queries/queries.sql.go: Generated file

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[High impact] The PR appears safe to merge; no actionable issues were found.

Summary

This PR moves repeated inspector lookups into the existing schema queries.

  • Privilege rows now include the grantee name in the schema query.
  • Foreign keys keep their own column order, even when names repeat.
  • Identity-backed sequences stay managed through their columns.
  • View rows now include their ordered column names.
  • Missing parent-index names now come back as empty strings.

No actionable issues found. Tests were not run during this review.

Reviews (1) · Last reviewed commit: "fix: batch per-row inspector lookups int..." · Reviewed by Greptile

@tianzhou
tianzhou merged commit 7ca8d07 into main Oct 15, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants