V106: Split phoenix_kit_projects.name uniqueness across templates and
real projects.
V101 created a single global unique index
(phoenix_kit_projects_name_index) on lower(name) over the
phoenix_kit_projects table. Templates and real projects share that
table — distinguished only by the is_template boolean — so they
also shared one name namespace, which made
Projects.create_project_from_template/2 collide whenever a real
project should reuse the source template's name (the common,
expected case).
This migration replaces that single index with two partial unique
indexes — one per is_template value — so a template "Onboarding"
and a real project "Onboarding" can coexist freely.
Indexes
phoenix_kit_projects_name_template_indexUNIQUE (lower(name)) WHERE is_template = truephoenix_kit_projects_name_project_indexUNIQUE (lower(name)) WHERE is_template = false
Both are idempotent (CREATE INDEX IF NOT EXISTS / DROP INDEX IF EXISTS).
Schema-side change only. The Ecto changeset's unique_constraint(:name, name: :phoenix_kit_projects_name_index, ...) reference is updated in
the same release of phoenix_kit_projects to point at whichever
partial index applies (the is_template value at validate time
selects the correct constraint name).
Summary
Functions
Reverts to V101's single global unique index.
Lossy rollback: if the post-V106 state has both a template and a
real project with the same name, recreating the single
phoenix_kit_projects_name_index will fail with a uniqueness
violation. Resolve duplicates before rolling back in production.