Files
railwaysystem/RuoYi-Vue/sql/system/kingbase/006_accommodation_history_constraint.sql
T

71 lines
3.3 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.
-- 006_accommodation_history_constraint.sql
-- 目标:移除 train_accommodation 全局唯一约束 uq_accommodation_enroll,
-- 创建部分唯一索引 uq_accommodation_enroll_active (每个 enrollment 最多 1 条有效住宿),
-- 允许学员拥有多条退宿历史记录 (status=2),彻底支持调房与历史留痕。
DO $$
DECLARE
v_dup_count INTEGER;
v_con_def TEXT;
v_idx_def TEXT;
BEGIN
-- 1. Pre-Migration Data Safety Guard
-- 检查是否已存在同一个 enrollment_id 拥有 2 条或以上处于有效状态 (0=预分配, 1=已入住) 的住宿记录
SELECT COUNT(*) INTO v_dup_count
FROM (
SELECT enrollment_id
FROM train_accommodation
WHERE accommodation_status IN (0, 1)
GROUP BY enrollment_id
HAVING COUNT(*) > 1
) t;
IF v_dup_count > 0 THEN
RAISE EXCEPTION 'Pre-migration check failed: found % enrollment(s) with multiple active accommodations (status IN (0,1)). Manual resolution required before applying migration 006.', v_dup_count;
END IF;
-- 2. Existing Constraint Guard (Idempotent Drop)
-- 检查约束 uq_accommodation_enroll 是否存在且符合预期
SELECT pg_get_constraintdef(c.oid) INTO v_con_def
FROM pg_constraint c
JOIN pg_class t ON c.conrelid = t.oid
WHERE t.relname = 'train_accommodation'
AND c.conname = 'uq_accommodation_enroll';
IF v_con_def IS NOT NULL THEN
-- 验证旧约束是否为 UNIQUE (enrollment_id)
IF v_con_def ILIKE 'UNIQUE (enrollment_id)%' THEN
RAISE NOTICE 'Dropping legacy global unique constraint: uq_accommodation_enroll';
ALTER TABLE train_accommodation DROP CONSTRAINT uq_accommodation_enroll;
ELSE
RAISE EXCEPTION 'Constraint collision: constraint uq_accommodation_enroll exists but definition is unexpected: %', v_con_def;
END IF;
ELSE
RAISE NOTICE 'Constraint uq_accommodation_enroll does not exist, skipping drop.';
END IF;
-- 3. New Index Collision Guard & Creation
-- 检查部分唯一索引 uq_accommodation_enroll_active
SELECT pg_get_indexdef(i.indexrelid) INTO v_idx_def
FROM pg_index i
JOIN pg_class c ON i.indexrelid = c.oid
JOIN pg_class t ON i.indrelid = t.oid
WHERE t.relname = 'train_accommodation'
AND c.relname = 'uq_accommodation_enroll_active';
IF v_idx_def IS NOT NULL THEN
-- 验证已有索引是否为预期的部分唯一索引
IF v_idx_def ILIKE '%UNIQUE INDEX uq_accommodation_enroll_active ON %train_accommodation% (enrollment_id)%WHERE (accommodation_status = ANY (ARRAY[0, 1]))%'
OR v_idx_def ILIKE '%UNIQUE INDEX uq_accommodation_enroll_active ON %train_accommodation% (enrollment_id)%WHERE%accommodation_status IN (0, 1)%' THEN
RAISE NOTICE 'Partial unique index uq_accommodation_enroll_active already exists with expected definition, skipping creation.';
ELSE
RAISE EXCEPTION 'Index collision: index uq_accommodation_enroll_active exists but definition differs: %', v_idx_def;
END IF;
ELSE
RAISE NOTICE 'Creating partial unique index: uq_accommodation_enroll_active';
CREATE UNIQUE INDEX uq_accommodation_enroll_active
ON train_accommodation (enrollment_id)
WHERE accommodation_status IN (0, 1);
END IF;
END $$;