Commit ddf9a79d authored by jan.koester's avatar jan.koester
Browse files

test

parent 3f47409b
Loading
Loading
Loading
Loading
+479 −0
Original line number Diff line number Diff line
-- =============================================================================
-- Blogi Migration: INTEGER id -> UUID
-- Database: PostgreSQL (requires 13+ for gen_random_uuid())
-- =============================================================================
--
-- Run: psql -d <dbname> -f migrate_int_to_uuid.sql
--
-- This script converts all integer primary keys and foreign keys to UUID.
-- It preserves existing data and relationships.
-- Back up your database before running!
--
-- =============================================================================

BEGIN;

-- ---------------------------------------------------------------------------
-- 0. Prerequisites (gen_random_uuid() is built-in since PostgreSQL 13)
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- 1. Add UUID columns to all tables (parent tables first)
-- ---------------------------------------------------------------------------

-- == Level 0: Independent tables (no FK to other migrated tables) ==

ALTER TABLE users              ADD COLUMN id_new UUID;
ALTER TABLE session            ADD COLUMN id_new UUID;
ALTER TABLE options            ADD COLUMN id_new UUID;
ALTER TABLE theme_colors       ADD COLUMN id_new UUID;
ALTER TABLE cookie_rules       ADD COLUMN id_new UUID;
ALTER TABLE tags               ADD COLUMN id_new UUID;
ALTER TABLE gameserver_protocols ADD COLUMN id_new UUID;
ALTER TABLE navbar             ADD COLUMN id_new UUID;
ALTER TABLE youtube_channels   ADD COLUMN id_new UUID;
ALTER TABLE templates          ADD COLUMN id_new UUID;
ALTER TABLE static_content     ADD COLUMN id_new UUID;
ALTER TABLE survey_results     ADD COLUMN id_new UUID;
ALTER TABLE editor_templates   ADD COLUMN id_new UUID;

-- contact_pending.token is already the PK; if it's INTEGER, migrate it too
DO $$
BEGIN
    IF EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_name = 'contact_pending' AND column_name = 'token'
        AND data_type IN ('integer','bigint','smallint')
    ) THEN
        EXECUTE 'ALTER TABLE contact_pending ADD COLUMN token_new UUID';
    END IF;
END$$;

-- == Level 1: Tables with FK to level 0 ==

ALTER TABLE session_data       ADD COLUMN sessionid_new UUID;
ALTER TABLE content            ADD COLUMN id_new UUID;
ALTER TABLE content            ADD COLUMN author_new UUID;
ALTER TABLE gameserver         ADD COLUMN id_new UUID;
ALTER TABLE gameserver         ADD COLUMN protocol_new UUID;
ALTER TABLE navbar_items       ADD COLUMN id_new UUID;
ALTER TABLE navbar_items       ADD COLUMN navbar_id_new UUID;
ALTER TABLE youtube_videos     ADD COLUMN id_new UUID;
ALTER TABLE youtube_videos     ADD COLUMN youtube_channels_pkey_new UUID;
ALTER TABLE editor_template_revisions ADD COLUMN id_new UUID;
ALTER TABLE editor_template_revisions ADD COLUMN template_id_new UUID;

-- == Level 2: Tables with FK to level 1 ==

ALTER TABLE tags_content       ADD COLUMN tag_id_new UUID;
ALTER TABLE tags_content       ADD COLUMN content_id_new UUID;
ALTER TABLE comments           ADD COLUMN id_new UUID;
ALTER TABLE comments           ADD COLUMN content_id_new UUID;
ALTER TABLE comments           ADD COLUMN user_id_new UUID;

-- ---------------------------------------------------------------------------
-- 2. Generate UUIDs for primary keys
-- ---------------------------------------------------------------------------

UPDATE users              SET id_new = gen_random_uuid();
UPDATE session            SET id_new = gen_random_uuid();
UPDATE options            SET id_new = gen_random_uuid();
UPDATE theme_colors       SET id_new = gen_random_uuid();
UPDATE cookie_rules       SET id_new = gen_random_uuid();
UPDATE tags               SET id_new = gen_random_uuid();
UPDATE gameserver_protocols SET id_new = gen_random_uuid();
UPDATE navbar             SET id_new = gen_random_uuid();
UPDATE youtube_channels   SET id_new = gen_random_uuid();
UPDATE templates          SET id_new = gen_random_uuid();
UPDATE static_content     SET id_new = gen_random_uuid();
UPDATE survey_results     SET id_new = gen_random_uuid();
UPDATE editor_templates   SET id_new = gen_random_uuid();

-- contact_pending (only if token was integer)
DO $$
BEGIN
    IF EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_name = 'contact_pending' AND column_name = 'token_new'
    ) THEN
        EXECUTE 'UPDATE contact_pending SET token_new = gen_random_uuid()';
    END IF;
END$$;

UPDATE content                    SET id_new = gen_random_uuid();
UPDATE gameserver                 SET id_new = gen_random_uuid();
UPDATE navbar_items               SET id_new = gen_random_uuid();
UPDATE youtube_videos             SET id_new = gen_random_uuid();
UPDATE editor_template_revisions  SET id_new = gen_random_uuid();
UPDATE tags_content               SET tag_id_new = NULL;  -- FK only, set below
UPDATE tags_content               SET content_id_new = NULL;
UPDATE comments                   SET id_new = gen_random_uuid();

-- ---------------------------------------------------------------------------
-- 3. Propagate UUIDs through foreign key references
-- ---------------------------------------------------------------------------

-- session_data.sessionid -> session.id
UPDATE session_data sd
   SET sessionid_new = s.id_new
  FROM session s
 WHERE sd.sessionid::text = s.id::text;

-- content.author -> users.id
UPDATE content c
   SET author_new = u.id_new
  FROM users u
 WHERE c.author::text = u.id::text;

-- gameserver.protocol -> gameserver_protocols.id
UPDATE gameserver g
   SET protocol_new = gp.id_new
  FROM gameserver_protocols gp
 WHERE g.protocol::text = gp.id::text;

-- navbar_items.navbar_id -> navbar.id
UPDATE navbar_items ni
   SET navbar_id_new = n.id_new
  FROM navbar n
 WHERE ni.navbar_id::text = n.id::text;

-- youtube_videos.youtube_channels_pkey -> youtube_channels.id
UPDATE youtube_videos yv
   SET youtube_channels_pkey_new = yc.id_new
  FROM youtube_channels yc
 WHERE yv.youtube_channels_pkey::text = yc.id::text;

-- editor_template_revisions.template_id -> editor_templates.id
UPDATE editor_template_revisions etr
   SET template_id_new = et.id_new
  FROM editor_templates et
 WHERE etr.template_id::text = et.id::text;

-- tags_content.tag_id -> tags.id
UPDATE tags_content tc
   SET tag_id_new = t.id_new
  FROM tags t
 WHERE tc.tag_id::text = t.id::text;

-- tags_content.content_id -> content.id
UPDATE tags_content tc
   SET content_id_new = c.id_new
  FROM content c
 WHERE tc.content_id::text = c.id::text;

-- comments.content_id -> content.id
UPDATE comments cm
   SET content_id_new = c.id_new
  FROM content c
 WHERE cm.content_id::text = c.id::text;

-- comments.user_id -> users.id
UPDATE comments cm
   SET user_id_new = u.id_new
  FROM users u
 WHERE cm.user_id::text = u.id::text;

-- ---------------------------------------------------------------------------
-- 4. Drop ALL foreign key constraints referencing migrated tables
-- ---------------------------------------------------------------------------

DO $$
DECLARE
    r RECORD;
BEGIN
    -- Drop all FK constraints that reference any of the tables being migrated
    FOR r IN (
        SELECT con.conname, con.conrelid::regclass AS tbl
          FROM pg_constraint con
          JOIN pg_constraint ref ON con.confrelid = ref.conrelid
         WHERE con.contype = 'f'
           AND con.confrelid::regclass::text IN (
               'users', 'session', 'options', 'theme_colors', 'cookie_rules',
               'tags', 'gameserver_protocols', 'navbar', 'youtube_channels',
               'templates', 'static_content', 'survey_results',
               'editor_templates', 'content', 'gameserver', 'navbar_items',
               'youtube_videos', 'editor_template_revisions', 'comments'
           )
           AND ref.contype = 'p'
    ) LOOP
        EXECUTE format('ALTER TABLE %s DROP CONSTRAINT IF EXISTS %I', r.tbl, r.conname);
    END LOOP;

    -- Also drop FK constraints ON the migrated tables themselves
    FOR r IN (
        SELECT conname, conrelid::regclass AS tbl
          FROM pg_constraint
         WHERE contype = 'f'
           AND conrelid::regclass::text IN (
               'session_data', 'content', 'gameserver',
               'navbar_items', 'youtube_videos',
               'editor_template_revisions', 'tags_content', 'comments',
               'media_albums'
           )
    ) LOOP
        EXECUTE format('ALTER TABLE %s DROP CONSTRAINT IF EXISTS %I', r.tbl, r.conname);
    END LOOP;
END$$;

-- ---------------------------------------------------------------------------
-- 5. Drop old primary key constraints
-- ---------------------------------------------------------------------------

DO $$
DECLARE
    r RECORD;
BEGIN
    FOR r IN (
        SELECT conname, conrelid::regclass AS tbl
          FROM pg_constraint
         WHERE contype = 'p'
           AND conrelid::regclass::text IN (
               'users', 'session', 'options', 'theme_colors', 'cookie_rules',
               'tags', 'gameserver_protocols', 'navbar', 'youtube_channels',
               'templates', 'static_content', 'survey_results',
               'editor_templates', 'content', 'gameserver', 'navbar_items',
               'youtube_videos', 'editor_template_revisions', 'comments'
           )
    ) LOOP
        EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %I', r.tbl, r.conname);
    END LOOP;
END$$;

-- ---------------------------------------------------------------------------
-- 6. Drop old columns, rename new columns
-- ---------------------------------------------------------------------------

-- == Level 0 tables ==

ALTER TABLE users              DROP COLUMN id CASCADE;
ALTER TABLE users              RENAME COLUMN id_new TO id;

ALTER TABLE session            DROP COLUMN id CASCADE;
ALTER TABLE session            RENAME COLUMN id_new TO id;

ALTER TABLE options            DROP COLUMN id CASCADE;
ALTER TABLE options            RENAME COLUMN id_new TO id;

ALTER TABLE theme_colors       DROP COLUMN id CASCADE;
ALTER TABLE theme_colors       RENAME COLUMN id_new TO id;

ALTER TABLE cookie_rules       DROP COLUMN id CASCADE;
ALTER TABLE cookie_rules       RENAME COLUMN id_new TO id;

ALTER TABLE tags               DROP COLUMN id CASCADE;
ALTER TABLE tags               RENAME COLUMN id_new TO id;

ALTER TABLE gameserver_protocols DROP COLUMN id CASCADE;
ALTER TABLE gameserver_protocols RENAME COLUMN id_new TO id;

ALTER TABLE navbar             DROP COLUMN id CASCADE;
ALTER TABLE navbar             RENAME COLUMN id_new TO id;

ALTER TABLE youtube_channels   DROP COLUMN id CASCADE;
ALTER TABLE youtube_channels   RENAME COLUMN id_new TO id;

ALTER TABLE templates          DROP COLUMN id CASCADE;
ALTER TABLE templates          RENAME COLUMN id_new TO id;

ALTER TABLE static_content     DROP COLUMN id CASCADE;
ALTER TABLE static_content     RENAME COLUMN id_new TO id;

ALTER TABLE survey_results     DROP COLUMN id CASCADE;
ALTER TABLE survey_results     RENAME COLUMN id_new TO id;

ALTER TABLE editor_templates   DROP COLUMN id CASCADE;
ALTER TABLE editor_templates   RENAME COLUMN id_new TO id;

-- contact_pending (conditional)
DO $$
BEGIN
    IF EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_name = 'contact_pending' AND column_name = 'token_new'
    ) THEN
        EXECUTE 'ALTER TABLE contact_pending DROP COLUMN token CASCADE';
        EXECUTE 'ALTER TABLE contact_pending RENAME COLUMN token_new TO token';
    END IF;
END$$;

-- == Level 1 tables ==

ALTER TABLE session_data       DROP COLUMN sessionid CASCADE;
ALTER TABLE session_data       RENAME COLUMN sessionid_new TO sessionid;

ALTER TABLE content            DROP COLUMN id CASCADE;
ALTER TABLE content            RENAME COLUMN id_new TO id;
ALTER TABLE content            DROP COLUMN author CASCADE;
ALTER TABLE content            RENAME COLUMN author_new TO author;

ALTER TABLE gameserver         DROP COLUMN id CASCADE;
ALTER TABLE gameserver         RENAME COLUMN id_new TO id;
ALTER TABLE gameserver         DROP COLUMN protocol CASCADE;
ALTER TABLE gameserver         RENAME COLUMN protocol_new TO protocol;

ALTER TABLE navbar_items       DROP COLUMN id CASCADE;
ALTER TABLE navbar_items       RENAME COLUMN id_new TO id;
ALTER TABLE navbar_items       DROP COLUMN navbar_id CASCADE;
ALTER TABLE navbar_items       RENAME COLUMN navbar_id_new TO navbar_id;

ALTER TABLE youtube_videos     DROP COLUMN id CASCADE;
ALTER TABLE youtube_videos     RENAME COLUMN id_new TO id;
ALTER TABLE youtube_videos     DROP COLUMN youtube_channels_pkey CASCADE;
ALTER TABLE youtube_videos     RENAME COLUMN youtube_channels_pkey_new TO youtube_channels_pkey;

ALTER TABLE editor_template_revisions DROP COLUMN id CASCADE;
ALTER TABLE editor_template_revisions RENAME COLUMN id_new TO id;
ALTER TABLE editor_template_revisions DROP COLUMN template_id CASCADE;
ALTER TABLE editor_template_revisions RENAME COLUMN template_id_new TO template_id;

-- == Level 2 tables ==

ALTER TABLE tags_content       DROP COLUMN tag_id CASCADE;
ALTER TABLE tags_content       RENAME COLUMN tag_id_new TO tag_id;
ALTER TABLE tags_content       DROP COLUMN content_id CASCADE;
ALTER TABLE tags_content       RENAME COLUMN content_id_new TO content_id;

ALTER TABLE comments           DROP COLUMN id CASCADE;
ALTER TABLE comments           RENAME COLUMN id_new TO id;
ALTER TABLE comments           DROP COLUMN content_id CASCADE;
ALTER TABLE comments           RENAME COLUMN content_id_new TO content_id;
ALTER TABLE comments           DROP COLUMN user_id CASCADE;
ALTER TABLE comments           RENAME COLUMN user_id_new TO user_id;

-- ---------------------------------------------------------------------------
-- 7. Re-add primary key constraints
-- ---------------------------------------------------------------------------

ALTER TABLE users              ADD PRIMARY KEY (id);
ALTER TABLE session            ADD PRIMARY KEY (id);
ALTER TABLE options            ADD PRIMARY KEY (id);
ALTER TABLE theme_colors       ADD PRIMARY KEY (id);
ALTER TABLE cookie_rules       ADD PRIMARY KEY (id);
ALTER TABLE tags               ADD PRIMARY KEY (id);
ALTER TABLE gameserver_protocols ADD PRIMARY KEY (id);
ALTER TABLE navbar             ADD PRIMARY KEY (id);
ALTER TABLE youtube_channels   ADD PRIMARY KEY (id);
ALTER TABLE templates          ADD PRIMARY KEY (id);
ALTER TABLE static_content     ADD PRIMARY KEY (id);
ALTER TABLE survey_results     ADD PRIMARY KEY (id);
ALTER TABLE editor_templates   ADD PRIMARY KEY (id);
ALTER TABLE content            ADD PRIMARY KEY (id);
ALTER TABLE gameserver         ADD PRIMARY KEY (id);
ALTER TABLE navbar_items       ADD PRIMARY KEY (id);
ALTER TABLE youtube_videos     ADD PRIMARY KEY (id);
ALTER TABLE editor_template_revisions ADD PRIMARY KEY (id);
ALTER TABLE comments           ADD PRIMARY KEY (id);

-- contact_pending: only add PK if we migrated it (token_new existed)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint
        WHERE conrelid = 'contact_pending'::regclass AND contype = 'p'
    ) THEN
        EXECUTE 'ALTER TABLE contact_pending ADD PRIMARY KEY (token)';
    END IF;
END$$;

-- ---------------------------------------------------------------------------
-- 8. Re-add foreign key constraints
-- ---------------------------------------------------------------------------

ALTER TABLE session_data
    ADD CONSTRAINT session_data_sessionid_fkey
    FOREIGN KEY (sessionid) REFERENCES session (id);

ALTER TABLE content
    ADD CONSTRAINT content_author_fkey
    FOREIGN KEY (author) REFERENCES users (id);

ALTER TABLE gameserver
    ADD CONSTRAINT gameserver_protocol_fkey
    FOREIGN KEY (protocol) REFERENCES gameserver_protocols (id);

ALTER TABLE navbar_items
    ADD CONSTRAINT navbar_items_navbar_id_fkey
    FOREIGN KEY (navbar_id) REFERENCES navbar (id);

ALTER TABLE youtube_videos
    ADD CONSTRAINT youtube_videos_youtube_channels_pkey_fkey
    FOREIGN KEY (youtube_channels_pkey) REFERENCES youtube_channels (id);

ALTER TABLE editor_template_revisions
    ADD CONSTRAINT editor_template_revisions_template_id_fkey
    FOREIGN KEY (template_id) REFERENCES editor_templates (id);

ALTER TABLE tags_content
    ADD CONSTRAINT tags_content_tag_id_fkey
    FOREIGN KEY (tag_id) REFERENCES tags (id);

ALTER TABLE tags_content
    ADD CONSTRAINT tags_content_content_id_fkey
    FOREIGN KEY (content_id) REFERENCES content (id);

ALTER TABLE comments
    ADD CONSTRAINT comments_content_id_fkey
    FOREIGN KEY (content_id) REFERENCES content (id);

ALTER TABLE comments
    ADD CONSTRAINT comments_user_id_fkey
    FOREIGN KEY (user_id) REFERENCES users (id);

-- ---------------------------------------------------------------------------
-- 9. Set NOT NULL constraints where required
-- ---------------------------------------------------------------------------

ALTER TABLE users              ALTER COLUMN id SET NOT NULL;
ALTER TABLE session            ALTER COLUMN id SET NOT NULL;
ALTER TABLE options            ALTER COLUMN id SET NOT NULL;
ALTER TABLE theme_colors       ALTER COLUMN id SET NOT NULL;
ALTER TABLE cookie_rules       ALTER COLUMN id SET NOT NULL;
ALTER TABLE tags               ALTER COLUMN id SET NOT NULL;
ALTER TABLE gameserver_protocols ALTER COLUMN id SET NOT NULL;
ALTER TABLE navbar             ALTER COLUMN id SET NOT NULL;
ALTER TABLE youtube_channels   ALTER COLUMN id SET NOT NULL;
ALTER TABLE templates          ALTER COLUMN id SET NOT NULL;
ALTER TABLE static_content     ALTER COLUMN id SET NOT NULL;
ALTER TABLE survey_results     ALTER COLUMN id SET NOT NULL;
ALTER TABLE editor_templates   ALTER COLUMN id SET NOT NULL;
ALTER TABLE content            ALTER COLUMN id SET NOT NULL;
ALTER TABLE gameserver         ALTER COLUMN id SET NOT NULL;
ALTER TABLE navbar_items       ALTER COLUMN id SET NOT NULL;
ALTER TABLE youtube_videos     ALTER COLUMN id SET NOT NULL;
ALTER TABLE editor_template_revisions ALTER COLUMN id SET NOT NULL;
ALTER TABLE comments           ALTER COLUMN id SET NOT NULL;

ALTER TABLE tags_content       ALTER COLUMN tag_id SET NOT NULL;
ALTER TABLE tags_content       ALTER COLUMN content_id SET NOT NULL;
ALTER TABLE comments           ALTER COLUMN content_id SET NOT NULL;
ALTER TABLE editor_template_revisions ALTER COLUMN template_id SET NOT NULL;

-- ---------------------------------------------------------------------------
-- 10. Set defaults for new inserts
-- ---------------------------------------------------------------------------

ALTER TABLE users              ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE session            ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE options            ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE theme_colors       ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE cookie_rules       ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE tags               ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE gameserver_protocols ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE navbar             ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE youtube_channels   ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE templates          ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE static_content     ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE survey_results     ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE editor_templates   ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE content            ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE gameserver         ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE navbar_items       ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE youtube_videos     ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE editor_template_revisions ALTER COLUMN id SET DEFAULT gen_random_uuid();
ALTER TABLE comments           ALTER COLUMN id SET DEFAULT gen_random_uuid();

-- ---------------------------------------------------------------------------
-- Done
-- ---------------------------------------------------------------------------

COMMIT;