fix(migrate): pre-check pg_constraint instead of catching duplicate_object

ADD CONSTRAINT UNIQUE creates a supporting index under the hood; when
the index name already exists from initial-schema's inline UNIQUE,
Postgres raises SQLSTATE 42P07 (duplicate_table), not 42710
(duplicate_object) — so the EXCEPTION block didn't catch it and CI's
Migrations apply gate failed with `relation
"user_cards_user_id_card_id_is_foil_key" already exists`.

Swap to a pg_constraint pre-check: bulletproof against both SQLSTATEs
without overreaching to WHEN OTHERS.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Randall Stillwell 2026-06-14 08:08:47 -05:00
parent 75ba7c751d
commit a000c59ec4

View file

@ -64,17 +64,25 @@ export const up = (pgm) => {
// Re-assert the canonical 3-col UNIQUE from `initial-schema.js`. // Re-assert the canonical 3-col UNIQUE from `initial-schema.js`.
// No-op against initial-schema-applied envs (the constraint already // No-op against initial-schema-applied envs (the constraint already
// exists under its auto-generated name); constructive against any // exists under its auto-generated name); constructive against any
// env where the constraint was somehow dropped. Wrapped in // env where the constraint was somehow dropped. Postgres does not
// `DO $$ ... EXCEPTION WHEN duplicate_object` because Postgres // support `ADD CONSTRAINT ... IF NOT EXISTS`, so we pre-check
// does not support `ADD CONSTRAINT ... IF NOT EXISTS`. // `pg_constraint`. (An earlier draft used `EXCEPTION WHEN
// duplicate_object`, but `ADD CONSTRAINT UNIQUE` raises
// SQLSTATE 42P07 `duplicate_table` from the auto-created
// supporting index, not 42710 `duplicate_object` — the pre-check
// sidesteps both.)
pgm.sql(` pgm.sql(`
DO $$ DO $$
BEGIN BEGIN
ALTER TABLE user_cards IF NOT EXISTS (
ADD CONSTRAINT user_cards_user_id_card_id_is_foil_key SELECT 1 FROM pg_constraint
UNIQUE (user_id, card_id, is_foil); WHERE conname = 'user_cards_user_id_card_id_is_foil_key'
EXCEPTION AND conrelid = 'user_cards'::regclass
WHEN duplicate_object THEN NULL; ) THEN
ALTER TABLE user_cards
ADD CONSTRAINT user_cards_user_id_card_id_is_foil_key
UNIQUE (user_id, card_id, is_foil);
END IF;
END $$; END $$;
`); `);
}; };