topfans/docker/sql/migrations/V6__consolidated_migrations.sql
2026-05-17 19:55:22 +08:00

353 lines
13 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- V6__consolidated_migrations.sql
-- 整合所有分散的迁移脚本2026-05-15
-- 包含: materials, asset_material_relations, 经济系统表, 字段修改等
-- =====================================================
-- Part 1: materials 素材主表
-- =====================================================
CREATE TABLE IF NOT EXISTS public.materials (
id BIGSERIAL PRIMARY KEY,
oss_key VARCHAR(255) NOT NULL,
original_name VARCHAR(255) NOT NULL,
file_size BIGINT NOT NULL,
mime_type VARCHAR(100) NOT NULL,
width INT,
height INT,
hash VARCHAR(64) NOT NULL,
created_by BIGINT NOT NULL,
star_id BIGINT NOT NULL DEFAULT 0,
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
deleted_at BIGINT
);
CREATE UNIQUE INDEX IF NOT EXISTS uk_materials_oss_key ON public.materials(oss_key);
CREATE INDEX IF NOT EXISTS idx_materials_hash ON public.materials(hash);
CREATE INDEX IF NOT EXISTS idx_materials_created_by ON public.materials(created_by);
CREATE INDEX IF NOT EXISTS idx_materials_star_id ON public.materials(star_id);
COMMENT ON TABLE public.materials IS '素材主表';
-- =====================================================
-- Part 2: asset_material_relations 资产-素材关联表
-- =====================================================
CREATE TABLE IF NOT EXISTS public.asset_material_relations (
id BIGSERIAL PRIMARY KEY,
asset_id BIGINT NOT NULL,
material_id BIGINT NOT NULL,
material_type VARCHAR(50) NOT NULL,
layer_order INT NOT NULL DEFAULT 0,
pos_x DOUBLE PRECISION,
pos_y DOUBLE PRECISION,
opacity DOUBLE PRECISION DEFAULT 1.0,
rotation DOUBLE PRECISION DEFAULT 0,
scale_x DOUBLE PRECISION DEFAULT 1.0,
scale_y DOUBLE PRECISION DEFAULT 1.0,
version INT NOT NULL DEFAULT 1,
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
deleted_at BIGINT
);
CREATE INDEX IF NOT EXISTS idx_amr_asset_id ON public.asset_material_relations(asset_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_amr_material_id ON public.asset_material_relations(material_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_amr_asset_type_layer ON public.asset_material_relations(asset_id, material_type, layer_order) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS uk_amr_asset_type_active ON public.asset_material_relations(asset_id, material_type) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS uk_amr_asset_layer_active ON public.asset_material_relations(asset_id, layer_order) WHERE deleted_at IS NULL;
COMMENT ON TABLE public.asset_material_relations IS '资产-素材关联表';
-- 外键约束(如果 assets 表已存在)
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_tables WHERE tablename = 'assets') THEN
ALTER TABLE public.asset_material_relations
ADD CONSTRAINT fk_amr_asset
FOREIGN KEY (asset_id) REFERENCES public.assets(id) ON DELETE CASCADE;
END IF;
EXCEPTION WHEN others THEN
RAISE NOTICE 'Foreign key constraint for asset_material_relations skipped: %', SQLERRM;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_tables WHERE tablename = 'materials') THEN
ALTER TABLE public.asset_material_relations
ADD CONSTRAINT fk_amr_material
FOREIGN KEY (material_id) REFERENCES public.materials(id) ON DELETE RESTRICT;
END IF;
EXCEPTION WHEN others THEN
RAISE NOTICE 'Foreign key constraint for asset_material_relations skipped: %', SQLERRM;
END $$;
-- =====================================================
-- Part 3: user_mint_count 铸爱次数表
-- =====================================================
CREATE TABLE IF NOT EXISTS public.user_mint_count (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
star_id BIGINT NOT NULL,
mint_count INT NOT NULL DEFAULT 0,
revenue_boost_bps INT NOT NULL DEFAULT 0,
updated_at BIGINT NOT NULL,
CONSTRAINT uk_user_mint_count_user_star UNIQUE (user_id, star_id)
);
CREATE INDEX IF NOT EXISTS idx_user_mint_count_user ON public.user_mint_count USING btree (user_id);
CREATE INDEX IF NOT EXISTS idx_user_mint_count_star ON public.user_mint_count USING btree (star_id);
COMMENT ON TABLE public.user_mint_count IS '用户在某偶像下的累计铸爱次数与收益加成(基点)';
-- =====================================================
-- Part 4: mint_cost_config 铸爱阶梯配置表
-- =====================================================
CREATE TABLE IF NOT EXISTS public.mint_cost_config (
id BIGSERIAL PRIMARY KEY,
mint_count INT NOT NULL,
cost_crystal BIGINT NOT NULL,
probability BIGINT NOT NULL DEFAULT 0,
reward_type VARCHAR(50) DEFAULT NULL,
reward_value BIGINT NOT NULL DEFAULT 0,
description VARCHAR(255),
updated_at BIGINT NOT NULL,
CONSTRAINT uk_mint_cost_config_mint_count UNIQUE (mint_count)
);
COMMENT ON TABLE public.mint_cost_config IS '铸爱次数阶梯消耗与保底配置';
-- 插入铸爱阶梯数据
INSERT INTO public.mint_cost_config (mint_count, cost_crystal, probability, reward_type, reward_value, description, updated_at)
VALUES
(1, 2, 0, NULL, 0, '第1次', 1773322573872),
(2, 4, 0, NULL, 0, '第2次', 1773322573872),
(3, 8, 0, NULL, 0, '第3次', 1773322573872),
(4, 16, 0, NULL, 0, '第4次', 1773322573872),
(5, 32, 0, NULL, 0, '第5次', 1773322573872),
(6, 64, 0, NULL, 0, '第6次', 1773322573872),
(7, 128, 0, NULL, 0, '第7次', 1773322573872),
(8, 256, 0, NULL, 0, '第8次', 1773322573872),
(9, 512, 20, '收益提升', 5, '小保底', 1773322573872),
(10, 1024, 100, '收益提升', 5, '大保底', 1773322573872)
ON CONFLICT (mint_count) DO UPDATE SET
cost_crystal = EXCLUDED.cost_crystal,
probability = EXCLUDED.probability,
reward_type = EXCLUDED.reward_type,
reward_value = EXCLUDED.reward_value,
description = EXCLUDED.description,
updated_at = EXCLUDED.updated_at;
-- =====================================================
-- Part 5: 字段修改迁移
-- =====================================================
-- 5.1 exhibitions 表添加 deleted_at 字段
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'exhibitions' AND column_name = 'deleted_at'
) THEN
ALTER TABLE public.exhibitions ADD COLUMN deleted_at BIGINT;
RAISE NOTICE 'Column deleted_at added to exhibitions table';
ELSE
RAISE NOTICE 'Column deleted_at already exists in exhibitions table';
END IF;
END $$;
-- 5.2 assets 表添加 material_type 字段
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'assets' AND column_name = 'material_type'
) THEN
ALTER TABLE public.assets ADD COLUMN material_type VARCHAR(50);
RAISE NOTICE 'Column material_type added to assets table';
ELSE
RAISE NOTICE 'Column material_type already exists in assets table';
END IF;
END $$;
-- 5.3 activities 表添加 icon 字段
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'activities' AND column_name = 'icon'
) THEN
ALTER TABLE public.activities ADD COLUMN icon VARCHAR(500) DEFAULT '';
RAISE NOTICE 'Column icon added to activities table';
ELSE
RAISE NOTICE 'Column icon already exists in activities table';
END IF;
END $$;
-- 5.4 activities 表添加 overall_end_time 字段
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'activities' AND column_name = 'overall_end_time'
) THEN
ALTER TABLE public.activities ADD COLUMN overall_end_time BIGINT DEFAULT 0;
RAISE NOTICE 'Column overall_end_time added to activities table';
ELSE
RAISE NOTICE 'Column overall_end_time already exists in activities table';
END IF;
END $$;
-- 5.5 fan_profiles 表添加 avatar_url 字段
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'fan_profiles' AND column_name = 'avatar_url'
) THEN
ALTER TABLE public.fan_profiles ADD COLUMN avatar_url VARCHAR(500);
RAISE NOTICE 'Column avatar_url added to fan_profiles table';
ELSE
RAISE NOTICE 'Column avatar_url already exists in fan_profiles table';
END IF;
END $$;
-- 5.6 assets 表添加 is_original 字段
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'assets' AND column_name = 'is_original'
) THEN
ALTER TABLE public.assets ADD COLUMN is_original BOOLEAN DEFAULT false;
RAISE NOTICE 'Column is_original added to assets table';
ELSE
RAISE NOTICE 'Column is_original already exists in assets table';
END IF;
END $$;
-- 5.7 activities 表添加 theme 字段
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'activities' AND column_name = 'theme'
) THEN
ALTER TABLE public.activities ADD COLUMN theme VARCHAR(100);
RAISE NOTICE 'Column theme added to activities table';
ELSE
RAISE NOTICE 'Column theme already exists in activities table';
END IF;
END $$;
-- =====================================================
-- Part 6: 索引和约束修改
-- =====================================================
-- 6.1 asset_likes 表唯一约束修改(添加 star_id
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'uk_asset_likes_user_asset'
) THEN
ALTER TABLE public.asset_likes DROP CONSTRAINT uk_asset_likes_user_asset;
RAISE NOTICE 'Old constraint uk_asset_likes_user_asset dropped';
END IF;
EXCEPTION WHEN others THEN
RAISE NOTICE 'Constraint uk_asset_likes_user_asset not found or already dropped: %', SQLERRM;
END $$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'uk_asset_likes_user_asset_star'
) THEN
ALTER TABLE public.asset_likes ADD CONSTRAINT uk_asset_likes_user_asset_star UNIQUE (user_id, asset_id, star_id);
RAISE NOTICE 'New constraint uk_asset_likes_user_asset_star added';
END IF;
EXCEPTION WHEN others THEN
RAISE NOTICE 'Constraint uk_asset_likes_user_asset_star already exists: %', SQLERRM;
END $$;
-- 6.2 exhibitions 表唯一约束移除asset_id
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'uk_asset'
) THEN
ALTER TABLE public.exhibitions DROP CONSTRAINT uk_asset;
RAISE NOTICE 'Constraint uk_asset dropped from exhibitions table';
END IF;
EXCEPTION WHEN others THEN
RAISE NOTICE 'Constraint uk_asset not found or already dropped: %', SQLERRM;
END $$;
-- 6.3 exhibitions 表添加 idx_asset 普通索引
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_indexes WHERE indexname = 'idx_asset' AND schemaname = 'public'
) THEN
CREATE INDEX idx_asset ON public.exhibitions(asset_id);
RAISE NOTICE 'Index idx_asset created on exhibitions table';
END IF;
EXCEPTION WHEN others THEN
RAISE NOTICE 'Index idx_asset already exists: %', SQLERRM;
END $$;
-- =====================================================
-- Migration completed
-- =====================================================
DO $$
BEGIN
RAISE NOTICE 'V6__consolidated_migrations completed successfully';
END $$;
-- 素材主表
CREATE TABLE materials (
id BIGSERIAL PRIMARY KEY,
oss_key VARCHAR(255) NOT NULL,
original_name VARCHAR(255) NOT NULL,
file_size BIGINT NOT NULL,
mime_type VARCHAR(100) NOT NULL,
width INT,
height INT,
hash VARCHAR(64) NOT NULL,
created_by BIGINT NOT NULL,
star_id BIGINT NOT NULL DEFAULT 0,
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
deleted_at BIGINT
);
CREATE UNIQUE INDEX uk_materials_oss_key ON materials(oss_key);
CREATE INDEX idx_materials_hash ON materials(hash);
CREATE INDEX idx_materials_created_by ON materials(created_by);
CREATE INDEX idx_materials_star_id ON materials(star_id);
-- 资产-素材关联表
CREATE TABLE asset_material_relations (
id BIGSERIAL PRIMARY KEY,
asset_id BIGINT NOT NULL REFERENCES assets(id) ON DELETE CASCADE,
material_id BIGINT NOT NULL REFERENCES materials(id) ON DELETE RESTRICT,
material_type VARCHAR(50) NOT NULL,
layer_order INT NOT NULL DEFAULT 0,
pos_x DOUBLE PRECISION,
pos_y DOUBLE PRECISION,
opacity DOUBLE PRECISION DEFAULT 1.0,
rotation DOUBLE PRECISION DEFAULT 0,
scale_x DOUBLE PRECISION DEFAULT 1.0,
scale_y DOUBLE PRECISION DEFAULT 1.0,
version INT NOT NULL DEFAULT 1,
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
deleted_at BIGINT
);
-- 索引
CREATE INDEX idx_amr_asset_id ON asset_material_relations(asset_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_amr_material_id ON asset_material_relations(material_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_amr_asset_type_layer ON asset_material_relations(asset_id, material_type, layer_order) WHERE deleted_at IS NULL;
-- 部分唯一索引(软删除感知)
CREATE UNIQUE INDEX uk_amr_asset_type_active ON asset_material_relations(asset_id, material_type) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX uk_amr_asset_layer_active ON asset_material_relations(asset_id, layer_order) WHERE deleted_at IS NULL;