PhoenixKit.Migrations.UUIDFKColumns (phoenix_kit v2.6.0)

Copy Markdown View Source

Adds UUID FK columns alongside integer FKs across PhoenixKit tables.

Called from V56 migration. This helper module keeps V56 manageable by extracting the UUID FK column creation logic (~80 columns across ~40 tables).

How It Works

For each FK column, three operations:

  1. ALTER TABLE ... ADD COLUMN IF NOT EXISTS {uuid_fk} UUID
  2. Backfill via JOIN: UPDATE t SET {uuid_fk} = s.uuid FROM source s WHERE s.id = t.{int_fk}
  3. CREATE INDEX IF NOT EXISTS ... ON table({uuid_fk})

Large tables use batched backfills (PL/pgSQL DO block, 10k rows/batch) to avoid long-running transactions.

After columns are created and backfilled, add_constraints/1 adds:

  • NOT NULL constraints where the integer FK is NOT NULL
  • FK constraints where the integer FK has an explicit DB-level FK constraint

Safety

  • All operations wrapped in table_exists? + column_exists? checks
  • FK constraint creation uses pg_constraint existence check (idempotent)
  • NOT NULL uses ALTER COLUMN SET NOT NULL (idempotent in PostgreSQL)
  • Idempotent — safe to run multiple times

Summary

Functions

Adds NOT NULL constraints and FK constraints to UUID FK columns.

Drops FK constraints and NOT NULL from UUID FK columns.

The FK constraint name add_fk_constraint/7/drop_fk_constraint/4 use for {table, uuid_fk}fk_<table minus the phoenix_kit_ prefix>_<uuid_fk>. Exposed so V163's repair names constraints identically to what this module itself would have created, instead of re-deriving the same string format a second time.

The {table, uuid_fk, ref_table, ref_col, on_delete} tuples add_constraints/1 builds FK constraints from — exposed for the same reason as not_null_uuid_fks/0: PhoenixKit.Migrations.Postgres.V163 drives its missing-FK repair off this exact list rather than a second copy of it. Not otherwise meant as a public contract.

The {table, uuid_fk_column} pairs add_constraints/1 sets NOT NULL on — exposed so PhoenixKit.Migrations.Postgres.V163 (a later repair for installs that ran the V56/V57 flush-order bug — see that migration's moduledoc) can drive the same list without duplicating it. Not otherwise meant as a public contract; if a future addition to @not_null_uuid_fks changes shape, this accessor and V163's consumption of it move together.

Functions

add_constraints(opts)

Adds NOT NULL constraints and FK constraints to UUID FK columns.

Must be called AFTER up/1 so that columns exist and are backfilled.

Order: NOT NULL first (data already backfilled), then ensure unique indexes on all FK-target tables, then FK constraints.

down(opts)

drop_constraints(opts)

Drops FK constraints and NOT NULL from UUID FK columns.

Must be called BEFORE down/1 so constraints are removed before columns are dropped.

Order: FK constraints first (unblocks column removal), then NOT NULL.

fk_constraint_name(table, uuid_fk)

@spec fk_constraint_name(atom() | String.t(), String.t()) :: String.t()

The FK constraint name add_fk_constraint/7/drop_fk_constraint/4 use for {table, uuid_fk}fk_<table minus the phoenix_kit_ prefix>_<uuid_fk>. Exposed so V163's repair names constraints identically to what this module itself would have created, instead of re-deriving the same string format a second time.

fk_constraints()

@spec fk_constraints() :: [{atom(), String.t(), String.t(), String.t(), String.t()}]

The {table, uuid_fk, ref_table, ref_col, on_delete} tuples add_constraints/1 builds FK constraints from — exposed for the same reason as not_null_uuid_fks/0: PhoenixKit.Migrations.Postgres.V163 drives its missing-FK repair off this exact list rather than a second copy of it. Not otherwise meant as a public contract.

not_null_uuid_fks()

@spec not_null_uuid_fks() :: [{atom(), String.t()}]

The {table, uuid_fk_column} pairs add_constraints/1 sets NOT NULL on — exposed so PhoenixKit.Migrations.Postgres.V163 (a later repair for installs that ran the V56/V57 flush-order bug — see that migration's moduledoc) can drive the same list without duplicating it. Not otherwise meant as a public contract; if a future addition to @not_null_uuid_fks changes shape, this accessor and V163's consumption of it move together.

up(opts)