Skip to content

feat: warn about and skip statements that have no effect on the plan (#602, #603) - #621

Merged
tianzhou merged 3 commits into
mainfrom
feat/warn-no-effect-statements
Sep 20, 2026
Merged

tianzhou merged 3 commits into
mainfrom
feat/warn-no-effect-statements

Conversation

@tianzhou

Copy link
Copy Markdown
Contributor

Summary

Two statement kinds set state that pgschema's inspection never reads, so a schema file containing them produced a successful empty plan with no diagnostic:

plan (and apply, which goes through GeneratePlan) now prints a warning per statement on stderr and drops it from the desired-state SQL:

Warning: statement has no effect: ALTER TABLE item OWNER TO app_owner
  pgschema does not manage object ownership; change the owner outside pgschema, see https://www.pgschema.com/syntax/unsupported#object-ownership

Why drop, not just warn

  • A global ALTER DEFAULT PRIVILEGES runs for real on the plan database. On an external plan database nothing cleans it up, so it would persist past the run.
  • A role named only in OWNER TO is not stubbed, so the statement fails in the plan database with role "x" does not exist.

Stripping happens right after include processing, before role validation and before the plan database.

How

  • One detector, postgres.StripNoEffectStatements, returns the findings plus the SQL without them. Adding another kind is one more case in classifyNoEffect.
  • Best-effort textual scan, no parser. It reuses the existing scanner (walkSQLCode*, parseQuotedIdent, …); walkSQLCodeSpans is a small refactor that exposes byte offsets. String literals, comments and dollar-quoted bodies are skipped, so statements inside DO blocks or function bodies are not seen.
  • Removal blanks the statement in place (length and newlines preserved), so PostgreSQL error positions still map to the user's file.
  • OWNER TO combined with other actions in one ALTER TABLE is warned about but kept.
  • RENAME [COLUMN|CONSTRAINT|ATTRIBUTE] owner TO ... and objects named owner are not misread. ALTER SCHEMA/DATABASE ... OWNER TO is left alone.

Docs

Test plan

  • go test ./internal/postgres/ — new TestStripNoEffectStatements table test
  • go test ./cmd/plan/ — new TestPlan_WarnsAboutNoEffectStatements (embedded Postgres; confirmed it fails without the fix)
  • go test ./internal/diff/
  • PGSCHEMA_TEST_FILTER="default_privilege/" go test ./cmd -run TestPlanAndApply
  • Full go test ./... left to CI

Closes #602
Closes #603

🤖 Generated with Claude Code

tianzhou and others added 2 commits September 20, 2026 03:25
ALTER DEFAULT PRIVILEGES without IN SCHEMA is database-level state that
the schema-scoped inspection never sees, so it yields an empty plan.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…602, #603)

Object OWNER TO and ALTER DEFAULT PRIVILEGES without IN SCHEMA set state
that inspection never reads, so they produced a successful empty plan,
indistinguishable from convergence. plan now reports each one on stderr
and drops it before role validation and the plan database, where a global
default ACL would otherwise persist on an external plan database and an
unstubbed owner role would fail.

Detection is a best-effort textual scan built on the existing
comment/literal/dollar-quote skipping scanner. Removal blanks the
statement in place so PostgreSQL error positions still map to the file.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 20, 2026 10:35
@greptile-apps

greptile-apps Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 3/5

The PR is not safe to merge until combined ownership actions are prevented from executing in the plan database and index ownership statements receive the intended warning and stripping behavior.

Findings

  1. P1 Combined ownership still executes ▶
  2. P1 Index ownership bypasses detection ▶

Summary

This PR adds preprocessing that warns about and blanks desired-state statements whose ownership or global-default-privilege state is not inspected, before role validation and plan-database execution.

  • Adds textual detection and position-preserving removal of standalone no-effect statements.
  • Integrates warnings into file-based plan generation and apply.
  • Documents unsupported ownership and database-wide default privileges.
  • The ownership handling remains incomplete for indexes and does not safely handle comma-separated ownership actions.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Expanded desired SQL] --> B[Detect no-effect statements]
  B -->|Standalone owner or global defaults| C[Warn and blank statement]
  B -->|Other SQL| D[Retain statement]
  C --> E[Validate referenced roles]
  D --> E
  E --> F[Apply to plan database]
  F --> G[Inspect desired state]
  G --> H[Generate plan]
Loading

Reviews (1) · Last reviewed commit: "feat: warn about and skip statements tha..."

Comment thread internal/postgres/no_effect.go Outdated
Comment thread internal/postgres/no_effect.go Outdated

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.

Copilot review overview

🟡 Changes recommended

The scanner can alter valid E-string contents and misclassify or miss valid ownership statements.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 2 Medium severity · 1 Low severity

Open (4)
What changed in this PR

Adds warnings and filtering for unsupported ownership changes and global default privileges.

Changes:

  • Detects and removes no-effect SQL while preserving source offsets.
  • Integrates warnings into plan/apply generation.
  • Adds tests and unsupported-syntax documentation.
File Description
internal/​postgres/​no_effect.go Implements detection and stripping.
internal/​postgres/​no_effect_test.go Adds detector tests.
internal/​postgres/​fk_refs.go Exposes code-span offsets.
cmd/​plan/​plan.go Applies stripping during planning.
cmd/​plan/​no_effect.go Formats warnings.
cmd/​plan/​no_effect_integration_test.go Tests planning behavior.
docs/​syntax/​unsupported.mdx Documents unsupported statements.
docs/​syntax/​alter_default_privileges.mdx Documents IN SCHEMA requirement.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/postgres/no_effect.go
Comment thread internal/postgres/no_effect.go Outdated
Comment thread internal/postgres/no_effect.go Outdated
Comment thread cmd/plan/no_effect.go Outdated
- Drop only the OWNER TO action when it shares an ALTER TABLE with other
  actions, so it no longer reaches the plan database; warn about the
  action rather than the whole statement.
- Report ALTER INDEX ... OWNER TO.
- Require the second keyword for two-word kinds, so ALTER FOREIGN DATA
  WRAPPER ... OWNER TO is left alone.
- Treat backslash-escaped quotes in E'...' literals as part of the
  literal, so text inside one is never blanked.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

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.

Copilot review overview

🟡 Changes recommended

The scanner can corrupt valid ordinary strings when standard_conforming_strings is disabled.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: None

Resolved since last review (4)

@tianzhou
tianzhou merged commit 670c531 into main Sep 20, 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

2 participants