This commit is contained in:
93
scripts/foundation-migration.sql
Normal file
93
scripts/foundation-migration.sql
Normal file
@@ -0,0 +1,93 @@
|
||||
-- Apply after auth-catalog-migration.sql and before deploying the foundation release.
|
||||
-- Additive domain-schema changes; existing records and numeric IDs are retained.
|
||||
|
||||
ALTER TABLE blog_articles ADD COLUMN IF NOT EXISTS tags text[] NOT NULL DEFAULT '{}'::text[];
|
||||
|
||||
ALTER TABLE lists ADD COLUMN IF NOT EXISTS slug text;
|
||||
UPDATE lists SET slug = COALESCE(NULLIF(trim(both '-' from regexp_replace(lower(name), '[^a-z0-9]+', '-', 'g')), ''), 'list') || '-' || id
|
||||
WHERE slug IS NULL;
|
||||
ALTER TABLE lists ALTER COLUMN slug SET NOT NULL;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS lists_slug_unique ON lists (slug);
|
||||
ALTER TABLE lists ADD COLUMN IF NOT EXISTS is_progress boolean NOT NULL DEFAULT false;
|
||||
ALTER TABLE list_items ADD COLUMN IF NOT EXISTS picture_url text;
|
||||
ALTER TABLE list_items ADD COLUMN IF NOT EXISTS description text;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS list_item_completions (
|
||||
id serial PRIMARY KEY,
|
||||
item_id integer NOT NULL REFERENCES list_items(id) ON DELETE CASCADE,
|
||||
user_id text NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
CONSTRAINT list_item_completions_item_id_user_id_unique UNIQUE (item_id, user_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS list_item_completions_user_id_idx ON list_item_completions(user_id);
|
||||
|
||||
-- Join/setting records gain the same numeric identity as other site-owned rows.
|
||||
ALTER TABLE tasks_to_topics ADD COLUMN IF NOT EXISTS id serial;
|
||||
DO $$ BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_constraint WHERE conrelid = 'tasks_to_topics'::regclass AND conname = 'tasks_to_topics_pkey'
|
||||
AND pg_get_constraintdef(oid) NOT LIKE 'PRIMARY KEY (id)') THEN
|
||||
ALTER TABLE tasks_to_topics DROP CONSTRAINT tasks_to_topics_pkey;
|
||||
END IF;
|
||||
END $$;
|
||||
DO $$ BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conrelid = 'tasks_to_topics'::regclass AND contype = 'p') THEN
|
||||
ALTER TABLE tasks_to_topics ADD CONSTRAINT tasks_to_topics_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS tasks_to_topics_task_id_topic_id_unique ON tasks_to_topics(task_id, topic_id);
|
||||
|
||||
ALTER TABLE catch_em_all_settings ADD COLUMN IF NOT EXISTS id serial;
|
||||
DO $$ BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_constraint WHERE conrelid = 'catch_em_all_settings'::regclass AND conname = 'catch_em_all_settings_pkey'
|
||||
AND pg_get_constraintdef(oid) NOT LIKE 'PRIMARY KEY (id)') THEN
|
||||
ALTER TABLE catch_em_all_settings DROP CONSTRAINT catch_em_all_settings_pkey;
|
||||
END IF;
|
||||
END $$;
|
||||
DO $$ BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conrelid = 'catch_em_all_settings'::regclass AND contype = 'p') THEN
|
||||
ALTER TABLE catch_em_all_settings ADD CONSTRAINT catch_em_all_settings_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS catch_em_all_settings_user_id_unique ON catch_em_all_settings(user_id);
|
||||
|
||||
-- Every site-owned table records creation and latest update. Domain-specific
|
||||
-- event times (submitted_at, seen_at, uploaded_at) remain untouched.
|
||||
DO $$
|
||||
DECLARE table_name text;
|
||||
BEGIN
|
||||
FOREACH table_name IN ARRAY ARRAY[
|
||||
'blog_articles', 'lists', 'list_items', 'list_item_completions',
|
||||
'animals', 'sightings', 'photos', 'tasks', 'topics', 'tasks_to_topics',
|
||||
'pokemon', 'games', 'pokemon_game_entries', 'user_entries', 'user_games',
|
||||
'catch_em_all_settings'
|
||||
] LOOP
|
||||
EXECUTE format('ALTER TABLE %I ADD COLUMN IF NOT EXISTS created_at timestamptz NOT NULL DEFAULT now()', table_name);
|
||||
EXECUTE format('ALTER TABLE %I ADD COLUMN IF NOT EXISTS updated_at timestamptz NOT NULL DEFAULT now()', table_name);
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
-- Preserve the best available creation time for older Animaldex rows.
|
||||
UPDATE animals SET created_at = submitted_at WHERE created_at > submitted_at;
|
||||
UPDATE sightings SET created_at = submitted_at WHERE created_at > submitted_at;
|
||||
UPDATE photos SET created_at = uploaded_at WHERE created_at > uploaded_at;
|
||||
|
||||
CREATE OR REPLACE FUNCTION site_touch_updated_at() RETURNS trigger LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = now();
|
||||
RETURN NEW;
|
||||
END $$;
|
||||
|
||||
DO $$
|
||||
DECLARE table_name text;
|
||||
BEGIN
|
||||
FOREACH table_name IN ARRAY ARRAY[
|
||||
'blog_articles', 'lists', 'list_items', 'list_item_completions',
|
||||
'animals', 'sightings', 'photos', 'tasks', 'topics', 'tasks_to_topics',
|
||||
'pokemon', 'games', 'pokemon_game_entries', 'user_entries', 'user_games',
|
||||
'catch_em_all_settings'
|
||||
] LOOP
|
||||
EXECUTE format('DROP TRIGGER IF EXISTS site_touch_updated_at ON %I', table_name);
|
||||
EXECUTE format('CREATE TRIGGER site_touch_updated_at BEFORE UPDATE ON %I FOR EACH ROW EXECUTE FUNCTION site_touch_updated_at()', table_name);
|
||||
END LOOP;
|
||||
END $$;
|
||||
Reference in New Issue
Block a user