119 lines
4.3 KiB
Python
119 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
create.py - 动态生成PostgreSQL建表SQL语句
|
||
"""
|
||
|
||
import os
|
||
import re
|
||
|
||
# 从环境变量获取表名,如果没有设置则使用默认值
|
||
table_name = os.environ.get('TABLE_NAME', 'cn_pmi_234_aaarecords')
|
||
|
||
# 2. 定义SQL模板
|
||
sql_template = f"""DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (
|
||
SELECT 1
|
||
FROM information_schema.tables
|
||
WHERE table_schema = 'public'
|
||
AND table_name = '{table_name}'
|
||
) THEN
|
||
CREATE TABLE {table_name} (
|
||
id UUID DEFAULT gen_random_uuid() PRIMARY KEY, -- id
|
||
payload JSONB NOT NULL, -- 数据
|
||
deleted BOOLEAN NOT NULL DEFAULT FALSE, -- 删除状态
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 记录创建时间
|
||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP -- 记录修改时间
|
||
);
|
||
|
||
-- 3 触发器:自动刷新 updated_at
|
||
CREATE TRIGGER trg_{table_name}_at
|
||
BEFORE UPDATE ON {table_name}
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION moddatetime(updated_at);
|
||
|
||
RAISE NOTICE '{table_name} 表已创建';
|
||
ELSE
|
||
RAISE NOTICE '{table_name} 表已存在,跳过';
|
||
END IF;
|
||
END $$;"""
|
||
|
||
def normalize_blank_lines(text):
|
||
"""规范化空行:确保END $$;和DO $$之间只有一个空行"""
|
||
# 将多个空行替换为单个空行
|
||
text = re.sub(r'\n{3,}', '\n\n', text)
|
||
|
||
# 确保END $$;后面有一个空行再接DO $$
|
||
text = re.sub(r'END \$\$;(\s*)DO \$\$', r'END $$;\n\nDO $$', text)
|
||
|
||
# 清理开头和结尾的多余空行
|
||
text = text.strip() + '\n'
|
||
|
||
return text
|
||
|
||
def update_sql_file():
|
||
"""将生成的SQL语句追加到03_create_table.sql文件中"""
|
||
|
||
# 定义文件路径
|
||
sql_file_path = os.path.join(
|
||
os.path.dirname(os.path.dirname(__file__)),
|
||
'infra',
|
||
'postgres',
|
||
'sql',
|
||
'03_create_table.sql'
|
||
)
|
||
|
||
try:
|
||
# 读取现有文件内容
|
||
with open(sql_file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
# 查找插入位置:在"部署开始"和"部署完成"之间插入
|
||
# 更简单的模式匹配
|
||
start_pattern = r"(DO \$\$.*?RAISE NOTICE '🚀============ 数据库表部署开始 ============🚀'.*?END \$\$;)"
|
||
end_pattern = r"(DO \$\$.*?RAISE NOTICE '✅============ 数据库表部署完成 ============✅'.*?END \$\$;)"
|
||
|
||
start_match = re.search(start_pattern, content, re.DOTALL)
|
||
end_match = re.search(end_pattern, content, re.DOTALL)
|
||
|
||
if start_match and end_match:
|
||
# 获取开始和结束位置
|
||
start_end_pos = start_match.end()
|
||
end_start_pos = end_match.start()
|
||
|
||
# 分割内容
|
||
before_insert = content[:start_end_pos]
|
||
existing_middle = content[start_end_pos:end_start_pos]
|
||
after_insert = content[end_start_pos:]
|
||
|
||
# 规范化空行
|
||
existing_middle = normalize_blank_lines(existing_middle)
|
||
|
||
# 组合新内容
|
||
new_content = f"""{before_insert}\n\n{sql_template}\n\n{existing_middle}\n{after_insert}"""
|
||
|
||
# 规范化整个内容的空行
|
||
new_content = normalize_blank_lines(new_content)
|
||
|
||
# 写回文件
|
||
with open(sql_file_path, 'w', encoding='utf-8') as f:
|
||
f.write(new_content)
|
||
|
||
print(f"✅ 成功更新 {sql_file_path}")
|
||
print(f"📋 生成的表名: {table_name}")
|
||
print(f"📝 SQL内容已追加到文件中")
|
||
|
||
else:
|
||
print("❌ 无法找到插入位置,请检查文件格式")
|
||
print(f"调试信息 - 开始模式匹配: {bool(start_match)}")
|
||
print(f"调试信息 - 结束模式匹配: {bool(end_match)}")
|
||
|
||
except FileNotFoundError:
|
||
print(f"❌ 文件 {sql_file_path} 不存在")
|
||
except Exception as e:
|
||
print(f"❌ 处理文件时出错: {e}")
|
||
|
||
if __name__ == "__main__":
|
||
print(f"🚀 开始生成表 '{table_name}' 的SQL语句...")
|
||
update_sql_file() |