From 9b236f3ebd65d76a2c570f19931353da9c858d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Pozo?= Date: Tue, 10 Feb 2026 12:14:38 -0500 Subject: [PATCH] feat: add schema-constraints reference for safe migration patterns (#30) * feat: add schema-constraints reference for safe migration patterns Documents correct approaches for adding constraints in PostgreSQL migrations, since ADD CONSTRAINT IF NOT EXISTS is not supported and causes syntax errors. Co-Authored-By: Claude Sonnet 4.5 * Remove additional correct options --------- Co-authored-by: Claude Sonnet 4.5 --- .../AGENTS.md | 3 +- .../references/schema-constraints.md | 80 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 skills/supabase-postgres-best-practices/references/schema-constraints.md diff --git a/skills/supabase-postgres-best-practices/AGENTS.md b/skills/supabase-postgres-best-practices/AGENTS.md index cb45e6b..a744cc8 100644 --- a/skills/supabase-postgres-best-practices/AGENTS.md +++ b/skills/supabase-postgres-best-practices/AGENTS.md @@ -74,6 +74,7 @@ Reference files are named `{prefix}-{topic}.md` (e.g., `query-missing-indexes.md - `references/query-partial-indexes.md` **Schema Design** (`schema-`): +- `references/schema-constraints.md` - `references/schema-data-types.md` - `references/schema-foreign-key-indexes.md` - `references/schema-lowercase-identifiers.md` @@ -87,4 +88,4 @@ Reference files are named `{prefix}-{topic}.md` (e.g., `query-missing-indexes.md --- -*30 reference files across 8 categories* \ No newline at end of file +*31 reference files across 8 categories* \ No newline at end of file diff --git a/skills/supabase-postgres-best-practices/references/schema-constraints.md b/skills/supabase-postgres-best-practices/references/schema-constraints.md new file mode 100644 index 0000000..1d2ef8f --- /dev/null +++ b/skills/supabase-postgres-best-practices/references/schema-constraints.md @@ -0,0 +1,80 @@ +--- +title: Add Constraints Safely in Migrations +impact: HIGH +impactDescription: Prevents migration failures and enables idempotent schema changes +tags: constraints, migrations, schema, alter-table +--- + +## Add Constraints Safely in Migrations + +PostgreSQL does not support `ADD CONSTRAINT IF NOT EXISTS`. Migrations using this syntax will fail. + +**Incorrect (causes syntax error):** + +```sql +-- ERROR: syntax error at or near "not" (SQLSTATE 42601) +alter table public.profiles +add constraint if not exists profiles_birthchart_id_unique unique (birthchart_id); +``` + +**Correct (idempotent constraint creation):** + +```sql +-- Use DO block to check before adding +do $$ +begin + if not exists ( + select 1 from pg_constraint + where conname = 'profiles_birthchart_id_unique' + and conrelid = 'public.profiles'::regclass + ) then + alter table public.profiles + add constraint profiles_birthchart_id_unique unique (birthchart_id); + end if; +end $$; +``` + +For all constraint types: + +```sql +-- Check constraints +do $$ +begin + if not exists ( + select 1 from pg_constraint + where conname = 'check_age_positive' + ) then + alter table users add constraint check_age_positive check (age > 0); + end if; +end $$; + +-- Foreign keys +do $$ +begin + if not exists ( + select 1 from pg_constraint + where conname = 'profiles_birthchart_id_fkey' + ) then + alter table profiles + add constraint profiles_birthchart_id_fkey + foreign key (birthchart_id) references birthcharts(id); + end if; +end $$; +``` + +Check if constraint exists: + +```sql +-- Query to check constraint existence +select conname, contype, pg_get_constraintdef(oid) +from pg_constraint +where conrelid = 'public.profiles'::regclass; + +-- contype values: +-- 'p' = PRIMARY KEY +-- 'f' = FOREIGN KEY +-- 'u' = UNIQUE +-- 'c' = CHECK +``` + +Reference: [Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html)