Files
personal-website/scripts/animaldex-uuid-to-serial.sql
Stan Runge d0c7b6548b
Some checks failed
Test and deploy staging / staging (push) Has been cancelled
beeeeg update
2026-09-23 04:16:50 +00:00

85 lines
3.0 KiB
PL/PgSQL

-- One-off: convert animaldex ids from uuid to serial, keeping existing rows.
-- Postgres can't cast uuid -> integer, so db:push can't do this itself.
--
-- Run BEFORE re-running db:push, once per database:
-- psql "$DB_URL" -v ON_ERROR_STOP=1 -f scripts/animaldex-uuid-to-serial.sql
--
-- Safe to run on an empty database too. Everything is in one transaction, so a
-- failure leaves the database untouched.
BEGIN;
-- the failed push created this before erroring out
DROP SEQUENCE IF EXISTS animals_id_seq;
-- 1. new integer ids alongside the uuid ones
ALTER TABLE animals ADD COLUMN new_id serial;
ALTER TABLE sightings ADD COLUMN new_id serial;
ALTER TABLE photos ADD COLUMN new_id serial;
-- 2. translate the foreign keys through the uuid -> integer mapping
ALTER TABLE sightings ADD COLUMN new_animal_id integer;
UPDATE sightings s SET new_animal_id = a.new_id FROM animals a WHERE a.id = s.animal_id;
ALTER TABLE photos ADD COLUMN new_sighting_id integer;
UPDATE photos p SET new_sighting_id = s.new_id FROM sightings s WHERE s.id = p.sighting_id;
-- 3. drop the old foreign keys (names vary by how they were created)
DO $$
DECLARE r record;
BEGIN
FOR r IN
SELECT conrelid::regclass AS tbl, conname
FROM pg_constraint
WHERE contype = 'f' AND conrelid IN ('sightings'::regclass, 'photos'::regclass)
LOOP
EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %I', r.tbl, r.conname);
END LOOP;
END $$;
-- 4. swap the foreign key columns
ALTER TABLE photos DROP COLUMN sighting_id;
ALTER TABLE photos RENAME COLUMN new_sighting_id TO sighting_id;
ALTER TABLE photos ALTER COLUMN sighting_id SET NOT NULL;
ALTER TABLE sightings DROP COLUMN animal_id;
ALTER TABLE sightings RENAME COLUMN new_animal_id TO animal_id;
ALTER TABLE sightings ALTER COLUMN animal_id SET NOT NULL;
-- 5. swap the primary keys
DO $$
DECLARE r record;
BEGIN
FOR r IN
SELECT conrelid::regclass AS tbl, conname
FROM pg_constraint
WHERE contype = 'p'
AND conrelid IN ('animals'::regclass, 'sightings'::regclass, 'photos'::regclass)
LOOP
EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %I', r.tbl, r.conname);
END LOOP;
END $$;
ALTER TABLE animals DROP COLUMN id;
ALTER TABLE animals RENAME COLUMN new_id TO id;
ALTER TABLE animals ADD PRIMARY KEY (id);
ALTER SEQUENCE animals_new_id_seq RENAME TO animals_id_seq;
ALTER TABLE sightings DROP COLUMN id;
ALTER TABLE sightings RENAME COLUMN new_id TO id;
ALTER TABLE sightings ADD PRIMARY KEY (id);
ALTER SEQUENCE sightings_new_id_seq RENAME TO sightings_id_seq;
ALTER TABLE photos DROP COLUMN id;
ALTER TABLE photos RENAME COLUMN new_id TO id;
ALTER TABLE photos ADD PRIMARY KEY (id);
ALTER SEQUENCE photos_new_id_seq RENAME TO photos_id_seq;
-- 6. restore the foreign keys under the names drizzle expects
ALTER TABLE sightings ADD CONSTRAINT sightings_animal_id_animals_id_fkey
FOREIGN KEY (animal_id) REFERENCES animals(id) ON DELETE CASCADE;
ALTER TABLE photos ADD CONSTRAINT photos_sighting_id_sightings_id_fkey
FOREIGN KEY (sighting_id) REFERENCES sightings(id) ON DELETE CASCADE;
COMMIT;