mirror of
https://github.com/rnvm9wjdtj-bot/myaps_api.git
synced 2026-06-02 05:54:40 +00:00
feat(migrate): add staging and monitor module database setup scripts
新增了两套数据库一键建表脚本: 1. PostgreSQL缓冲表建表脚本,用于APS数据清洗缓冲表初始化 2. SQLite监控模块建表脚本,用于API监控数据记录表初始化 同时附带了对应的SQL建表语句文件
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
-- =====================================================
|
||||
-- 监控模块数据库表建表脚本 (SQLite版本)
|
||||
-- 版本: V001
|
||||
-- 生成时间: 自动生成
|
||||
-- 说明: 可重入脚本,支持重复执行和增量更新
|
||||
-- =====================================================
|
||||
|
||||
-- =====================================================
|
||||
-- 1. API 请求记录表
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS api_requests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
request_id VARCHAR(36),
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
method VARCHAR(10) NOT NULL,
|
||||
path VARCHAR(512) NOT NULL,
|
||||
query_params TEXT,
|
||||
status_code INTEGER NOT NULL,
|
||||
response_time REAL NOT NULL,
|
||||
client_ip VARCHAR(64),
|
||||
user_agent TEXT,
|
||||
payload_size INTEGER,
|
||||
response_size INTEGER,
|
||||
request_body TEXT,
|
||||
response_body TEXT,
|
||||
is_slow INTEGER DEFAULT 0,
|
||||
slow_threshold REAL,
|
||||
is_error INTEGER DEFAULT 0,
|
||||
error_message TEXT,
|
||||
is_internal INTEGER DEFAULT 0
|
||||
);
|
||||
|
||||
-- 索引(幂等创建)
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_timestamp ON api_requests(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_path ON api_requests(path);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_status_code ON api_requests(status_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_response_time ON api_requests(response_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_is_slow ON api_requests(is_slow);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_is_error ON api_requests(is_error);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_is_internal ON api_requests(is_internal);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_request_id ON api_requests(request_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_client_ip ON api_requests(client_ip);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_method ON api_requests(method);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_requests_timestamp_status ON api_requests(timestamp, status_code);
|
||||
|
||||
-- =====================================================
|
||||
-- 2. 对外 HTTP 请求记录表
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS outbound_api_requests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
method VARCHAR(10) NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
status_code INTEGER NOT NULL,
|
||||
duration REAL NOT NULL,
|
||||
request_headers TEXT,
|
||||
request_body TEXT,
|
||||
response_headers TEXT,
|
||||
response_body TEXT,
|
||||
error_message TEXT,
|
||||
module VARCHAR(255),
|
||||
is_error INTEGER DEFAULT 0,
|
||||
is_slow INTEGER DEFAULT 0,
|
||||
is_internal INTEGER DEFAULT 0
|
||||
);
|
||||
|
||||
-- 索引(幂等创建)
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_timestamp ON outbound_api_requests(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_module ON outbound_api_requests(module);
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_status_code ON outbound_api_requests(status_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_is_error ON outbound_api_requests(is_error);
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_is_slow ON outbound_api_requests(is_slow);
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_is_internal ON outbound_api_requests(is_internal);
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_method ON outbound_api_requests(method);
|
||||
CREATE INDEX IF NOT EXISTS idx_outbound_timestamp_status ON outbound_api_requests(timestamp, status_code);
|
||||
|
||||
-- =====================================================
|
||||
-- 3. 系统日志表
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS system_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
level VARCHAR(10) NOT NULL,
|
||||
module VARCHAR(255) NOT NULL,
|
||||
function VARCHAR(255) NOT NULL,
|
||||
line_number INTEGER NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
details TEXT,
|
||||
stack_trace TEXT,
|
||||
process_id INTEGER,
|
||||
thread_id INTEGER,
|
||||
thread_name VARCHAR(255)
|
||||
);
|
||||
|
||||
-- 索引(幂等创建)
|
||||
CREATE INDEX IF NOT EXISTS idx_logs_timestamp ON system_logs(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_logs_level ON system_logs(level);
|
||||
CREATE INDEX IF NOT EXISTS idx_logs_module ON system_logs(module);
|
||||
CREATE INDEX IF NOT EXISTS idx_logs_function ON system_logs(function);
|
||||
CREATE INDEX IF NOT EXISTS idx_logs_timestamp_level ON system_logs(timestamp, level);
|
||||
|
||||
-- =====================================================
|
||||
-- 4. Binlog 位置记录表
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS binlog_positions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
server_id VARCHAR(255) NOT NULL,
|
||||
log_file VARCHAR(255) NOT NULL,
|
||||
log_pos INTEGER NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 索引(幂等创建)
|
||||
CREATE INDEX IF NOT EXISTS idx_binlog_server_id ON binlog_positions(server_id);
|
||||
|
||||
-- =====================================================
|
||||
-- 5. 已处理事件记录表(用于去重)
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS processed_events (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_id VARCHAR(512) UNIQUE NOT NULL,
|
||||
log_file VARCHAR(255) NOT NULL,
|
||||
log_pos INTEGER NOT NULL,
|
||||
event_type VARCHAR(100) NOT NULL,
|
||||
table_name VARCHAR(255) NOT NULL,
|
||||
database_name VARCHAR(255) NOT NULL,
|
||||
processed_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 索引(幂等创建)
|
||||
CREATE INDEX IF NOT EXISTS idx_events_event_id ON processed_events(event_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_events_log_file_pos ON processed_events(log_file, log_pos);
|
||||
CREATE INDEX IF NOT EXISTS idx_events_processed_at ON processed_events(processed_at);
|
||||
|
||||
-- =====================================================
|
||||
-- 6. 失败操作记录表
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS failed_operations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
operation_id VARCHAR(64) UNIQUE NOT NULL,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
db_name VARCHAR(100) NOT NULL,
|
||||
function_name VARCHAR(255) NOT NULL,
|
||||
args_json TEXT NOT NULL,
|
||||
kwargs_json TEXT NOT NULL,
|
||||
error_message TEXT NOT NULL,
|
||||
error_type VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(50) DEFAULT 'pending',
|
||||
retry_count INTEGER DEFAULT 0,
|
||||
max_retries INTEGER DEFAULT 10,
|
||||
last_retry_time DATETIME,
|
||||
next_retry_time DATETIME,
|
||||
event_type VARCHAR(100),
|
||||
event_data TEXT,
|
||||
metadata TEXT
|
||||
);
|
||||
|
||||
-- 索引(幂等创建)
|
||||
CREATE INDEX IF NOT EXISTS idx_failed_timestamp ON failed_operations(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_failed_db_name_status ON failed_operations(db_name, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_failed_next_retry_status ON failed_operations(next_retry_time, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_failed_event_type ON failed_operations(event_type);
|
||||
|
||||
-- =====================================================
|
||||
-- 7. 版本管理表
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS schema_version (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
version VARCHAR(16) UNIQUE NOT NULL,
|
||||
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
description TEXT,
|
||||
sql_scripts TEXT,
|
||||
status VARCHAR(16) DEFAULT 'applied'
|
||||
);
|
||||
|
||||
-- =====================================================
|
||||
-- 记录版本(幂等)
|
||||
-- =====================================================
|
||||
INSERT OR IGNORE INTO schema_version (version, description, sql_scripts)
|
||||
VALUES (
|
||||
'V001',
|
||||
'初始化监控模块表结构:api_requests, outbound_api_requests, system_logs, binlog_positions, processed_events, failed_operations',
|
||||
'monitor_tables.sql V001'
|
||||
);
|
||||
|
||||
-- =====================================================
|
||||
-- 完成提示
|
||||
-- =====================================================
|
||||
-- 执行完成后,可通过以下命令验证:
|
||||
-- SELECT name FROM sqlite_master WHERE type='table';
|
||||
-- SELECT * FROM schema_version ORDER BY applied_at DESC;
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
#!/bin/bash
|
||||
# ==============================================
|
||||
# 监控模块数据库一键建表脚本
|
||||
# 使用方法: ./setup_monitor_tables.sh [选项]
|
||||
# 功能: 向MyAPS API容器的SQLite数据库执行建表脚本
|
||||
# ==============================================
|
||||
|
||||
set -e
|
||||
|
||||
# 配置
|
||||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
SQL_FILE="${SCRIPT_DIR}/monitor_tables.sql"
|
||||
ENV_FILE="${SCRIPT_DIR}/../../../.env"
|
||||
CONTAINER_NAME="myaps_api"
|
||||
STORAGE_DIR="/app/storage"
|
||||
|
||||
# 默认数据库名
|
||||
SQLITE_FILE="local_data"
|
||||
|
||||
# 从.env文件读取配置
|
||||
read_env_config() {
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
while IFS='=' read -r key value; do
|
||||
case "$key" in
|
||||
SQLITE_FILE)
|
||||
if [ -n "$value" ]; then
|
||||
SQLITE_FILE="$value"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done < "$ENV_FILE"
|
||||
fi
|
||||
|
||||
# 移除.sqlite3后缀
|
||||
SQLITE_FILE="${SQLITE_FILE%.sqlite3}"
|
||||
}
|
||||
|
||||
# 显示帮助
|
||||
show_help() {
|
||||
echo "监控模块数据库一键建表脚本"
|
||||
echo ""
|
||||
echo "用法: $0 [选项]"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " --help, -h 显示此帮助信息"
|
||||
echo " --db, -d 指定SQLite数据库文件名(不含.sqlite3后缀)"
|
||||
echo " --container, -c 指定MyAPS API容器名称 (默认: $CONTAINER_NAME)"
|
||||
echo " --dry-run, -n 仅显示将要执行的操作,不实际执行"
|
||||
echo " --local, -l 在本地直接执行(不通过容器)"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " # 使用默认配置"
|
||||
echo " ./setup_monitor_tables.sh"
|
||||
echo ""
|
||||
echo " # 指定数据库文件名"
|
||||
echo " ./setup_monitor_tables.sh -d my_data"
|
||||
echo ""
|
||||
echo " # 指定容器名称"
|
||||
echo " ./setup_monitor_tables.sh -c my_api_container"
|
||||
echo ""
|
||||
echo " # 本地执行(开发环境)"
|
||||
echo " ./setup_monitor_tables.sh -l"
|
||||
}
|
||||
|
||||
# 解析参数
|
||||
DRY_RUN=false
|
||||
LOCAL_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--help|-h)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
--db|-d)
|
||||
SQLITE_FILE="$2"
|
||||
shift
|
||||
;;
|
||||
--container|-c)
|
||||
CONTAINER_NAME="$2"
|
||||
shift
|
||||
;;
|
||||
--dry-run|-n)
|
||||
DRY_RUN=true
|
||||
;;
|
||||
--local|-l)
|
||||
LOCAL_MODE=true
|
||||
;;
|
||||
*)
|
||||
echo "未知选项: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 读取环境变量
|
||||
read_env_config
|
||||
|
||||
echo -e "${BLUE}==============================================${NC}"
|
||||
echo -e "${BLUE} 监控模块数据库一键建表脚本${NC}"
|
||||
echo -e "${BLUE}==============================================${NC}"
|
||||
|
||||
# 1. 检查SQL文件是否存在
|
||||
echo -e "\n${YELLOW}🔍 检查SQL文件...${NC}"
|
||||
if [ ! -f "$SQL_FILE" ]; then
|
||||
echo -e "${RED}❌ 错误: SQL文件不存在 - $SQL_FILE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ SQL文件存在: $SQL_FILE${NC}"
|
||||
|
||||
if [ "$LOCAL_MODE" = true ]; then
|
||||
# 本地模式执行
|
||||
echo -e "\n${YELLOW}⚙️ 本地模式执行...${NC}"
|
||||
|
||||
DB_PATH="${SCRIPT_DIR}/../../../storage/${SQLITE_FILE}.sqlite3"
|
||||
echo -e "${BLUE} 数据库文件: ${DB_PATH}${NC}"
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW} [模拟] sqlite3 ${DB_PATH} < ${SQL_FILE}${NC}"
|
||||
else
|
||||
# 确保storage目录存在
|
||||
mkdir -p "$(dirname "$DB_PATH")"
|
||||
|
||||
# 执行SQL脚本
|
||||
echo -e "${YELLOW} 执行SQL脚本...${NC}"
|
||||
sqlite3 "$DB_PATH" < "$SQL_FILE"
|
||||
|
||||
EXIT_CODE=$?
|
||||
if [ $EXIT_CODE -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ 建表成功${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ 建表失败 (退出码: $EXIT_CODE)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# 容器模式执行
|
||||
# 2. 检查容器是否存在
|
||||
echo -e "\n${YELLOW}🔍 检查MyAPS API容器状态...${NC}"
|
||||
if ! docker inspect "$CONTAINER_NAME" &>/dev/null; then
|
||||
echo -e "${RED}❌ 错误: 容器 $CONTAINER_NAME 不存在${NC}"
|
||||
echo -e "${RED} 请先启动MyAPS API容器${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查容器是否运行
|
||||
CONTAINER_STATUS=$(docker inspect -f '{{.State.Status}}' "$CONTAINER_NAME")
|
||||
if [ "$CONTAINER_STATUS" != "running" ]; then
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW}⚠️ [模拟] 容器未运行,将启动...${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ 容器未运行,正在启动...${NC}"
|
||||
docker start "$CONTAINER_NAME"
|
||||
sleep 5
|
||||
fi
|
||||
fi
|
||||
echo -e "${GREEN}✅ 容器 $CONTAINER_NAME 运行正常${NC}"
|
||||
|
||||
# 3. 执行建表
|
||||
echo -e "\n${YELLOW}⚙️ 执行建表脚本...${NC}"
|
||||
echo -e "${BLUE} 数据库文件: ${STORAGE_DIR}/${SQLITE_FILE}.sqlite3${NC}"
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW} [模拟] docker cp ${SQL_FILE} ${CONTAINER_NAME}:/tmp/monitor_tables.sql${NC}"
|
||||
echo -e "${YELLOW} [模拟] docker exec ${CONTAINER_NAME} sqlite3 ${STORAGE_DIR}/${SQLITE_FILE}.sqlite3 < /tmp/monitor_tables.sql${NC}"
|
||||
else
|
||||
# 复制SQL文件到容器
|
||||
echo -e "${YELLOW} 复制SQL文件到容器...${NC}"
|
||||
docker cp "$SQL_FILE" "$CONTAINER_NAME":/tmp/monitor_tables.sql
|
||||
|
||||
# 执行建表脚本
|
||||
echo -e "${YELLOW} 执行SQL脚本...${NC}"
|
||||
docker exec "$CONTAINER_NAME" sqlite3 "${STORAGE_DIR}/${SQLITE_FILE}.sqlite3" < /tmp/monitor_tables.sql
|
||||
|
||||
EXIT_CODE=$?
|
||||
if [ $EXIT_CODE -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ 建表成功${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ 建表失败 (退出码: $EXIT_CODE)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 清理容器内的临时文件
|
||||
docker exec "$CONTAINER_NAME" rm -f /tmp/monitor_tables.sql
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. 验证结果
|
||||
echo -e "\n${YELLOW}📊 验证建表结果...${NC}"
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW} [模拟] 验证表是否创建成功${NC}"
|
||||
else
|
||||
if [ "$LOCAL_MODE" = true ]; then
|
||||
TABLES=$(sqlite3 "$DB_PATH" "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;")
|
||||
else
|
||||
TABLES=$(docker exec "$CONTAINER_NAME" sqlite3 "${STORAGE_DIR}/${SQLITE_FILE}.sqlite3" "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;")
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ 创建的表:${NC}"
|
||||
echo "$TABLES" | while read -r table; do
|
||||
if [ -n "$table" ]; then
|
||||
echo -e " - $table"
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查版本记录
|
||||
if [ "$LOCAL_MODE" = true ]; then
|
||||
VERSION=$(sqlite3 "$DB_PATH" "SELECT version FROM schema_version ORDER BY applied_at DESC LIMIT 1;")
|
||||
else
|
||||
VERSION=$(docker exec "$CONTAINER_NAME" sqlite3 "${STORAGE_DIR}/${SQLITE_FILE}.sqlite3" "SELECT version FROM schema_version ORDER BY applied_at DESC LIMIT 1;")
|
||||
fi
|
||||
if [ -n "$VERSION" ]; then
|
||||
echo -e "\n${GREEN}✅ 版本记录: $VERSION${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}==============================================${NC}"
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW}⚠️ 模拟完成,未执行实际操作${NC}"
|
||||
else
|
||||
echo -e "${GREEN}🎉 建表完成!${NC}"
|
||||
fi
|
||||
echo -e "${BLUE}==============================================${NC}"
|
||||
echo -e "\n${YELLOW}💡 验证命令:${NC}"
|
||||
if [ "$LOCAL_MODE" = true ]; then
|
||||
echo -e "${YELLOW} sqlite3 ${DB_PATH}${NC}"
|
||||
else
|
||||
echo -e "${YELLOW} docker exec -it ${CONTAINER_NAME} sqlite3 ${STORAGE_DIR}/${SQLITE_FILE}.sqlite3${NC}"
|
||||
fi
|
||||
echo -e "${YELLOW} SELECT * FROM schema_version;${NC}"
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
#!/bin/bash
|
||||
# ==============================================
|
||||
# PostgreSQL 缓冲表一键建表脚本
|
||||
# 使用方法: ./setup_staging_tables.sh [选项]
|
||||
# 功能: 向PostgreSQL容器执行建表SQL脚本
|
||||
# ==============================================
|
||||
|
||||
set -e
|
||||
|
||||
# 配置
|
||||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
SQL_FILE="${SCRIPT_DIR}/staging_tables.sql"
|
||||
ENV_FILE="${SCRIPT_DIR}/../../.env"
|
||||
CONTAINER_NAME="myaps_postgres"
|
||||
|
||||
# 默认数据库名
|
||||
DB_NAME=""
|
||||
|
||||
# 从.env文件读取数据库配置
|
||||
read_env_config() {
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
while IFS='=' read -r key value; do
|
||||
case "$key" in
|
||||
THIS_DB_HOST) DB_HOST="$value" ;;
|
||||
THIS_DB_PORT) DB_PORT="$value" ;;
|
||||
THIS_DB_USER) DB_USER="$value" ;;
|
||||
THIS_DB_PASSWORD) DB_PASSWORD="$value" ;;
|
||||
THIS_DB_NAME) DB_NAME="$value" ;;
|
||||
esac
|
||||
done < "$ENV_FILE"
|
||||
fi
|
||||
|
||||
# 设置默认值
|
||||
DB_HOST=${DB_HOST:-localhost}
|
||||
DB_PORT=${DB_PORT:-5432}
|
||||
DB_USER=${DB_USER:-postgres}
|
||||
}
|
||||
|
||||
# 显示帮助
|
||||
show_help() {
|
||||
echo "PostgreSQL 缓冲表一键建表脚本"
|
||||
echo ""
|
||||
echo "用法: $0 [选项]"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " --help, -h 显示此帮助信息"
|
||||
echo " --db, -d 指定数据库名称(必填)"
|
||||
echo " --container, -c 指定PostgreSQL容器名称 (默认: $CONTAINER_NAME)"
|
||||
echo " --dry-run, -n 仅显示将要执行的操作,不实际执行"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " # 使用默认配置"
|
||||
echo " ./setup_staging_tables.sh -d myaps_db"
|
||||
echo ""
|
||||
echo " # 指定容器名称"
|
||||
echo " ./setup_staging_tables.sh -d myaps_db -c my_postgres"
|
||||
echo ""
|
||||
echo " # 模拟执行"
|
||||
echo " ./setup_staging_tables.sh -d myaps_db -n"
|
||||
}
|
||||
|
||||
# 解析参数
|
||||
DRY_RUN=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--help|-h)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
--db|-d)
|
||||
DB_NAME="$2"
|
||||
shift
|
||||
;;
|
||||
--container|-c)
|
||||
CONTAINER_NAME="$2"
|
||||
shift
|
||||
;;
|
||||
--dry-run|-n)
|
||||
DRY_RUN=true
|
||||
;;
|
||||
*)
|
||||
echo "未知选项: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 检查数据库名称是否指定
|
||||
if [ -z "$DB_NAME" ]; then
|
||||
echo -e "${RED}❌ 错误: 必须使用 -d 指定数据库名称${NC}"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 读取环境变量
|
||||
read_env_config
|
||||
|
||||
echo -e "${BLUE}==============================================${NC}"
|
||||
echo -e "${BLUE} PostgreSQL 缓冲表一键建表脚本${NC}"
|
||||
echo -e "${BLUE}==============================================${NC}"
|
||||
|
||||
# 1. 检查SQL文件是否存在
|
||||
echo -e "\n${YELLOW}🔍 检查SQL文件...${NC}"
|
||||
if [ ! -f "$SQL_FILE" ]; then
|
||||
echo -e "${RED}❌ 错误: SQL文件不存在 - $SQL_FILE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ SQL文件存在: $SQL_FILE${NC}"
|
||||
|
||||
# 2. 检查容器是否存在
|
||||
echo -e "\n${YELLOW}🔍 检查PostgreSQL容器状态...${NC}"
|
||||
if ! docker inspect "$CONTAINER_NAME" &>/dev/null; then
|
||||
echo -e "${RED}❌ 错误: 容器 $CONTAINER_NAME 不存在${NC}"
|
||||
echo -e "${RED} 请先启动PostgreSQL容器${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查容器是否运行
|
||||
CONTAINER_STATUS=$(docker inspect -f '{{.State.Status}}' "$CONTAINER_NAME")
|
||||
if [ "$CONTAINER_STATUS" != "running" ]; then
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW}⚠️ [模拟] 容器未运行,将启动...${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ 容器未运行,正在启动...${NC}"
|
||||
docker start "$CONTAINER_NAME"
|
||||
sleep 5
|
||||
fi
|
||||
fi
|
||||
echo -e "${GREEN}✅ 容器 $CONTAINER_NAME 运行正常${NC}"
|
||||
|
||||
# 3. 执行建表
|
||||
echo -e "\n${YELLOW}⚙️ 执行建表脚本...${NC}"
|
||||
echo -e "${BLUE} 数据库: ${DB_NAME}${NC}"
|
||||
echo -e "${BLUE} 用户: ${DB_USER}${NC}"
|
||||
echo -e "${BLUE} 端口: ${DB_PORT}${NC}"
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW} [模拟] docker exec -i $CONTAINER_NAME psql -U $DB_USER -d $DB_NAME -f - < $SQL_FILE${NC}"
|
||||
else
|
||||
# 检查数据库是否存在,不存在则创建
|
||||
echo -e "${YELLOW} 检查数据库是否存在...${NC}"
|
||||
if ! docker exec "$CONTAINER_NAME" psql -U "$DB_USER" -tAc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" | grep -q 1; then
|
||||
echo -e "${YELLOW} 数据库不存在,创建数据库...${NC}"
|
||||
docker exec "$CONTAINER_NAME" createdb -U "$DB_USER" "$DB_NAME"
|
||||
fi
|
||||
|
||||
# 执行建表脚本
|
||||
echo -e "${YELLOW} 执行SQL脚本...${NC}"
|
||||
cat "$SQL_FILE" | docker exec -i "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME"
|
||||
|
||||
EXIT_CODE=$?
|
||||
if [ $EXIT_CODE -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ 建表成功${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ 建表失败 (退出码: $EXIT_CODE)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. 验证结果
|
||||
echo -e "\n${YELLOW}📊 验证建表结果...${NC}"
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW} [模拟] 验证缓冲表是否创建成功${NC}"
|
||||
else
|
||||
TABLES=$(docker exec "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT tablename FROM pg_tables WHERE tablename LIKE '%staging' OR tablename IN ('t_validation_error', 't_transform_rule', 't_schema_version') ORDER BY tablename;")
|
||||
echo -e "${GREEN}✅ 创建的表:${NC}"
|
||||
echo "$TABLES" | while read -r table; do
|
||||
if [ -n "$table" ]; then
|
||||
echo -e " - $table"
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查版本记录
|
||||
VERSION=$(docker exec "$CONTAINER_NAME" psql -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT version FROM t_schema_version ORDER BY applied_at DESC LIMIT 1;")
|
||||
if [ -n "$VERSION" ]; then
|
||||
echo -e "\n${GREEN}✅ 版本记录: $VERSION${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}==============================================${NC}"
|
||||
if $DRY_RUN; then
|
||||
echo -e "${YELLOW}⚠️ 模拟完成,未执行实际操作${NC}"
|
||||
else
|
||||
echo -e "${GREEN}🎉 建表完成!${NC}"
|
||||
fi
|
||||
echo -e "${BLUE}==============================================${NC}"
|
||||
echo -e "\n${YELLOW}💡 验证命令:${NC}"
|
||||
echo -e "${YELLOW} docker exec -it $CONTAINER_NAME psql -U $DB_USER -d $DB_NAME${NC}"
|
||||
echo -e "${YELLOW} SELECT * FROM t_schema_version;${NC}"
|
||||
@@ -77,7 +77,8 @@ CREATE TABLE IF NOT EXISTS t_material_staging (
|
||||
DO $$
|
||||
BEGIN
|
||||
-- V001 新增字段示例(演示增量模式)
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 't_material_staging' AND column_name = 'free4') THEN
|
||||
-- 使用 pg_attribute 检查,支持大小写敏感的标识符
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 't_material_staging'::regclass AND LOWER(attname) = LOWER('Free4') AND NOT attisdropped) THEN
|
||||
ALTER TABLE t_material_staging ADD COLUMN "Free4" VARCHAR(255) NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
@@ -347,6 +348,7 @@ CREATE TABLE IF NOT EXISTS t_mat_wc_mold_staging (
|
||||
"BaseSec" INT NULL,
|
||||
"FixSec" INT NULL,
|
||||
"Priority" INT NULL,
|
||||
"Worker" FLOAT NULL,
|
||||
"Memo" VARCHAR(255) NULL
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user