-- Step 1: Create the backup per-season table CREATE TABLE IF NOT EXISTS "season_participant_golf_skills" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "participant_id" uuid NOT NULL, "sports_season_id" uuid NOT NULL, "sg_total" numeric(5, 2), "datagolf_rank" integer, "masters_odds" integer, "us_open_odds" integer, "open_championship_odds" integer, "pga_championship_odds" integer, "updated_at" timestamp DEFAULT now() NOT NULL ); --> statement-breakpoint -- Step 2: Copy existing per-season data to backup table INSERT INTO "season_participant_golf_skills" ("id", "participant_id", "sports_season_id", "sg_total", "datagolf_rank", "masters_odds", "us_open_odds", "open_championship_odds", "pga_championship_odds", "updated_at") SELECT "id", "participant_id", "sports_season_id", "sg_total", "datagolf_rank", "masters_odds", "us_open_odds", "open_championship_odds", "pga_championship_odds", "updated_at" FROM "participant_golf_skills"; --> statement-breakpoint -- Step 3: Add FK constraints on backup table DO $$ BEGIN ALTER TABLE "season_participant_golf_skills" ADD CONSTRAINT "season_participant_golf_skills_participant_id_season_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."season_participants"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "season_participant_golf_skills" ADD CONSTRAINT "season_participant_golf_skills_sports_season_id_sports_seasons_id_fk" FOREIGN KEY ("sports_season_id") REFERENCES "public"."sports_seasons"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "season_participant_golf_skills_unique" ON "season_participant_golf_skills" USING btree ("participant_id","sports_season_id"); --> statement-breakpoint -- Step 4 + 5: Clear and repurpose participant_golf_skills as canonical table. -- Wrapped in a transaction so that a failure between TRUNCATE and re-INSERT -- doesn't leave the table empty. The backup table from steps 1-3 remains as a -- safety net regardless. BEGIN; --> statement-breakpoint ALTER TABLE "participant_golf_skills" DROP CONSTRAINT IF EXISTS "participant_golf_skills_participant_id_season_participants_id_fk"; --> statement-breakpoint ALTER TABLE "participant_golf_skills" DROP CONSTRAINT IF EXISTS "participant_golf_skills_sports_season_id_sports_seasons_id_fk"; --> statement-breakpoint DROP INDEX IF EXISTS "participant_golf_skills_unique"; --> statement-breakpoint ALTER TABLE "participant_golf_skills" DROP COLUMN IF EXISTS "sports_season_id"; --> statement-breakpoint TRUNCATE "participant_golf_skills"; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "participant_golf_skills" ADD CONSTRAINT "participant_golf_skills_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "participant_golf_skills_participant_unique" ON "participant_golf_skills" USING btree ("participant_id"); --> statement-breakpoint -- Migrate data from per-season to canonical, taking latest values per canonical participant INSERT INTO "participant_golf_skills" ("id", "participant_id", "sg_total", "datagolf_rank", "masters_odds", "us_open_odds", "open_championship_odds", "pga_championship_odds", "updated_at") SELECT DISTINCT ON (sp.participant_id) gen_random_uuid(), sp.participant_id, backup.sg_total, backup.datagolf_rank, backup.masters_odds, backup.us_open_odds, backup.open_championship_odds, backup.pga_championship_odds, backup.updated_at FROM "season_participant_golf_skills" backup JOIN "season_participants" sp ON backup.participant_id = sp.id WHERE sp.participant_id IS NOT NULL ORDER BY sp.participant_id, backup.updated_at DESC; --> statement-breakpoint COMMIT;