Skip to content

migrate/supabase: translate composite UNIQUE(a,b) instead of silently dropping it (conformance M1) - #309

Open
Sorcecoder wants to merge 2 commits into
mainfrom
fix/m1-migrate-composite-unique
Open

Sorcecoder wants to merge 2 commits into
mainfrom
fix/m1-migrate-composite-unique

Conversation

@Sorcecoder

Copy link
Copy Markdown
Contributor

Docs↔codegen conformance sweep — code-wrong bucket. The migrator's headline promise (19-migrate-supabase.md:7) is 'never silently drop — untranslatable becomes a gap.' But a multi-column UNIQUE(a,b) fell through the single-column guard in apply_table_constraint (pgmodel.rs) and entities.rs hardcoded unique: vec![] — so the constraint vanished and the migrated app allowed duplicate rows the source forbade, silently, staying green (no test probed it).

Fix: capture multi-column table UNIQUE into PgTable.composite_uniques and translate to the entity's composite unique (reusing the #115 Vec<Vec<String>> representation — column mapping is identity). If a column didn't survive translation, raise a Blocking gap instead of dropping — the 'never silently drop' promise holds either way. Covers both inline UNIQUE(a,b) and ALTER TABLE ADD CONSTRAINT forms.

Test: composite_unique_survives_translation_and_an_unrepresentable_one_gaps. No version bump.

Follow-up (M1b, not in this PR): a multi-column CREATE UNIQUE INDEX ON t(a,b) is a separate parse node (CreateIndex) and still drops the same way — same class, tracked separately.

…tly dropping it

apply_table_constraint only handled single-column UNIQUE; a table-level
UNIQUE(a, b) fell through and vanished, so the migrated app permitted
duplicate rows the source forbade — violating the migrator's never-silently-drop
promise (docs/ai/19-migrate-supabase.md:7).

Capture multi-column groups into PgTable.composite_uniques and emit them as
the entity's composite `unique` (issue #115), mapping source columns to the
entity's field / belongs_to fk-column names (the shape JC0559 accepts). If a
group's column dropped out (e.g. an unmappable-type column), raise a blocking
gap for that constraint instead of dropping it — the promise holds either way.

Covers both the inline CREATE TABLE constraint and the pg_dump
ALTER TABLE ... ADD CONSTRAINT ... UNIQUE(a,b) form (both route through
apply_table_constraint).
@Sorcecoder

Copy link
Copy Markdown
Contributor Author

Held for 0.8.0 — not a 0.7.x patch. The semver gate correctly flags this: constructible_struct_adds_field on PgTable (pgmodel.rs). The migrate IR (PgDatabase/PgTable/PgColumn) is public, all-pub-field, Default-derived and not #[non_exhaustive], so any new field is a breaking change for a 0.x crate, and no existing field can carry composite-unique groups non-breakingly. Per the release policy (bug fixes stay 0.7.x; breaking/feature work goes to the next minor), this lands in the 0.8.0 breaking window — where the migrate IR should also be marked #[non_exhaustive] (the 0.7.0 convention already used by design.rs/mod.rs/realtimegen.rs) so every future IR addition is non-breaking. The fix itself is reviewed and correct; only its version placement changes.

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