#!/bin/bash # # gen-model.sh — 基于自定义 goctl 模板生成 model 代码 # # 用法: # ./gen-model.sh ddl -src [-table <表1,表2,...>] # ./gen-model.sh datasource -url -table <表1,表2,...> # # 示例: # ./gen-model.sh ddl -src nomo.sql # 从 DDL 生成所有表 # ./gen-model.sh ddl -src nomo.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// # 文件风格: 小驼峰 (--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 [-table <表1,表2,...>] ./gen-model.sh datasource -url -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