Skip to content

fix: exclude extension-owned objects and privileges from inspection (#595) - #604

Merged
tianzhou merged 2 commits into
pgplex:mainfrom
christophostertag:codex/fix-extension-members-595
Sep 14, 2026
Merged

tianzhou merged 2 commits into
pgplex:mainfrom
christophostertag:codex/fix-extension-members-595

Conversation

@christophostertag

@christophostertag christophostertag commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

A dump with pg_stat_statements currently includes its views but omits their required extension functions. With preinstalled PostGIS and an external planner, an application-only schema also produces extension-member drops and ACL changes; saved-plan apply fails with PostgreSQL 2BP01. This patch leaves extension-owned definitions and privileges outside application schema management, while retaining application objects that reference extensions.

Fixes #595. Reproduced on current main 319b88c83d62b2c9a62eff7a09ec6563954bcf4b, not only the v1.13.0 release.

Change

  • Apply consistent membership filtering to the shared inspector queries, both global and schema-scoped. Match full pg_depend catalog/subobject identity and deptype = 'e'; ordinary dependencies and AUTO_EXTENSION (x) remain managed.
  • Exclude attached member metadata, owned SERIAL/identity sequences, and all three object-ACL paths (explicit grants, revoked PUBLIC defaults, column grants), including relation row-type ACLs.
  • Correct existing routine/aggregate filters that matched an OID without its catalog class. Schemas remain inspectable even if extension-owned, so application objects in them stay managed.
  • Preserve application partition DEFAULT/NOT NULL overrides when the parent is an extension member. Read parent columns only as transient comparison metadata, outside managed definitions and fingerprints; normalize parent and child defaults consistently after planner schema remapping.
  • Regenerate queries with sqlc v1.30.0. Regenerating unchanged main first was byte-identical to all checked-in generated files.

Compatibility decision: member privileges are unmanaged even when deliberately changed after installation. Unlike pg_dump, this does not export pg_init_privs ACL deltas. Ordinary application GRANT/REVOKE remains supported. This restriction and the external planner caveat are documented in the extension and privilege guides. Extension-member GRANT/REVOKE belongs outside desired application SQL. Extension installation/upgrades and roles are not added to the managed scope; external databases must still have matching preinstalled extensions.

Validation

  • New catalog regressions use real ALTER EXTENSION ... ADD membership with bundled hstore: tables, views/materialized views, sequences, enum/composite/domain types, routines/aggregates and attached metadata/ACLs; application controls, quoted names, same-name objects across schemas, extension-owned schema, x dependency, and transactional OID-collision tests. They fail on baseline and pass with the fix.
  • New bundled pg_stat_statements dump/reload regression preserves an application view using the extension while omitting member definitions and column ACLs. It needs no shared preload change because it inspects definitions rather than querying statistics.
  • All new runtime test sets executed locally on PostgreSQL 14.18, 15.13, 16.9, 17.5 and 18.3, with no skips. Query matrix used -count=1 because its existing TestMain reads the version environment before Go test logging.
  • New partition dump/replay regression covers same-schema and quoted cross-schema extension parents. Real INSERTs verify child default/NOT NULL, inherited default and generated-column behavior. A normalization regression prevents redundant overrides for inherited function defaults. Native external-plan/saved-apply creation of a new application partition also passes, with extension/parent metadata unchanged and empty repeats. Both review findings have RED→GREEN evidence.
  • Existing embedded-extension planner, external-planner, privilege-ignore and all 14 privilege/ fixtures passed. The adjacent partition-override diff and plan/apply fixture also passed. Relevant go vet and build passed. Independent Astra and Opus reviews completed; final verification reconciled executable evidence separately.
  • Separate local real-extension acceptance: PostgreSQL 18.4, PostGIS 3.6.3, pg_stat_statements 1.12, vector 0.8.6, Go 1.26.4, darwin/arm64 CLI against a disposable Linux arm64 server. Native dump → external plan → unedited saved-plan apply → repeat plan succeeds; native dumps reload into preinstalled-extension databases. All 1,159 member identities, owners and object/column ACLs stay unchanged on target and planner. Application rows, geometry/geography/vector(3), GiST/HNSW and intended application ACL changes are verified. SQL-standard RETURN dependencies on PostGIS functions retain correct creation ordering and results. Third-party extension acceptance is local evidence; the committed bundled tests run in normal upstream CI.

Commands for the automated regressions:

for version in 14 15 16 17 18; do
  PGSCHEMA_POSTGRES_VERSION=$version go test -count=1 -v ./ir/queries ./cmd/dump \
    -run 'TestExtensionMembers|TestExtensionMembershipCatalogIdentity|TestGetSequencesForSchemaOwnershipComesFromPgDepend|TestDumpExtension'
done
PGSCHEMA_POSTGRES_VERSION=18 go test -v ./cmd/plan \
  -run 'TestEmbeddedPlanDB_InstallsTargetExtensions|TestExternalDatabase_'
PGSCHEMA_POSTGRES_VERSION=18 go test -v ./cmd -run 'TestIgnorePrivileges'
PGSCHEMA_POSTGRES_VERSION=18 PGSCHEMA_TEST_FILTER='privilege/' \
  go test -count=1 -v ./internal/diff -run TestDiffFromFiles

Standalone reproduction

Use an otherwise unused local PostgreSQL server with PostGIS and pg_stat_statements available, the latter preloaded for querying statistics. Set PGHOST, PGPORT, PGUSER and authentication for that disposable server. Use fresh database names and a directory with no ignore/config file. pgschema below is either the baseline or patched binary.

createdb issue595_target
createdb issue595_plan
for database in issue595_target issue595_plan; do
  psql -X -v ON_ERROR_STOP=1 -d "$database" \
    -c 'CREATE EXTENSION postgis; CREATE EXTENSION pg_stat_statements;'
done
cat > desired.sql <<'SQL'
CREATE FUNCTION public.f() RETURNS integer LANGUAGE sql AS $$ SELECT 3 $$;
SQL
pgschema dump --host "$PGHOST" --port "$PGPORT" --user "$PGUSER" \
  --db issue595_target --schema public > before.sql
pgschema plan --host "$PGHOST" --port "$PGPORT" --user "$PGUSER" \
  --db issue595_target --schema public --file desired.sql \
  --plan-host "$PGHOST" --plan-port "$PGPORT" --plan-user "$PGUSER" \
  --plan-db issue595_plan --output-json plan.json --output-sql plan.sql
pgschema apply --host "$PGHOST" --port "$PGPORT" --user "$PGUSER" \
  --db issue595_target --schema public --plan plan.json --auto-approve

Before: member views/tables/types leak into the dump/plan, with unwanted REVOKEs; apply rejects a member drop with 2BP01. After: extension-only dump contains no managed objects; plan creates only f(); apply succeeds and repeating plan is empty. PostgreSQL rejected the baseline member drop; no successful member deletion is claimed.

Scope limits: this patch does not repair existing quoted-schema view search_path errors, qualification-only churn for application views over extension relations, or non-public vector schema/opclass rendering. The separate public-schema spatial/vector/function-view workflow and quoted application schema without views passed; these unrelated cases are not counted as passing.

Application partitions of extension-owned parents remain managed and their DEFAULT/NOT NULL overrides are covered by native replay and saved-plan acceptance. Cross-schema partition-stub behavior in external planning is unchanged; quoted cross-schema coverage here is direct native dump/replay. The direct trigger-membership predicate is defensive; regressions cover triggers on member tables, not a separately extension-owned trigger on an application table.

@greptile-apps

greptile-apps Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR excludes extension-owned objects and their privileges from managed inspection while retaining application objects that depend on extensions. The follow-up repair preserves application partition behavior when its parent is an unmanaged extension member.

  • Matches extension membership using complete PostgreSQL catalog identity and deptype = 'e'.
  • Filters member definitions, attached metadata, owned sequences, and object/column privilege paths.
  • Retains unmanaged parent columns as transient, non-serialized metadata for partition override comparison.
  • Normalizes parent and child defaults consistently after temporary planner-schema remapping.
  • Adds catalog, dump/replay, and inherited function-default regressions.

Confidence Score: 5/5

The PR appears safe to merge; the previously reported partition override loss is fully addressed and no new actionable defect remains.

Transient parent columns are populated before normalization, excluded from serialization and fingerprints, normalized with the same schema context as child columns, and used only when the managed parent is unavailable. Temporary-schema restoration now covers both sides of the default comparison, preventing inherited function defaults from producing redundant overrides while preserving child-specific DEFAULT and NOT NULL clauses. The previous partition finding was fully fixed, and its thread is resolved.

Important Files Changed

Filename Overview
ir/queries/queries.sql Adds catalog-identity extension filtering and a scoped query for transient partition-parent column metadata.
ir/inspector.go Attaches unmanaged parent-column properties only to managed partitions that require override comparison.
internal/diff/table.go Falls back to transient parent metadata when rendering partition DEFAULT and NOT NULL overrides.
ir/normalize.go Normalizes transient parent defaults in the same child-schema context as managed columns.
cmd/plan/plan.go Remaps transient parent defaults alongside child defaults when restoring the target schema name.
cmd/dump/extension_integration_test.go Adds runtime dump/replay coverage for extension filtering and partition column behavior.
cmd/plan/plan_test.go Verifies inherited function defaults do not become redundant child overrides.
ir/queries/queries.sql.go Regenerates typed query methods and row contracts from the updated SQL definitions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    DB[(PostgreSQL catalogs)] --> Inspect[Schema inspection]
    Inspect --> Filter{Extension member?}
    Filter -->|Yes| Omit[Exclude managed definition and ACLs]
    Filter -->|No| IR[Managed application IR]
    Parent[Unmanaged partition parent columns] --> Metadata[Transient comparison metadata]
    Metadata --> Normalize[Normalize with child schema context]
    IR --> Normalize
    Normalize --> Diff[DEFAULT / NOT NULL override comparison]
    Diff --> DDL[Application partition DDL]
Loading

Reviews (2): Last reviewed commit: "fix: preserve partition overrides with u..." | Re-trigger Greptile

Comment thread ir/queries/queries.sql
@christophostertag

Copy link
Copy Markdown
Contributor Author

@greptileai Please re-review the repair in e207b9d, especially preservation of application partition DEFAULT/NOT NULL overrides and inherited function defaults. The original finding is addressed with transient parent metadata, runtime regressions and native saved-plan acceptance; details are in the reply on the original thread.

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.

🔵 Needs a closer look

The changes span catalog inspection, planning, diffing, generated queries, and PostgreSQL extension behavior, requiring final human review.

Pull request overview

Updates PostgreSQL inspection and planning to exclude extension-owned objects and privileges while preserving application objects and partition overrides that depend on extensions.

Changes:

  • Adds extension membership filtering across catalog and ACL queries.
  • Preserves and normalizes application partition metadata.
  • Adds regression coverage and documents planner and privilege limitations.
File summaries
File Description
ir/queries/queries.sql.go Regenerated inspection queries.
ir/queries/queries.sql Adds extension filters and partition metadata queries.
ir/queries/extension_members_test.go Tests extension membership and ACL filtering.
ir/normalize.go Normalizes inherited defaults.
ir/ir.go Adds transient partition metadata.
ir/inspector.go Loads unmanaged parent metadata.
internal/diff/table.go Preserves partition overrides in generated DDL.
docs/syntax/grant_revoke.mdx Documents unmanaged extension privileges.
docs/cli/plan-db.mdx Documents extension planner requirements.
cmd/plan/plan.go Remaps planner schema references.
cmd/plan/plan_test.go Tests planner normalization.
cmd/dump/extension_integration_test.go Covers extension dump and replay behavior.
Review details

Files not reviewed (1)

  • ir/queries/queries.sql.go: Generated file
  • Files reviewed: 11/12 changed files
  • Comments generated: 0
  • Review effort level: Lite (auto)

Note

Copilot is running an experiment and ran this review at Lite.


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

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.

🔵 Needs a closer look

Broad PostgreSQL catalog, privilege, planning, and partition behavior changes require final human review.

Review details

Files not reviewed (1)

  • ir/queries/queries.sql.go: Generated file
  • Files reviewed: 11/12 changed files
  • Comments generated: 0 new
  • Review effort level: Lite (auto)

Note

Copilot is running an experiment and ran this review at Lite.

@tianzhou tianzhou 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.

LGTM. Thanks for the contribution.

@tianzhou
tianzhou merged commit 11678c5 into pgplex:main Sep 14, 2026
2 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

Development

Successfully merging this pull request may close these issues.

dump takes some extension objects

3 participants