Skip to content

Add --no-privileges flag to exclude GRANT/REVOKE from plan/apply #269

@kjanoudi

Description

@kjanoudi

Summary

Since v1.0.5 (#264), pg-schema-diff diffs table privileges and emits GRANT/REVOKE statements. There is currently no CLI flag or library option to opt out of this behavior. When the source and target databases have different role sets, the generated statements fail because the referenced roles do not exist on the target.

A --no-privileges (or --exclude-privileges) flag on plan and apply would let users skip privilege diffing entirely.

Motivation

A common deployment pattern is syncing schema from a primary database to a secondary (e.g., an Aurora primary to a reporting replica, or a production database to a temp/staging copy). These environments often have different PostgreSQL roles. After upgrading to v1.0.5, the generated plan includes statements like:

GRANT SELECT ON TABLE public.users TO reporting_reader;

This fails on the target with:

ERROR: role "reporting_reader" does not exist

The only workaround today is downgrading to v1.0.4 (which lacks privilege diffing entirely).

Reproduction

# Source database has role "reporting_reader" with SELECT on public.users
# Target database does NOT have that role

pg-schema-diff plan \
  --dsn "postgres://target-host/mydb" \
  --schema-source-dsn "postgres://source-host/mydb"

# Output includes:
#   GRANT SELECT ON TABLE "public"."users" TO "reporting_reader";
#
# Applying this plan fails:
#   ERROR: role "reporting_reader" does not exist

Precedent in the codebase

The codebase already acknowledges that privilege statements are problematic when roles differ between databases. Specifically:

  1. clearTablePrivileges() in pkg/diff/plan_generator.go strips privileges from both schemas during plan validation, with the comment: "Clear privileges from both schemas since privilege statements are skipped during validation (roles don't exist in temp DB)."

  2. Statement.SkipValidation is set to true on privilege statements so they are excluded during temp-DB validation, with the comment: "Skip statements that cannot be validated in temp DB (e.g., GRANT/REVOKE which reference roles that don't exist in the temp DB)"

The same problem that affects the internal temp-DB validation affects any real-world target database that has a different role set than the source. Exposing the existing skip logic as a user-facing option would be a natural extension.

Proposed solution

Add a --no-privileges flag (or similar) to the plan and apply CLI commands that excludes table privilege diffing from the output. At the library level, this could be an option on PlanGeneratorOpt or similar.

For example:

pg-schema-diff plan \
  --dsn "postgres://target-host/mydb" \
  --schema-source-dsn "postgres://source-host/mydb" \
  --no-privileges

# Plan no longer includes GRANT/REVOKE statements

Relationship to #197

Issue #197 proposes a generic --exclude grammar (--exclude 'type=[schema|table] name="regex"'). A --no-privileges flag could be implemented as a standalone option now and later subsumed by the more general exclusion grammar if/when that lands. The two are complementary rather than conflicting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions