chore(db): clean up redundant schema migrations and legacy import logic
Remove obsolete ALTER TABLE statements and data migration blocks that are already reflected in base table definitions. Simplify data tool import normalization by removing legacy artifact mapping and unused entity types.
This commit is contained in:
@@ -26,8 +26,6 @@ CREATE TABLE IF NOT EXISTS entity_translations (
|
||||
'skills',
|
||||
'environments',
|
||||
'favorite-things',
|
||||
'item-categories',
|
||||
'item-usages',
|
||||
'acquisition-methods',
|
||||
'items',
|
||||
'ancient-artifacts',
|
||||
@@ -51,41 +49,6 @@ CREATE TABLE IF NOT EXISTS entity_translations (
|
||||
CREATE INDEX IF NOT EXISTS entity_translations_lookup_idx
|
||||
ON entity_translations (entity_type, entity_id, field_name, locale);
|
||||
|
||||
ALTER TABLE entity_translations
|
||||
DROP CONSTRAINT IF EXISTS entity_translations_entity_type_check;
|
||||
|
||||
ALTER TABLE entity_translations
|
||||
ADD CONSTRAINT entity_translations_entity_type_check CHECK (
|
||||
entity_type IN (
|
||||
'pokemon',
|
||||
'pokemon-types',
|
||||
'skills',
|
||||
'environments',
|
||||
'favorite-things',
|
||||
'item-categories',
|
||||
'item-usages',
|
||||
'acquisition-methods',
|
||||
'items',
|
||||
'ancient-artifacts',
|
||||
'maps',
|
||||
'habitats',
|
||||
'daily-checklist-items',
|
||||
'life-tags',
|
||||
'game-versions',
|
||||
'dish-categories',
|
||||
'dish-flavors',
|
||||
'dishes'
|
||||
)
|
||||
);
|
||||
|
||||
ALTER TABLE entity_translations
|
||||
DROP CONSTRAINT IF EXISTS entity_translations_field_name_check;
|
||||
|
||||
ALTER TABLE entity_translations
|
||||
ADD CONSTRAINT entity_translations_field_name_check CHECK (
|
||||
field_name IN ('name', 'title', 'details', 'genus', 'effect', 'mosslaxEffect')
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
email text NOT NULL UNIQUE,
|
||||
@@ -201,22 +164,10 @@ CREATE TABLE IF NOT EXISTS ai_moderation_settings (
|
||||
CHECK (length(model) BETWEEN 1 AND 120)
|
||||
);
|
||||
|
||||
ALTER TABLE ai_moderation_settings
|
||||
ADD COLUMN IF NOT EXISTS api_format text NOT NULL DEFAULT 'gemini-generate-content' CHECK (api_format IN ('gemini-generate-content', 'openai-chat-completions')),
|
||||
ADD COLUMN IF NOT EXISTS auth_mode text NOT NULL DEFAULT 'bearer-token' CHECK (auth_mode IN ('query-key', 'bearer-token'));
|
||||
|
||||
INSERT INTO ai_moderation_settings (id)
|
||||
VALUES (true)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
UPDATE ai_moderation_settings
|
||||
SET api_format = 'gemini-generate-content',
|
||||
auth_mode = 'bearer-token',
|
||||
updated_at = now()
|
||||
WHERE api_format = 'openai-chat-completions'
|
||||
AND auth_mode = 'query-key'
|
||||
AND endpoint ~* '/v1beta/?$';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_moderation_cache (
|
||||
content_hash text NOT NULL,
|
||||
model text NOT NULL,
|
||||
@@ -229,9 +180,6 @@ CREATE TABLE IF NOT EXISTS ai_moderation_cache (
|
||||
CHECK (length(model) BETWEEN 1 AND 120)
|
||||
);
|
||||
|
||||
ALTER TABLE ai_moderation_cache
|
||||
ADD COLUMN IF NOT EXISTS reason text;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rate_limit_settings (
|
||||
id boolean PRIMARY KEY DEFAULT true CHECK (id = true),
|
||||
settings jsonb NOT NULL DEFAULT '{}'::jsonb CHECK (jsonb_typeof(settings) = 'object'),
|
||||
@@ -918,10 +866,6 @@ CREATE TABLE IF NOT EXISTS pokemon (
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
ALTER TABLE pokemon
|
||||
ADD COLUMN IF NOT EXISTS data_id integer CHECK (data_id > 0),
|
||||
ADD COLUMN IF NOT EXISTS data_identifier text NOT NULL DEFAULT '';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pokemon_pokemon_types (
|
||||
pokemon_id integer NOT NULL REFERENCES pokemon(id) ON DELETE CASCADE,
|
||||
type_id integer NOT NULL REFERENCES pokemon_types(id) ON DELETE CASCADE,
|
||||
@@ -942,26 +886,6 @@ CREATE TABLE IF NOT EXISTS pokemon_favorite_things (
|
||||
PRIMARY KEY (pokemon_id, favorite_thing_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS item_categories (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name text NOT NULL UNIQUE,
|
||||
sort_order integer NOT NULL DEFAULT 0 CHECK (sort_order >= 0),
|
||||
created_by_user_id integer REFERENCES users(id) ON DELETE SET NULL,
|
||||
updated_by_user_id integer REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS item_usages (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name text NOT NULL UNIQUE,
|
||||
sort_order integer NOT NULL DEFAULT 0 CHECK (sort_order >= 0),
|
||||
created_by_user_id integer REFERENCES users(id) ON DELETE SET NULL,
|
||||
updated_by_user_id integer REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS acquisition_methods (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name text NOT NULL UNIQUE,
|
||||
@@ -980,8 +904,6 @@ CREATE TABLE IF NOT EXISTS items (
|
||||
ancient_artifact_category_key text,
|
||||
category_key text NOT NULL DEFAULT 'other',
|
||||
usage_key text,
|
||||
category_id integer REFERENCES item_categories(id),
|
||||
usage_id integer REFERENCES item_usages(id),
|
||||
dyeable boolean NOT NULL DEFAULT false,
|
||||
dual_dyeable boolean NOT NULL DEFAULT false,
|
||||
pattern_editable boolean NOT NULL DEFAULT false,
|
||||
@@ -1071,58 +993,6 @@ CREATE TABLE IF NOT EXISTS dish_categories (
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
ALTER TABLE dish_categories
|
||||
ADD COLUMN IF NOT EXISTS main_material_item_id integer REFERENCES items(id);
|
||||
|
||||
ALTER TABLE dish_categories
|
||||
ADD COLUMN IF NOT EXISTS total_material_quantity integer NOT NULL DEFAULT 2;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF to_regclass('public.dishes') IS NOT NULL
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'dishes'
|
||||
AND column_name = 'main_material_item_id'
|
||||
)
|
||||
THEN
|
||||
EXECUTE '
|
||||
UPDATE dish_categories dc
|
||||
SET main_material_item_id = source.main_material_item_id
|
||||
FROM (
|
||||
SELECT DISTINCT ON (category_id) category_id, main_material_item_id
|
||||
FROM dishes
|
||||
WHERE main_material_item_id IS NOT NULL
|
||||
ORDER BY category_id, sort_order, id
|
||||
) AS source
|
||||
WHERE dc.id = source.category_id
|
||||
AND dc.main_material_item_id IS NULL
|
||||
';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
UPDATE dish_categories
|
||||
SET main_material_item_id = cookware_item_id
|
||||
WHERE main_material_item_id IS NULL;
|
||||
|
||||
ALTER TABLE dish_categories
|
||||
ALTER COLUMN main_material_item_id SET NOT NULL;
|
||||
|
||||
ALTER TABLE dish_categories
|
||||
ALTER COLUMN total_material_quantity SET DEFAULT 2;
|
||||
|
||||
UPDATE dish_categories
|
||||
SET total_material_quantity = 2
|
||||
WHERE total_material_quantity < 2;
|
||||
|
||||
ALTER TABLE dish_categories
|
||||
DROP CONSTRAINT IF EXISTS dish_categories_total_material_quantity_check;
|
||||
|
||||
ALTER TABLE dish_categories
|
||||
ADD CONSTRAINT dish_categories_total_material_quantity_check CHECK (total_material_quantity >= 2);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS dish_flavors (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name text NOT NULL UNIQUE,
|
||||
@@ -1154,15 +1024,6 @@ CREATE TABLE IF NOT EXISTS dishes (
|
||||
)
|
||||
);
|
||||
|
||||
ALTER TABLE dishes
|
||||
ADD COLUMN IF NOT EXISTS flavor_id integer REFERENCES dish_flavors(id);
|
||||
|
||||
ALTER TABLE dishes
|
||||
ALTER COLUMN secondary_material_1_item_id DROP NOT NULL;
|
||||
|
||||
ALTER TABLE dishes
|
||||
DROP COLUMN IF EXISTS main_material_item_id;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS maps (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name text NOT NULL UNIQUE,
|
||||
@@ -1202,221 +1063,6 @@ CREATE TABLE IF NOT EXISTS habitat_pokemon (
|
||||
PRIMARY KEY (habitat_id, pokemon_id, map_id, time_of_day, weather)
|
||||
);
|
||||
|
||||
ALTER TABLE life_tags
|
||||
ADD COLUMN IF NOT EXISTS is_default boolean NOT NULL DEFAULT false;
|
||||
|
||||
ALTER TABLE items
|
||||
ADD COLUMN IF NOT EXISTS details text NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS base_price integer,
|
||||
ADD COLUMN IF NOT EXISTS ancient_artifact_category_key text,
|
||||
ADD COLUMN IF NOT EXISTS category_key text,
|
||||
ADD COLUMN IF NOT EXISTS usage_key text;
|
||||
|
||||
UPDATE items
|
||||
SET base_price = NULL
|
||||
WHERE base_price < 0;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'items'
|
||||
AND column_name = 'category_id'
|
||||
AND table_schema = current_schema()
|
||||
) THEN
|
||||
ALTER TABLE items ALTER COLUMN category_id DROP NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
UPDATE items i
|
||||
SET category_key = CASE lower(trim(c.name))
|
||||
WHEN 'furniture' THEN 'furniture'
|
||||
WHEN 'misc' THEN 'misc'
|
||||
WHEN 'outdoor' THEN 'outdoor'
|
||||
WHEN 'utilities' THEN 'utilities'
|
||||
WHEN 'buildings' THEN 'buildings'
|
||||
WHEN 'blocks' THEN 'blocks'
|
||||
WHEN 'kits' THEN 'kits'
|
||||
WHEN 'nature' THEN 'nature'
|
||||
WHEN 'food' THEN 'food'
|
||||
WHEN 'materials' THEN 'materials'
|
||||
WHEN 'key items' THEN 'key-items'
|
||||
WHEN 'key-items' THEN 'key-items'
|
||||
WHEN 'other' THEN 'other'
|
||||
ELSE 'other'
|
||||
END
|
||||
FROM item_categories c
|
||||
WHERE i.category_id = c.id
|
||||
AND (i.category_key IS NULL OR i.category_key = '');
|
||||
|
||||
UPDATE items i
|
||||
SET usage_key = CASE lower(trim(u.name))
|
||||
WHEN 'decoration' THEN 'decoration'
|
||||
WHEN 'relaxation' THEN 'relaxation'
|
||||
WHEN 'toy' THEN 'toy'
|
||||
WHEN 'road' THEN 'road'
|
||||
ELSE NULL
|
||||
END
|
||||
FROM item_usages u
|
||||
WHERE i.usage_id = u.id
|
||||
AND i.usage_key IS NULL;
|
||||
|
||||
UPDATE items
|
||||
SET category_key = 'other'
|
||||
WHERE category_key IS NULL
|
||||
OR category_key NOT IN (
|
||||
'furniture',
|
||||
'misc',
|
||||
'outdoor',
|
||||
'utilities',
|
||||
'buildings',
|
||||
'blocks',
|
||||
'kits',
|
||||
'nature',
|
||||
'food',
|
||||
'materials',
|
||||
'key-items',
|
||||
'other'
|
||||
);
|
||||
|
||||
UPDATE items
|
||||
SET usage_key = NULL
|
||||
WHERE usage_key IS NOT NULL
|
||||
AND usage_key NOT IN ('decoration', 'relaxation', 'toy', 'road');
|
||||
|
||||
ALTER TABLE items
|
||||
ALTER COLUMN category_key SET NOT NULL,
|
||||
ALTER COLUMN category_key SET DEFAULT 'other';
|
||||
|
||||
ALTER TABLE items
|
||||
DROP CONSTRAINT IF EXISTS items_display_id_positive,
|
||||
DROP CONSTRAINT IF EXISTS items_base_price_check,
|
||||
DROP CONSTRAINT IF EXISTS items_ancient_artifact_category_key_check,
|
||||
DROP CONSTRAINT IF EXISTS items_category_key_check,
|
||||
DROP CONSTRAINT IF EXISTS items_usage_key_check;
|
||||
|
||||
ALTER TABLE items
|
||||
ADD CONSTRAINT items_base_price_check CHECK (base_price IS NULL OR base_price >= 0),
|
||||
ADD CONSTRAINT items_ancient_artifact_category_key_check CHECK (
|
||||
ancient_artifact_category_key IS NULL
|
||||
OR ancient_artifact_category_key IN ('lost-relics-l', 'lost-relics-s', 'fossils')
|
||||
),
|
||||
ADD CONSTRAINT items_category_key_check CHECK (category_key IN (
|
||||
'furniture',
|
||||
'misc',
|
||||
'outdoor',
|
||||
'utilities',
|
||||
'buildings',
|
||||
'blocks',
|
||||
'kits',
|
||||
'nature',
|
||||
'food',
|
||||
'materials',
|
||||
'key-items',
|
||||
'other'
|
||||
)),
|
||||
ADD CONSTRAINT items_usage_key_check CHECK (usage_key IS NULL OR usage_key IN ('decoration', 'relaxation', 'toy', 'road'));
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF to_regclass('ancient_artifacts') IS NOT NULL THEN
|
||||
ALTER TABLE ancient_artifacts
|
||||
ADD COLUMN IF NOT EXISTS image_path text NOT NULL DEFAULT '';
|
||||
|
||||
CREATE TEMP TABLE migrated_ancient_artifact_items (
|
||||
old_id integer PRIMARY KEY,
|
||||
item_id integer NOT NULL
|
||||
) ON COMMIT DROP;
|
||||
|
||||
INSERT INTO items (
|
||||
name,
|
||||
details,
|
||||
ancient_artifact_category_key,
|
||||
category_key,
|
||||
image_path,
|
||||
sort_order,
|
||||
created_by_user_id,
|
||||
updated_by_user_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
a.name,
|
||||
a.details,
|
||||
a.category_key,
|
||||
'other',
|
||||
a.image_path,
|
||||
a.sort_order,
|
||||
a.created_by_user_id,
|
||||
a.updated_by_user_id,
|
||||
a.created_at,
|
||||
a.updated_at
|
||||
FROM ancient_artifacts a
|
||||
ON CONFLICT (name) DO UPDATE
|
||||
SET ancient_artifact_category_key = EXCLUDED.ancient_artifact_category_key,
|
||||
details = CASE WHEN items.details = '' THEN EXCLUDED.details ELSE items.details END,
|
||||
image_path = CASE WHEN items.image_path = '' THEN EXCLUDED.image_path ELSE items.image_path END,
|
||||
updated_by_user_id = COALESCE(items.updated_by_user_id, EXCLUDED.updated_by_user_id),
|
||||
updated_at = GREATEST(items.updated_at, EXCLUDED.updated_at);
|
||||
|
||||
INSERT INTO migrated_ancient_artifact_items (old_id, item_id)
|
||||
SELECT a.id, i.id
|
||||
FROM ancient_artifacts a
|
||||
JOIN items i ON i.name = a.name
|
||||
ON CONFLICT (old_id) DO UPDATE SET item_id = EXCLUDED.item_id;
|
||||
|
||||
IF to_regclass('ancient_artifact_favorite_things') IS NOT NULL THEN
|
||||
INSERT INTO item_favorite_things (item_id, favorite_thing_id)
|
||||
SELECT m.item_id, aft.favorite_thing_id
|
||||
FROM ancient_artifact_favorite_things aft
|
||||
JOIN migrated_ancient_artifact_items m ON m.old_id = aft.ancient_artifact_id
|
||||
ON CONFLICT DO NOTHING;
|
||||
END IF;
|
||||
|
||||
INSERT INTO entity_translations (entity_type, entity_id, locale, field_name, value)
|
||||
SELECT 'items', m.item_id, et.locale, et.field_name, et.value
|
||||
FROM entity_translations et
|
||||
JOIN migrated_ancient_artifact_items m ON m.old_id = et.entity_id
|
||||
WHERE et.entity_type = 'ancient-artifacts'
|
||||
ON CONFLICT (entity_type, entity_id, locale, field_name) DO UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
|
||||
UPDATE wiki_edit_logs wel
|
||||
SET entity_type = 'items',
|
||||
entity_id = m.item_id
|
||||
FROM migrated_ancient_artifact_items m
|
||||
WHERE wel.entity_type = 'ancient-artifacts'
|
||||
AND wel.entity_id = m.old_id;
|
||||
|
||||
UPDATE entity_image_uploads eiu
|
||||
SET entity_type = 'items',
|
||||
entity_id = m.item_id
|
||||
FROM migrated_ancient_artifact_items m
|
||||
WHERE eiu.entity_type = 'ancient-artifacts'
|
||||
AND eiu.entity_id = m.old_id;
|
||||
|
||||
UPDATE entity_discussion_comments edc
|
||||
SET entity_id = m.item_id
|
||||
FROM migrated_ancient_artifact_items m
|
||||
WHERE edc.entity_type = 'ancient-artifacts'
|
||||
AND edc.entity_id = m.old_id;
|
||||
|
||||
DELETE FROM entity_translations
|
||||
WHERE entity_type = 'ancient-artifacts';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
DROP INDEX IF EXISTS items_display_event_item_key;
|
||||
DROP INDEX IF EXISTS items_display_order_idx;
|
||||
DROP INDEX IF EXISTS ancient_artifacts_display_order_idx;
|
||||
|
||||
ALTER TABLE items
|
||||
DROP COLUMN IF EXISTS display_id;
|
||||
|
||||
DROP TABLE IF EXISTS ancient_artifact_favorite_things;
|
||||
DROP TABLE IF EXISTS ancient_artifacts;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS environments_sort_order_idx ON environments(sort_order, id);
|
||||
CREATE INDEX IF NOT EXISTS skills_sort_order_idx ON skills(sort_order, id);
|
||||
CREATE INDEX IF NOT EXISTS favorite_things_sort_order_idx ON favorite_things(sort_order, id);
|
||||
@@ -1425,8 +1071,6 @@ CREATE INDEX IF NOT EXISTS pokemon_sort_order_idx ON pokemon(sort_order, id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS pokemon_display_event_item_key ON pokemon(display_id, is_event_item);
|
||||
CREATE INDEX IF NOT EXISTS life_tags_sort_order_idx ON life_tags(sort_order, id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS life_tags_single_default_idx ON life_tags(is_default) WHERE is_default = true;
|
||||
CREATE INDEX IF NOT EXISTS item_categories_sort_order_idx ON item_categories(sort_order, id);
|
||||
CREATE INDEX IF NOT EXISTS item_usages_sort_order_idx ON item_usages(sort_order, id);
|
||||
CREATE INDEX IF NOT EXISTS acquisition_methods_sort_order_idx ON acquisition_methods(sort_order, id);
|
||||
CREATE INDEX IF NOT EXISTS items_sort_order_idx ON items(sort_order, id);
|
||||
CREATE INDEX IF NOT EXISTS recipes_sort_order_idx ON recipes(sort_order, id);
|
||||
@@ -1468,14 +1112,6 @@ CREATE TABLE IF NOT EXISTS entity_image_uploads (
|
||||
CHECK (path !~ '(^/|\\.\\.)')
|
||||
);
|
||||
|
||||
ALTER TABLE entity_image_uploads
|
||||
DROP CONSTRAINT IF EXISTS entity_image_uploads_entity_type_check;
|
||||
|
||||
ALTER TABLE entity_image_uploads
|
||||
ADD CONSTRAINT entity_image_uploads_entity_type_check CHECK (
|
||||
entity_type IN ('pokemon', 'items', 'habitats', 'ancient-artifacts')
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS entity_image_uploads_entity_idx
|
||||
ON entity_image_uploads(entity_type, entity_id, created_at DESC, id DESC);
|
||||
|
||||
@@ -1524,14 +1160,6 @@ CREATE INDEX IF NOT EXISTS entity_discussion_comment_likes_comment_idx
|
||||
CREATE INDEX IF NOT EXISTS entity_discussion_comment_likes_user_idx
|
||||
ON entity_discussion_comment_likes(user_id, created_at DESC, comment_id DESC);
|
||||
|
||||
ALTER TABLE entity_discussion_comments
|
||||
DROP CONSTRAINT IF EXISTS entity_discussion_comments_entity_type_check;
|
||||
|
||||
ALTER TABLE entity_discussion_comments
|
||||
ADD CONSTRAINT entity_discussion_comments_entity_type_check CHECK (
|
||||
entity_type IN ('pokemon', 'items', 'recipes', 'habitats', 'ancient-artifacts')
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notifications (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
recipient_user_id integer NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -1587,9 +1215,6 @@ CREATE UNIQUE INDEX IF NOT EXISTS notifications_life_post_reaction_unique_idx
|
||||
ON notifications(recipient_user_id, actor_user_id, life_post_id)
|
||||
WHERE type = 'life_post_reaction' AND actor_user_id IS NOT NULL AND life_post_id IS NOT NULL;
|
||||
|
||||
ALTER TABLE notifications
|
||||
ADD COLUMN IF NOT EXISTS profile_user_id integer REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS notifications_user_follow_unique_idx
|
||||
ON notifications(recipient_user_id, actor_user_id, profile_user_id)
|
||||
WHERE type = 'user_follow' AND actor_user_id IS NOT NULL AND profile_user_id IS NOT NULL;
|
||||
@@ -1606,66 +1231,6 @@ CREATE TABLE IF NOT EXISTS notification_ws_tickets (
|
||||
CREATE INDEX IF NOT EXISTS notification_ws_tickets_user_idx
|
||||
ON notification_ws_tickets(user_id, expires_at DESC);
|
||||
|
||||
ALTER TABLE notifications
|
||||
ADD COLUMN IF NOT EXISTS moderation_reason text;
|
||||
|
||||
ALTER TABLE notifications
|
||||
ADD COLUMN IF NOT EXISTS profile_user_id integer REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE notifications
|
||||
DROP CONSTRAINT IF EXISTS notifications_type_check;
|
||||
|
||||
ALTER TABLE notifications
|
||||
ADD CONSTRAINT notifications_type_check CHECK (
|
||||
type IN (
|
||||
'life_post_comment',
|
||||
'life_comment_reply',
|
||||
'discussion_comment_reply',
|
||||
'life_post_reaction',
|
||||
'user_follow',
|
||||
'moderation_result'
|
||||
)
|
||||
);
|
||||
|
||||
ALTER TABLE life_tags
|
||||
ADD COLUMN IF NOT EXISTS is_rateable boolean NOT NULL DEFAULT false;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS game_versions (
|
||||
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name text NOT NULL UNIQUE,
|
||||
change_log text NOT NULL DEFAULT '',
|
||||
sort_order integer NOT NULL DEFAULT 0 CHECK (sort_order >= 0),
|
||||
created_by_user_id integer REFERENCES users(id) ON DELETE SET NULL,
|
||||
updated_by_user_id integer REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS game_versions_sort_order_idx
|
||||
ON game_versions(sort_order, id);
|
||||
|
||||
ALTER TABLE life_posts
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_status text NOT NULL DEFAULT 'unreviewed' CHECK (ai_moderation_status IN ('unreviewed', 'reviewing', 'approved', 'rejected', 'failed')),
|
||||
ADD COLUMN IF NOT EXISTS category_id integer REFERENCES life_tags(id) ON DELETE RESTRICT,
|
||||
ADD COLUMN IF NOT EXISTS game_version_id integer REFERENCES game_versions(id) ON DELETE SET NULL,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_language_code text REFERENCES languages(code) ON DELETE SET NULL,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_reason text,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_content_hash text,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_checked_at timestamptz,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_retry_count integer NOT NULL DEFAULT 0 CHECK (ai_moderation_retry_count >= 0),
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_updated_at timestamptz NOT NULL DEFAULT now();
|
||||
|
||||
UPDATE life_posts lp
|
||||
SET category_id = selected.tag_id
|
||||
FROM (
|
||||
SELECT DISTINCT ON (lpt.post_id) lpt.post_id, lpt.tag_id
|
||||
FROM life_post_tags lpt
|
||||
JOIN life_tags lt ON lt.id = lpt.tag_id
|
||||
ORDER BY lpt.post_id, lt.sort_order, lt.id
|
||||
) selected
|
||||
WHERE lp.id = selected.post_id
|
||||
AND lp.category_id IS NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS life_posts_category_idx
|
||||
ON life_posts(category_id, created_at DESC, id DESC)
|
||||
WHERE deleted_at IS NULL;
|
||||
@@ -1674,39 +1239,6 @@ CREATE INDEX IF NOT EXISTS life_posts_game_version_idx
|
||||
ON life_posts(game_version_id, created_at DESC, id DESC)
|
||||
WHERE deleted_at IS NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS life_post_ratings (
|
||||
post_id integer NOT NULL REFERENCES life_posts(id) ON DELETE CASCADE,
|
||||
user_id integer NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
rating integer NOT NULL CHECK (rating BETWEEN 1 AND 5),
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (post_id, user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS life_post_ratings_post_idx
|
||||
ON life_post_ratings(post_id, rating);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS life_post_ratings_user_idx
|
||||
ON life_post_ratings(user_id, updated_at DESC, post_id DESC);
|
||||
|
||||
ALTER TABLE life_post_comments
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_status text NOT NULL DEFAULT 'unreviewed' CHECK (ai_moderation_status IN ('unreviewed', 'reviewing', 'approved', 'rejected', 'failed')),
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_language_code text REFERENCES languages(code) ON DELETE SET NULL,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_reason text,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_content_hash text,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_checked_at timestamptz,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_retry_count integer NOT NULL DEFAULT 0 CHECK (ai_moderation_retry_count >= 0),
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_updated_at timestamptz NOT NULL DEFAULT now();
|
||||
|
||||
ALTER TABLE entity_discussion_comments
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_status text NOT NULL DEFAULT 'unreviewed' CHECK (ai_moderation_status IN ('unreviewed', 'reviewing', 'approved', 'rejected', 'failed')),
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_language_code text REFERENCES languages(code) ON DELETE SET NULL,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_reason text,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_content_hash text,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_checked_at timestamptz,
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_retry_count integer NOT NULL DEFAULT 0 CHECK (ai_moderation_retry_count >= 0),
|
||||
ADD COLUMN IF NOT EXISTS ai_moderation_updated_at timestamptz NOT NULL DEFAULT now();
|
||||
|
||||
CREATE INDEX IF NOT EXISTS life_posts_ai_moderation_status_idx
|
||||
ON life_posts(ai_moderation_status, ai_moderation_updated_at, id)
|
||||
WHERE deleted_at IS NULL;
|
||||
|
||||
Reference in New Issue
Block a user