This commit is contained in:
vipg
2025-12-26 16:57:36 +08:00
parent 665758fe32
commit 22f805af62
3 changed files with 143 additions and 210 deletions

View File

@@ -1,205 +1,21 @@
这是我工程目录的组织结构:
```tree
.
├── LICENSE
```
TableName
├── dev.sh
├── README.md
── create
├── README.md
── create.sh
└── create_table.py
├── docker-compose.yaml
├── infra
── postgres
├── scripts
│ │ └── db-lanuch-entrypoint.sh
── sql
├── 01_uuid_v7_setup.sql
├── 02_create_function.sql
└── 03_create_table.sql
└── services
```
其中 create.sh 内容如下:
```
#!/bin/bash
# create.sh - 启动Python容器执行create_table.py脚本
set -e # 遇到错误立即退出
echo "🚀 启动Python容器执行create_table.py..."
# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# 容器名称
CONTAINER_NAME="python-create-runner"
# 检查是否已存在同名容器,如果存在则删除
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "🧹 清理已存在的容器 ${CONTAINER_NAME}..."
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
fi
# 运行Python容器
echo "📦 启动Python容器..."
docker run --rm \
--name "${CONTAINER_NAME}" \
-v "${SCRIPT_DIR}:/app/create" \
-v "${PROJECT_ROOT}/infra/postgres/sql:/app/infra/postgres/sql" \
-w /app \
python:3.13.7-alpine3.22 \
sh -c "
echo '📋 容器内环境信息:'
python --version
echo ''
echo '🔧 安装依赖(如果需要)...'
pip install --quiet --no-cache-dir psycopg2-binary >/dev/null 2>&1 || true
echo '⚙️ 执行 create_table.py...'
python create/create_table.py
echo ''
echo '✅ 执行完成!'
"
echo ""
echo "🎉 create.sh 执行完成!"
```
其中 create_table.py 内容如下:
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
create.py - 动态生成PostgreSQL建表SQL语句
"""
import os
import re
# 1. 定义表名称变量,方便调整
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()
# 查找插入位置(在\"部署完成\"日志前)
insert_pattern = r'(DO \$\$.*?RAISE NOTICE \'🚀============ 数据库表部署开始 ============🚀\'.*?END \$\$;)(.*?)(DO \$\$.*?RAISE NOTICE \'============ 数据库表部署完成 ============\'.*?END \$\$;)'
match = re.search(insert_pattern, content, re.DOTALL)
if match:
# 分割内容
before_insert = match.group(1)
existing_middle = match.group(2)
after_insert = match.group(3)
# 规范化空行
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("❌ 无法找到插入位置,请检查文件格式")
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()
```
其中 03_create_table.sql 内容如下:
```sql
DO $$
BEGIN
RAISE NOTICE '🚀============ 数据库表部署开始 ============🚀';
END $$;
DO $$
BEGIN
RAISE NOTICE '✅============ 数据库表部署完成 ============✅';
END $$;
── src
├── crud
│   └── create.go
│   └── read.go
│   └── update.go
│   └── delete.go
── Dockerfile
├── go.mod
├── go.sum
── infra
│   ├── launch.go
│   ├── logger.go
│   └── postgres.go
├── main.go
└── model
└── payload.go
```

View File

@@ -1,13 +1,17 @@
#!/bin/bash
# create.sh - 启动Python容器执行create_table.py脚本
# create.sh - 启动Python容器执行create_table.py和create_src.py脚本
set -e # 遇到错误立即退出
# 定义表名变量,可以根据需要修改
TABLE_NAME="cn_pmi_a_records"
TABLE_NAME="cn_pmi_234_aaarecords"
echo "🚀 开始创建流程,表名: ${TABLE_NAME}"
echo "=========================================="
# ========== 第一部分:创建数据库表 ==========
echo "📋 第一步:创建数据库表结构..."
echo "🚀 启动Python容器执行create_table.py..."
echo "📋 目标表名: ${TABLE_NAME}"
# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -22,8 +26,8 @@ if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1
fi
# 运行Python容器
echo "📦 启动Python容器..."
# 运行Python容器执行create_table.py
echo "📦 启动Python容器执行create_table.py..."
docker run --rm \
--name "${CONTAINER_NAME}" \
-v "${SCRIPT_DIR}:/app/create" \
@@ -43,8 +47,36 @@ docker run --rm \
python create/create_table.py
echo ''
echo '✅ 执行完成!'
echo '✅ create_table.py 执行完成!'
"
# ========== 第二部分:创建服务结构 ==========
echo ""
echo "📋 第二步:创建服务文件夹结构..."
echo "🚀 执行create_src.py..."
# 运行Python容器执行create_src.py
docker run --rm \
--name "${CONTAINER_NAME}-src" \
-v "${SCRIPT_DIR}:/app/create" \
-v "${PROJECT_ROOT}/services:/app/services" \
-e TABLE_NAME="${TABLE_NAME}" \
-w /app \
python:3.13.7-alpine3.22 \
sh -c "
echo '📋 容器内环境信息:'
python --version
echo ''
echo '⚙️ 执行 create_src.py...'
python create/create_src.py
echo ''
echo '✅ create_src.py 执行完成!'
"
echo ""
echo "🎉 create.sh 执行完成!"
echo "=========================================="
echo "🎉 所有任务执行完成!"
echo "📋 表名: ${TABLE_NAME}"
echo "📁 服务目录: ${PROJECT_ROOT}/services/${TABLE_NAME}"

85
create/create_src.py Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
create_src.py - 在services目录下创建服务文件夹和文件结构
"""
import os
import sys
def create_service_structure(table_name):
"""创建服务文件夹结构"""
# 获取项目根目录
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
services_dir = os.path.join(project_root, 'services')
# 创建服务目录
service_dir = os.path.join(services_dir, table_name)
print(f"🚀 开始创建服务结构: {table_name}")
print(f"📁 目标目录: {service_dir}")
try:
# 创建主目录
os.makedirs(service_dir, exist_ok=True)
print(f"✅ 创建主目录: {service_dir}")
# 创建子目录
subdirs = ['src', 'src/crud', 'src/infra', 'src/model']
for subdir in subdirs:
dir_path = os.path.join(service_dir, subdir)
os.makedirs(dir_path, exist_ok=True)
print(f"✅ 创建子目录: {dir_path}")
# 定义要创建的文件列表
files_to_create = [
'dev.sh',
'README.md',
'src/Dockerfile',
'src/go.mod',
'src/go.sum',
'src/main.go',
'src/crud/create.go',
'src/crud/read.go',
'src/crud/update.go',
'src/crud/delete.go',
'src/infra/launch.go',
'src/infra/logger.go',
'src/infra/postgres.go',
'src/model/payload.go'
]
# 创建所有文件
for file_path in files_to_create:
full_path = os.path.join(service_dir, file_path)
os.makedirs(os.path.dirname(full_path), exist_ok=True) # 确保目录存在
# 创建空文件
with open(full_path, 'w', encoding='utf-8') as f:
f.write('') # 创建空文件
print(f"✅ 创建文件: {full_path}")
print(f"🎉 服务结构创建完成: {table_name}")
return True
except Exception as e:
print(f"❌ 创建服务结构时出错: {e}")
return False
if __name__ == "__main__":
# 从环境变量获取表名
table_name = os.environ.get('TABLE_NAME')
if not table_name:
print("❌ 错误: 未设置 TABLE_NAME 环境变量")
sys.exit(1)
print(f"📋 接收到的表名: {table_name}")
success = create_service_structure(table_name)
if success:
sys.exit(0)
else:
sys.exit(1)