| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- #!/bin/bash
- #
- # gen-model.sh — 基于自定义 goctl 模板生成 model 代码
- #
- # 用法:
- # ./gen-model.sh ddl -src <sql文件> [-table <表1,表2,...>]
- # ./gen-model.sh datasource -url <DSN> -table <表1,表2,...>
- #
- # 示例:
- # ./gen-model.sh ddl -src perms.sql # 从 DDL 生成所有表
- # ./gen-model.sh ddl -src perms.sql -table sys_user,sys_role # 从 DDL 生成指定表
- # ./gen-model.sh datasource \
- # -url 'root:123456@tcp(127.0.0.1:3306)/mydb' \
- # -table sys_user,sys_role # 从数据库生成指定表
- #
- # 表名到目录的映射规则:
- # 去掉 sys_ 前缀,再去掉下划线。如 sys_role_perm -> roleperm
- # 生成目录: internal/model/<pkg>/
- # 文件风格: 小驼峰 (--style goZero)
- set -euo pipefail
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
- TEMPLATE_HOME="$SCRIPT_DIR/cli/goctl"
- MODEL_BASE_DIR="$SCRIPT_DIR/internal/model"
- STYLE="goZero"
- # ---- 工具函数 ----
- # 表名 -> 包名/目录名
- # sys_user -> user, sys_role_perm -> roleperm, sys_product_member -> productmember
- table_to_pkg() {
- local table="$1"
- local name="${table#sys_}"
- echo "${name//_/}"
- }
- # 从 SQL 文件中拆分出每张表的独立 DDL
- # 输出: 临时目录路径(包含 <表名>.sql 文件)
- split_ddl() {
- local sql_file="$1"
- local tmp_dir
- tmp_dir=$(mktemp -d)
- local current_table=""
- local outfile=""
- local printing=0
- while IFS= read -r line; do
- if echo "$line" | grep -qE "(DROP TABLE IF EXISTS|CREATE TABLE IF NOT EXISTS|CREATE TABLE)"; then
- current_table=$(echo "$line" | sed "s/.*\`\([^\`]*\)\`.*/\1/")
- outfile="$tmp_dir/${current_table}.sql"
- printing=1
- echo "$line" > "$outfile"
- elif [[ $printing -eq 1 ]]; then
- echo "$line" >> "$outfile"
- if echo "$line" | grep -qE "^\).*ENGINE" ; then
- printing=0
- fi
- fi
- done < "$sql_file"
- echo "$tmp_dir"
- }
- # 从 DDL 文件生成单张表的 model
- gen_from_ddl() {
- local ddl_file="$1"
- local table_name="$2"
- local pkg
- pkg=$(table_to_pkg "$table_name")
- local out_dir="$MODEL_BASE_DIR/$pkg"
- mkdir -p "$out_dir"
- echo " [$table_name] -> $out_dir/"
- goctl model mysql ddl \
- -src "$ddl_file" \
- -dir "$out_dir" \
- -c \
- --home "$TEMPLATE_HOME" \
- --style "$STYLE"
- }
- # 从数据库连接生成单张表的 model
- gen_from_datasource() {
- local url="$1"
- local table_name="$2"
- local pkg
- pkg=$(table_to_pkg "$table_name")
- local out_dir="$MODEL_BASE_DIR/$pkg"
- mkdir -p "$out_dir"
- echo " [$table_name] -> $out_dir/"
- goctl model mysql datasource \
- -url "$url" \
- -table "$table_name" \
- -dir "$out_dir" \
- -c \
- --home "$TEMPLATE_HOME" \
- --style "$STYLE"
- }
- # ---- 主流程 ----
- usage() {
- cat <<'EOF'
- 用法:
- ./gen-model.sh ddl -src <sql文件> [-table <表1,表2,...>]
- ./gen-model.sh datasource -url <DSN> -table <表1,表2,...>
- 选项:
- ddl 模式:
- -src SQL DDL 文件路径(必填)
- -table 要生成的表名,逗号分隔(可选,默认生成 SQL 中所有表)
- datasource 模式:
- -url MySQL DSN 连接串(必填),如 'root:pass@tcp(127.0.0.1:3306)/dbname'
- -table 要生成的表名,逗号分隔(必填)
- 示例:
- ./gen-model.sh ddl -src perm.sql
- ./gen-model.sh ddl -src perm.sql -table sys_user,sys_role
- ./gen-model.sh datasource -url 'root:123456@tcp(127.0.0.1:3306)/mydb' -table sys_user
- EOF
- exit 1
- }
- if [[ $# -lt 1 ]]; then
- usage
- fi
- MODE="$1"
- shift
- case "$MODE" in
- ddl)
- SRC=""
- TABLES=""
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -src) SRC="$2"; shift 2 ;;
- -table) TABLES="$2"; shift 2 ;;
- *) echo "未知选项: $1"; usage ;;
- esac
- done
- if [[ -z "$SRC" ]]; then
- echo "错误: ddl 模式必须指定 -src"
- usage
- fi
- # 支持相对路径
- if [[ "$SRC" != /* ]]; then
- SRC="$SCRIPT_DIR/$SRC"
- fi
- if [[ ! -f "$SRC" ]]; then
- echo "错误: SQL 文件不存在: $SRC"
- exit 1
- fi
- echo "拆分 DDL 文件: $SRC"
- TMP_DIR=$(split_ddl "$SRC")
- trap "rm -rf '$TMP_DIR'" EXIT
- # 获取拆分出的所有表名
- ALL_TABLES=()
- for f in "$TMP_DIR"/*.sql; do
- [[ -f "$f" ]] || continue
- ALL_TABLES+=("$(basename "$f" .sql)")
- done
- # 如果指定了 -table 则过滤
- if [[ -n "$TABLES" ]]; then
- IFS=',' read -ra FILTER <<< "$TABLES"
- TARGET_TABLES=()
- for t in "${FILTER[@]}"; do
- t="${t## }"; t="${t%% }"
- if [[ -f "$TMP_DIR/${t}.sql" ]]; then
- TARGET_TABLES+=("$t")
- else
- echo "警告: 表 '$t' 未在 SQL 文件中找到,跳过"
- fi
- done
- else
- TARGET_TABLES=("${ALL_TABLES[@]}")
- fi
- if [[ ${#TARGET_TABLES[@]} -eq 0 ]]; then
- echo "错误: 没有可生成的表"
- exit 1
- fi
- echo "即将生成 ${#TARGET_TABLES[@]} 张表: ${TARGET_TABLES[*]}"
- echo ""
- for t in "${TARGET_TABLES[@]}"; do
- gen_from_ddl "$TMP_DIR/${t}.sql" "$t"
- done
- echo ""
- echo "完成!共生成 ${#TARGET_TABLES[@]} 个 model。"
- ;;
- datasource)
- URL=""
- TABLES=""
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -url) URL="$2"; shift 2 ;;
- -table) TABLES="$2"; shift 2 ;;
- *) echo "未知选项: $1"; usage ;;
- esac
- done
- if [[ -z "$URL" ]]; then
- echo "错误: datasource 模式必须指定 -url"
- usage
- fi
- if [[ -z "$TABLES" ]]; then
- echo "错误: datasource 模式必须指定 -table"
- usage
- fi
- IFS=',' read -ra TARGET_TABLES <<< "$TABLES"
- echo "连接数据库..."
- echo "即将生成 ${#TARGET_TABLES[@]} 张表: ${TARGET_TABLES[*]}"
- echo ""
- for t in "${TARGET_TABLES[@]}"; do
- t="${t## }"; t="${t%% }"
- gen_from_datasource "$URL" "$t"
- done
- echo ""
- echo "完成!共生成 ${#TARGET_TABLES[@]} 个 model。"
- ;;
- *)
- echo "未知模式: $MODE"
- usage
- ;;
- esac
|