#!/usr/bin/env bash
|
# ─────────────────────────────────────────────────────────────────────────────
|
# JNPF PostgreSQL schema 初始化(全新空库专用)
|
# 1) 建四库 jnpf_init / jnpf_flow / jnpf_xxljob / nacos_config
|
# 2) 跑官方初始化脚本(结构,无业务数据)
|
# 3) 跑自建表 DDL self_built_tables_pg.sql
|
# 4) 跑数据接口修正 data_interface_pg_fixes.sql(此刻空表→幂等 no-op,数据迁移后由 migrate-data.sh 再放一次)
|
# 5) 建 Nacos 存储库 schema(nacos_config_pg.sql)
|
#
|
# 前置:cx-postgres 容器已由根 compose 拉起(安全基线随根 compose,本脚本不再部署容器):
|
# docker volume create postgres_pgdata # 全新机器
|
# docker compose up -d cx-postgres # 在仓库根 / 离线交付包根目录执行
|
#
|
# 安全守卫:目标库已存在且含表时**拒绝执行**(官方 init 含 DROP TABLE IF EXISTS,
|
# 重放会清空既有数据);确需重灌请显式 FORCE_RESEED=1。
|
#
|
# 用法:
|
# ./install.sh # 建库 + 建表(= schema)
|
# ./install.sh schema # 同上(兼容旧参数写法)
|
#
|
# 参数(环境变量,默认=现场标准值):
|
# CONTAINER PG 容器名 默认 cx-postgres
|
# PGUSER 超级用户 默认 postgres(exec psql 走容器本地 trust,无需密码)
|
# DB_INIT / DB_FLOW / DB_XXLJOB / DB_NACOS 四库名(测试时可改 *_t8 隔离)
|
# CREATE_EXTENSIONS 是否建常用扩展(1/0),默认 1(非致命,失败仅告警)
|
# FORCE_RESEED 目标库非空时仍强制重灌(1/0),默认 0
|
# ─────────────────────────────────────────────────────────────────────────────
|
set -euo pipefail
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SQL_DIR="$SCRIPT_DIR/sql"
|
|
CONTAINER="${CONTAINER:-cx-postgres}"
|
PGUSER="${PGUSER:-postgres}"
|
DB_INIT="${DB_INIT:-jnpf_init}"
|
DB_FLOW="${DB_FLOW:-jnpf_flow}"
|
DB_XXLJOB="${DB_XXLJOB:-jnpf_xxljob}"
|
DB_NACOS="${DB_NACOS:-nacos_config}"
|
CREATE_EXTENSIONS="${CREATE_EXTENSIONS:-1}"
|
FORCE_RESEED="${FORCE_RESEED:-0}"
|
STEP="${1:-schema}"
|
|
log() { printf '\033[1;34m[install]\033[0m %s\n' "$*"; }
|
warn() { printf '\033[1;33m[install][warn]\033[0m %s\n' "$*"; }
|
die() { printf '\033[1;31m[install][err]\033[0m %s\n' "$*" >&2; exit 1; }
|
|
# 在容器内跑 psql(本地 unix socket,postgres 超级用户 trust,无需密码/端口)
|
psql_exec() { docker exec -i "$CONTAINER" psql -U "$PGUSER" "$@"; }
|
|
# 等 PG 进程就绪(首次 initdb 数十秒)。此阶段容器健康检查 unhealthy 属预期——
|
# 它探测的业务库正是本脚本要创建的,healthy 只会出现在本脚本成功之后
|
for _i in $(seq 1 60); do
|
if docker exec "$CONTAINER" pg_isready -qU "$PGUSER" 2>/dev/null; then break; fi
|
[ "$_i" = 60 ] && { echo "错误:等待 PG 就绪超时(docker logs $CONTAINER 查看)" >&2; exit 1; }
|
sleep 2
|
done
|
# 把宿主 SQL 文件喂给容器内 psql,遇错即停
|
run_sql_file() {
|
local db="$1" file="$2"
|
[ -f "$file" ] || die "缺 SQL 文件:${file}(git 拉码路线:先跑 ./assemble-sql-onsite.sh;离线包路线:包内 sql/ 应已组装,联系构建机)"
|
log "→ [$db] 执行 $(basename "$file") ($(du -h "$file" | cut -f1))"
|
psql_exec -d "$db" -v ON_ERROR_STOP=1 -q -f - < "$file"
|
}
|
db_exists() { psql_exec -tAc "SELECT 1 FROM pg_database WHERE datname='$1'" | grep -q 1; }
|
create_db() {
|
local db="$1"
|
if db_exists "$db"; then
|
warn "库 $db 已存在,跳过 CREATE DATABASE(幂等)"
|
else
|
log "创建库 $db"
|
psql_exec -d postgres -v ON_ERROR_STOP=1 -c "CREATE DATABASE \"$db\" ENCODING 'UTF8'"
|
fi
|
}
|
# 只数 BASE TABLE(排除 pg_stat_statements 等扩展视图,计数不受 CREATE_EXTENSIONS 影响)
|
table_count() { psql_exec -tAc "SELECT count(*) FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'" -d "$1"; }
|
# 全新 schema 基线:官方 293 张表 + 自建 99 张表(含 DMS V2.3 十表及文件对象映射表)。
|
verify_init_table_count() {
|
local init_table_count init_custom_table_count
|
init_table_count="$(table_count "$DB_INIT")"
|
init_custom_table_count=$((init_table_count - 293))
|
if [ "$init_table_count" -ne 392 ] || [ "$init_custom_table_count" -ne 99 ]; then
|
die "表数核对失败:$DB_INIT 共 ${init_table_count} 张 BASE TABLE,自建表 ${init_custom_table_count} 张;期望总数 392 张、自建 99 张"
|
fi
|
}
|
# 非空守卫:init SQL 含 DROP TABLE IF EXISTS,对已有数据的库重放=清库
|
guard_empty() {
|
local db="$1" n
|
db_exists "$db" || return 0
|
n="$(table_count "$db")"
|
[ "$n" -eq 0 ] && return 0
|
if [ "$FORCE_RESEED" = "1" ]; then
|
warn "库 $db 已有 $n 张表,FORCE_RESEED=1 → 继续重灌(既有数据将被 init 脚本覆盖/清空)"
|
else
|
die "库 $db 已有 $n 张表——本脚本只用于全新空库(init 含 DROP TABLE,重放会清数据)。确需重灌:FORCE_RESEED=1 ./install.sh"
|
fi
|
}
|
|
# ── schema:建库 + 官方 init + 自建表 + 数据接口修正 + Nacos 存储库 ──────────
|
do_schema() {
|
docker inspect "$CONTAINER" >/dev/null 2>&1 \
|
|| die "容器 $CONTAINER 不在——先在仓库根/交付包根目录:docker volume create postgres_pgdata && docker compose up -d cx-postgres"
|
|
log "===== 非空守卫 ====="
|
guard_empty "$DB_INIT"; guard_empty "$DB_FLOW"; guard_empty "$DB_XXLJOB"; guard_empty "$DB_NACOS"
|
|
log "===== 建四库 ====="
|
create_db "$DB_INIT"; create_db "$DB_FLOW"; create_db "$DB_XXLJOB"; create_db "$DB_NACOS"
|
|
if [ "$CREATE_EXTENSIONS" = "1" ]; then
|
log "建常用扩展(非致命)"
|
for ext in pg_stat_statements pg_trgm pgcrypto pg_bigm vector; do
|
psql_exec -d "$DB_INIT" -c "CREATE EXTENSION IF NOT EXISTS \"$ext\"" >/dev/null 2>&1 \
|
&& log " ext $ext ✓" || warn " ext $ext 跳过(镜像未含或无需)"
|
done
|
fi
|
|
log "===== 官方初始化脚本 ====="
|
run_sql_file "$DB_INIT" "$SQL_DIR/jnpf_dbnull_init.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/Update_PostgreSQL_1127.sql"
|
run_sql_file "$DB_FLOW" "$SQL_DIR/jnpf_flow_init.sql"
|
run_sql_file "$DB_XXLJOB" "$SQL_DIR/jnpf_xxljob_init.sql"
|
|
log "===== 自建表 DDL ====="
|
run_sql_file "$DB_INIT" "$SQL_DIR/self_built_tables_pg.sql"
|
|
log "===== 自建表增量(迁移快照后的列级对齐,幂等)====="
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_huanjing_20260717.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_sxt_wendingxing_20260717.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_sxt_wendingxing_20260720.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_sxt_flow_biz_status_20260719.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_sxt_quyang_zhongzhi_shenqing_biz_status_20260723.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_sxt_quyang_zhongzhi_shenqing_qingyandan_link_20260723.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_sxt_plan_status_20260720.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_lims_wendingxing_biangeng_20260720.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/create_lims_sxt_quyang_jihua_renwu_20260724.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/alter_lims_sxt_quyang_jihua_renwu_jianyan_xiang_kuaizhao_20260724.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/create_audit_events_ext_20260724.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/create_audit_events_20260724.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_audit_events_title_entry_20260810.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_audit_events_ingest_merge_20260818.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/repair_audit_events_integrity_20260824.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/create_dms_permission_v2_2_20260815.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/upgrade_dms_permission_v2_2_to_v2_3_20260817.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/create_dms_file_objects_20260817.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/upgrade_dms_file_properties_20260820.sql"
|
run_sql_file "$DB_INIT" "$SQL_DIR/update_audit_events_target_timeline_index_20260823.sql"
|
|
log "===== 数据接口修正(空表幂等,数据迁移后 migrate-data.sh 再放一次)====="
|
run_sql_file "$DB_INIT" "$SQL_DIR/data_interface_pg_fixes.sql"
|
|
log "===== Nacos 存储库 schema ====="
|
run_sql_file "$DB_NACOS" "$SQL_DIR/nacos_config_pg.sql"
|
|
log "===== 表数核对 ====="
|
verify_init_table_count
|
log " $DB_INIT BASE TABLE = $(table_count "$DB_INIT") (期望 392:官方293 + 自建99,含 DMS V2.3 十表和文件对象映射表)"
|
log " $DB_FLOW BASE TABLE = $(table_count "$DB_FLOW") (期望 70)"
|
log " $DB_XXLJOB BASE TABLE = $(table_count "$DB_XXLJOB") (期望 11)"
|
log " $DB_NACOS BASE TABLE = $(table_count "$DB_NACOS") (期望 12)"
|
log "schema 就绪。下一步:停机窗口跑 ./migrate-data.sh 迁数据;Nacos 配置内容按 docs/archive/server-pg-cutover-checklist.md SW-7 导入。"
|
}
|
|
case "$STEP" in
|
schema) do_schema ;;
|
container|all) die "步骤 '$STEP' 已废弃:PG 容器统一由根 compose 拉起(docker compose up -d cx-postgres),本脚本只做 schema" ;;
|
*) die "未知步骤 '$STEP'(仅支持 schema)" ;;
|
esac
|
log "install.sh [$STEP] 完成 ✓"
|