Files
akmon/safe_config_table_init.sql
2026-01-20 08:04:15 +08:00

286 lines
11 KiB
SQL

-- ===================================================================
-- 安全的全局配置表初始化脚本
-- 适配现有表结构,避免字段冲突
-- ===================================================================
-- 首先检查现有的 ak_languages 表结构
DO $$
DECLARE
rec RECORD;
BEGIN
RAISE NOTICE '========================================';
RAISE NOTICE '检查现有 ak_languages 表结构:';
RAISE NOTICE '========================================';
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'ak_languages') THEN
FOR rec IN
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages'
ORDER BY ordinal_position
LOOP
RAISE NOTICE '列: % - 类型: % - 可空: % - 默认值: %',
rec.column_name, rec.data_type, rec.is_nullable, rec.column_default;
END LOOP;
ELSE
RAISE NOTICE 'ak_languages 表不存在';
END IF;
RAISE NOTICE '========================================';
END $$;
-- 检查并创建必要的扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- 1. 检查并创建/修改主配置表
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = 'public' AND table_name = 'ak_global_config'
) THEN
-- 如果主配置表不存在,创建新的主表+翻译表结构
CREATE TABLE public.ak_global_config (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
config_key VARCHAR(100) NOT NULL UNIQUE,
config_type VARCHAR(50) DEFAULT 'string',
config_category VARCHAR(50) DEFAULT 'general',
default_value TEXT,
is_translatable BOOLEAN DEFAULT false,
is_active BOOLEAN DEFAULT true,
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
RAISE NOTICE '已创建新的 ak_global_config 主表';
ELSE
RAISE NOTICE 'ak_global_config 表已存在,检查是否需要添加字段';
-- 检查并添加缺失的字段
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_global_config'
AND column_name = 'config_category'
) THEN
ALTER TABLE public.ak_global_config ADD COLUMN config_category VARCHAR(50) DEFAULT 'general';
RAISE NOTICE '已添加 config_category 字段';
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_global_config'
AND column_name = 'is_translatable'
) THEN
ALTER TABLE public.ak_global_config ADD COLUMN is_translatable BOOLEAN DEFAULT false;
RAISE NOTICE '已添加 is_translatable 字段';
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_global_config'
AND column_name = 'sort_order'
) THEN
ALTER TABLE public.ak_global_config ADD COLUMN sort_order INTEGER DEFAULT 0;
RAISE NOTICE '已添加 sort_order 字段';
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_global_config'
AND column_name = 'default_value'
) THEN
ALTER TABLE public.ak_global_config ADD COLUMN default_value TEXT;
RAISE NOTICE '已添加 default_value 字段';
END IF;
END IF;
END $$;
-- 2. 创建翻译表
CREATE TABLE IF NOT EXISTS public.ak_global_config_translations (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
config_id UUID NOT NULL REFERENCES public.ak_global_config(id) ON DELETE CASCADE,
language_code VARCHAR(10) NOT NULL,
translated_value TEXT NOT NULL,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(config_id, language_code)
);
-- 3. 适配现有的 ak_languages 表
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'ak_languages') THEN
RAISE NOTICE '使用现有的 ak_languages 表';
-- 检查并添加可能缺失的字段
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages'
AND column_name = 'sort_order'
) THEN
ALTER TABLE public.ak_languages ADD COLUMN sort_order INTEGER DEFAULT 0;
RAISE NOTICE '已为 ak_languages 表添加 sort_order 字段';
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages'
AND column_name = 'is_default'
) THEN
ALTER TABLE public.ak_languages ADD COLUMN is_default BOOLEAN DEFAULT false;
RAISE NOTICE '已为 ak_languages 表添加 is_default 字段';
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages'
AND column_name = 'native_name'
) THEN
ALTER TABLE public.ak_languages ADD COLUMN native_name VARCHAR(100);
RAISE NOTICE '已为 ak_languages 表添加 native_name 字段';
END IF;
ELSE
-- 创建新的语言表
CREATE TABLE public.ak_languages (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
code VARCHAR(10) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
native_name VARCHAR(100) NOT NULL,
is_active BOOLEAN DEFAULT true,
is_default BOOLEAN DEFAULT false,
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
RAISE NOTICE '已创建新的 ak_languages 表';
END IF;
END $$;
-- 4. 创建索引
CREATE INDEX IF NOT EXISTS idx_ak_global_config_key ON public.ak_global_config(config_key);
CREATE INDEX IF NOT EXISTS idx_ak_global_config_active ON public.ak_global_config(is_active);
CREATE INDEX IF NOT EXISTS idx_ak_global_config_category ON public.ak_global_config(config_category);
CREATE INDEX IF NOT EXISTS idx_ak_global_config_translatable ON public.ak_global_config(is_translatable);
CREATE INDEX IF NOT EXISTS idx_ak_global_config_translations_config ON public.ak_global_config_translations(config_id);
CREATE INDEX IF NOT EXISTS idx_ak_global_config_translations_lang ON public.ak_global_config_translations(language_code);
CREATE INDEX IF NOT EXISTS idx_ak_global_config_translations_active ON public.ak_global_config_translations(is_active);
CREATE INDEX IF NOT EXISTS idx_ak_languages_code ON public.ak_languages(code);
CREATE INDEX IF NOT EXISTS idx_ak_languages_active ON public.ak_languages(is_active);
-- 5. 安全地插入语言数据(动态构建 INSERT 语句)
DO $$
DECLARE
has_sort_order BOOLEAN;
has_is_default BOOLEAN;
has_native_name BOOLEAN;
insert_sql TEXT;
BEGIN
-- 检查字段是否存在
SELECT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages' AND column_name = 'sort_order'
) INTO has_sort_order;
SELECT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages' AND column_name = 'is_default'
) INTO has_is_default;
SELECT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages' AND column_name = 'native_name'
) INTO has_native_name;
-- 构建动态 INSERT 语句
insert_sql := 'INSERT INTO public.ak_languages (code, name';
IF has_native_name THEN
insert_sql := insert_sql || ', native_name';
END IF;
IF has_is_default THEN
insert_sql := insert_sql || ', is_default';
END IF;
IF has_sort_order THEN
insert_sql := insert_sql || ', sort_order';
END IF;
insert_sql := insert_sql || ') VALUES ';
insert_sql := insert_sql || '(''zh'', ''Chinese Simplified''';
IF has_native_name THEN
insert_sql := insert_sql || ', ''简体中文''';
END IF;
IF has_is_default THEN
insert_sql := insert_sql || ', true';
END IF;
IF has_sort_order THEN
insert_sql := insert_sql || ', 1';
END IF;
insert_sql := insert_sql || '), (''en'', ''English''';
IF has_native_name THEN
insert_sql := insert_sql || ', ''English''';
END IF;
IF has_is_default THEN
insert_sql := insert_sql || ', false';
END IF;
IF has_sort_order THEN
insert_sql := insert_sql || ', 2';
END IF;
insert_sql := insert_sql || ') ON CONFLICT (code) DO UPDATE SET name = EXCLUDED.name';
IF has_native_name THEN
insert_sql := insert_sql || ', native_name = EXCLUDED.native_name';
END IF;
IF has_is_default THEN
insert_sql := insert_sql || ', is_default = EXCLUDED.is_default';
END IF;
IF has_sort_order THEN
insert_sql := insert_sql || ', sort_order = EXCLUDED.sort_order';
END IF;
-- 执行动态 SQL
EXECUTE insert_sql;
RAISE NOTICE '已安全插入语言数据';
RAISE NOTICE '执行的 SQL: %', insert_sql;
END $$;
-- 6. 显示最终的表结构确认
DO $$
DECLARE
rec RECORD;
BEGIN
RAISE NOTICE '========================================';
RAISE NOTICE '最终的 ak_languages 表结构:';
FOR rec IN
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'ak_languages'
ORDER BY ordinal_position
LOOP
RAISE NOTICE ' - % (%)', rec.column_name, rec.data_type;
END LOOP;
RAISE NOTICE '========================================';
RAISE NOTICE '语言数据:';
FOR rec IN
SELECT code, name FROM public.ak_languages ORDER BY code
LOOP
RAISE NOTICE ' - %: %', rec.code, rec.name;
END LOOP;
RAISE NOTICE '========================================';
END $$;