Skip to content

fix(pg-delta): recreate policies for column rewrite dependencies#275

Open
xmh1011 wants to merge 3 commits into
supabase:mainfrom
xmh1011:fix/pg-delta-policy-column-rewrite-cascade
Open

fix(pg-delta): recreate policies for column rewrite dependencies#275
xmh1011 wants to merge 3 commits into
supabase:mainfrom
xmh1011:fix/pg-delta-policy-column-rewrite-cascade

Conversation

@xmh1011

@xmh1011 xmh1011 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Refs #263

This is the third incremental fix for issue #263, scoped to Case 1: ALTER TABLE ... ALTER COLUMN ... TYPE fails when an existing RLS policy still depends on the rewritten column.

What changed

For this case, pg-delta was producing the right table rewrite but the wrong policy handling:

  1. diffRlsPolicies saw the policy expression text change after the column type changed from text to an enum, so it emitted ALTER POLICY ... USING and ALTER POLICY ... WITH CHECK.
  2. PostgreSQL does not allow ALTER COLUMN TYPE while the old policy definition still depends on that column, so the policy must be fully dropped before the rewrite and recreated after it.
  3. The table rewrite is an in-place mutation. After fix(pg-delta): order view drops before column type rewrites #273, these changes expose the affected stable ids through BaseChange.invalidates rather than adding concrete subtype checks to generic expansion/sorting code.

This PR now builds on #273's invalidates primitive:

  • collect invalidated stable ids from change.invalidates;
  • use mainCatalog.depends to find surviving rlsPolicy:* objects whose policy expressions depend on those ids;
  • add DropRlsPolicy / CreateRlsPolicy for those policies;
  • remove same-policy ALTER POLICY changes that are superseded by the replacement.

The fix stays within existing pg_catalog/pg_depend metadata and does not parse policy SQL or couple expandReplaceDependencies to AlterTableAlterColumnType.

RED evidence

  • Initial focused unit regression failed because expandReplaceDependencies did not add DropRlsPolicy for a policy whose pg_depend row referenced the rewritten column.
  • Initial focused PG17 integration regression failed because generated SQL had ALTER TABLE ... ALTER COLUMN role TYPE ... followed by ALTER POLICY ... USING / ALTER POLICY ... WITH CHECK, with no DROP POLICY / CREATE POLICY around the column rewrite.
  • Manual apply reproduced PostgreSQL 0A000: cannot alter type of a column used in a policy definition.
  • After rebasing onto fix(pg-delta): order view drops before column type rewrites #273, I added a design regression using a generic invalidating change. RED before the refactor: expand-replace-dependencies.test.ts failed with Expected: true / Received: false for DropRlsPolicy because the helper still checked AlterTableAlterColumnType directly.

Local validation

  • Unit-only focused invalidates regression: 1 pass / 0 fail.
  • Full expand-replace-dependencies.test.ts: 9 pass / 0 fail.
  • PG17 focused integration for policy depending on a column type rewrite is dropped and recreated: 1 pass / 0 fail.
  • Full PG17 policy-dependencies.test.ts: 9 pass / 0 fail (one connection timeout retried by the test runner; final result was green).
  • ./node_modules/.bin/bun run format-and-lint:fix: passed.
  • ./node_modules/.bin/bun run check-types: passed.
  • ./node_modules/.bin/bun run knip --fix: passed; knip only reported existing configuration hints.

Local integration validation used PGDELTA_SKIP_DUMMY_SECLABEL_BUILD=1 to avoid rebuilding the local dummy security-label image; CI should keep security-label coverage enabled.

@changeset-bot

changeset-bot Bot commented Jun 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6dbc536

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@supabase/pg-delta Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@xmh1011

xmh1011 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up after comparing this PR with the review discussion on #273.

This PR still addresses a separate issue #263 case: an RLS policy whose expression depends on a column being rewritten needs to be promoted from ALTER POLICY changes to a DROP POLICY + CREATE POLICY replacement. Otherwise PostgreSQL can still block ALTER TABLE ... ALTER COLUMN ... TYPE because the policy expression is bound to the old column/type definition.

One design note before this is finalized: #273 introduced the BaseChange.invalidates primitive so in-place rewrites can declare the stable ids they invalidate without adding concrete instanceof checks to generic planning/sorting code. Once #273 lands in main, I think this PR should be rebased and adjusted to consume change.invalidates instead of importing/checking AlterTableAlterColumnType inside expand-replace-dependencies.ts.

Planned cleanup after #273 merges:

  • rebase this branch onto the updated main;
  • rename the column-specific helper to something like collectInvalidatedRlsPolicyReplacements;
  • collect invalidated stable ids from change.invalidates and use pg_depend to find dependent rlsPolicy:* objects;
  • keep the current focused regression and integration coverage, with the unit test wording updated to reflect the invalidates primitive rather than a concrete column-rewrite subtype.

I am intentionally not stacking #273's infrastructure onto this PR before #273 merges, to keep this diff reviewable and avoid duplicating the same base changes across two open PRs.

@xmh1011 xmh1011 force-pushed the fix/pg-delta-policy-column-rewrite-cascade branch from 0476a23 to e5b75ee Compare June 10, 2026 09:10
@xmh1011

xmh1011 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

@avallete Follow-up after #273 merged:

I rebased this branch onto the current main (9f01826) and updated the implementation to consume the BaseChange.invalidates primitive from #273 instead of checking AlterTableAlterColumnType inside expandReplaceDependencies.

Pushed e5b75ee:

  • expandReplaceDependencies now collects invalidated stable ids from change.invalidates;
  • it uses mainCatalog.depends to find surviving dependent rlsPolicy:* objects and promotes those policies to DROP POLICY + CREATE POLICY;
  • same-policy ALTER POLICY changes are still removed when superseded by that replacement;
  • the unit regression now uses a generic invalidating change so it verifies the design boundary, not a concrete table-change subtype.

RED after the rebase, before the refactor: the generic invalidates regression failed with Expected: true / Received: false for DropRlsPolicy because the helper still checked AlterTableAlterColumnType directly.

Validation:

  • focused invalidates unit regression: 1 pass / 0 fail;
  • full expand-replace-dependencies.test.ts: 9 pass / 0 fail;
  • PG17 focused policy integration: 1 pass / 0 fail;
  • full PG17 policy-dependencies.test.ts: 9 pass / 0 fail (one connection timeout retried by the runner; final result green);
  • format-and-lint:fix, check-types, and knip --fix passed; knip only reported existing configuration hints.

@xmh1011 xmh1011 force-pushed the fix/pg-delta-policy-column-rewrite-cascade branch from e5b75ee to 98c0d8c Compare June 10, 2026 09:14
xmh1011 added 3 commits June 10, 2026 17:19
Signed-off-by: xiaominghao <xiaominghao@baidu.com>
RED: PG17 focused integration generated ALTER TABLE ... ALTER COLUMN role TYPE before two ALTER POLICY statements, with no DROP POLICY / CREATE POLICY. The focused unit regression also showed expandReplaceDependencies did not add DropRlsPolicy for a policy whose pg_depend row referenced the rewritten column.

Signed-off-by: xiaominghao <xiaominghao@baidu.com>
RED: after rebasing onto supabase#273, the design regression using a generic invalidating change failed in expand-replace-dependencies.test.ts with Expected: true / Received: false for DropRlsPolicy because the helper still checked AlterTableAlterColumnType directly.

GREEN: expand-replace-dependencies.test.ts now passes, PG17 policy-dependencies.test.ts focused and full-file runs pass, and format-and-lint/check-types/knip pass.
Signed-off-by: xiaominghao <xiaominghao@baidu.com>
@xmh1011 xmh1011 force-pushed the fix/pg-delta-policy-column-rewrite-cascade branch from 98c0d8c to 6dbc536 Compare June 10, 2026 09:20
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.

1 participant