create_schema.sh
5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/bin/bash
# 初始化 GaussDB 数据库:使用 GaussDB 的 gsql 客户端,创建 PG 兼容模式(DBCOMPATIBILITY = 'PG')、UTF8 编码的全新数据库,并导入 sql/opengauss 脚本
# GaussDB 已内置 dual 视图(sys.dual、pg_catalog.dual),导入时只跳过 sql/opengauss/ruoyi-vue-pro.sql 开头创建 dual 表的一段,不修改内置视图,其余 SQL 保持不变
# 数据库已存在(包括空库)时拒绝导入;任一步骤失败都以非零状态退出
# 执行:GAUSSDB_PORT=8000 GAUSSDB_USER='数据库账号' GAUSSDB_PASSWORD='数据库密码' bash sql/tools/gaussdb/create_schema.sh
set -euo pipefail
host="${GAUSSDB_HOST:-}" # 为空时,使用本机的 Unix Socket 连接
port="${GAUSSDB_PORT:?GAUSSDB_PORT 未设置,请设置为 GaussDB 的端口}"
user="${GAUSSDB_USER:?GAUSSDB_USER 未设置,请设置为具有 CREATEDB 权限的数据库账号}"
password="${GAUSSDB_PASSWORD:?GAUSSDB_PASSWORD 未设置,请设置为数据库账号的实际密码}"
maintenance_db="${GAUSSDB_MAINTENANCE_DB:-postgres}"
database="${GAUSSDB_DATABASE:-ruoyi-vue-pro}"
sql_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../opengauss" && pwd)"
if [[ ! "${database}" =~ ^[A-Za-z0-9_-]+$ ]]; then
echo "数据库名 ${database} 不合法,只允许字母、数字、下划线和中划线" >&2
exit 1
fi
if ! command -v gsql >/dev/null 2>&1; then
echo "未找到 gsql 客户端:请在安装了 GaussDB gsql 客户端的机器上执行,例如以数据库安装用户登录 GaussDB 服务器" >&2
exit 1
fi
client=(gsql -p "${port}" -U "${user}" -W "${password}" -X -q -v ON_ERROR_STOP=1)
if [ -n "${host}" ]; then
client+=(-h "${host}")
fi
# 1. 生成跳过 dual 段的临时脚本:只允许跳过「-- Table structure for dual」到其后第一个「-- @formatter:on」之间的 dual 建表、注释及插入语句
schema_file="$(mktemp)"
trap 'rm -f "${schema_file}"' EXIT
# 注释语句只允许单个字符串常量(内部的单引号写作 ''),字符串后只能是行尾的分号,避免同一行中的其它 SQL 被一起跳过
if ! awk -v q="'" '
BEGIN { comment = "^COMMENT ON TABLE dual IS " q "([^" q "]|" q q ")*" q ";$" }
/^-- Table structure for dual$/ { skipping = 1; blocks++ }
skipping {
if ($0 ~ /^(DROP TABLE IF EXISTS dual;|CREATE TABLE dual|INSERT INTO dual VALUES \(1\);)$/) {
statements++
} else if ($0 !~ /^(--.*|\(|[[:space:]]*id int2|\);)?$/ && $0 !~ comment) {
unexpected = 1
}
if ($0 ~ /^-- @formatter:on$/) {
skipping = 0
}
next
}
{ print }
END { exit (blocks == 1 && statements == 3 && !skipping && !unexpected) ? 0 : 1 }
' "${sql_dir}/ruoyi-vue-pro.sql" > "${schema_file}" \
|| grep -Eq '^(DROP TABLE IF EXISTS dual;|CREATE TABLE dual|INSERT INTO dual )' "${schema_file}"; then
echo "${sql_dir}/ruoyi-vue-pro.sql 中 dual 表一段的格式与预期不一致,拒绝导入;请检查脚本是否由 sql/tools/convertor.py 生成" >&2
exit 1
fi
# 2. 校验账号、密码及认证方式
if ! "${client[@]}" -d "${maintenance_db}" -c 'SELECT 1' >/dev/null; then
echo "无法使用账号 ${user} 登录 ${maintenance_db} 数据库:请检查 GAUSSDB_HOST、GAUSSDB_PORT、GAUSSDB_USER、GAUSSDB_PASSWORD,以及 gs_hba.conf 中该账号、客户端地址的认证配置" >&2
exit 1
fi
# 3. 校验 GaussDB 内置的 dual 视图:openGauss、MogDB 没有该视图,请直接导入 sql/opengauss 脚本
dual_count=$("${client[@]}" -d "${maintenance_db}" -At -c "SELECT COUNT(*) FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = 'dual' AND c.relkind = 'v' AND n.nspname IN ('sys', 'pg_catalog');")
if [ "${dual_count}" = "0" ]; then
echo "未检测到 GaussDB 内置的 dual 视图,拒绝导入:该脚本只适用于 GaussDB,openGauss、MogDB 请直接导入 sql/opengauss 脚本" >&2
exit 1
fi
# 4. 创建全新数据库:不判断是否存在,数据库已存在时直接失败,避免项目 SQL 中的 DROP TABLE 重建已有的同名表
# 注意:GaussDB 默认创建的是 A(Oracle)兼容模式的数据库,项目脚本需要使用 PG 兼容模式
if ! "${client[@]}" -d "${maintenance_db}" -c "CREATE DATABASE \"${database}\" ENCODING 'UTF8' DBCOMPATIBILITY = 'PG';"; then
echo "创建数据库 ${database} 失败:只允许初始化全新的数据库,数据库已存在(包括空库)时拒绝导入;如需重新初始化,请确认数据可以删除后,手动删除该数据库" >&2
exit 1
fi
compatibility=$("${client[@]}" -d "${database}" -At -c 'SHOW sql_compatibility;')
if [ "${compatibility}" != "PG" ]; then
echo "数据库 ${database} 的兼容模式为 ${compatibility},不是 PG,拒绝导入" >&2
exit 1
fi
# 5. 按 quartz、ruoyi-vue-pro 的顺序导入脚本(ON_ERROR_STOP 遇到错误立即退出,失败时保留数据库,便于排查)
"${client[@]}" -d "${database}" -f "${sql_dir}/quartz.sql"
"${client[@]}" -d "${database}" -f "${schema_file}"
# 只统计普通表、分区表;dual 使用 GaussDB 内置视图,不计入
table_count=$("${client[@]}" -d "${database}" -At -c "SELECT COUNT(*) FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = current_schema() AND c.relkind IN ('r', 'p');")
echo "GaussDB 初始化完成:数据库 ${database} 共 ${table_count} 张表"