初始化
This commit is contained in:
85
tools/applysql/main.go
Normal file
85
tools/applysql/main.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// applysql —— 开发辅助工具:把 SQL 文件应用到 z_xk 库
|
||||
//
|
||||
// 为什么需要它:Windows 开发机没有 mysql 客户端,而 Go 项目本身带着
|
||||
// GORM 依赖与 config.Load() 的 DSN 解析逻辑,直接复用即可执行 DDL,
|
||||
// 且凭据不经过命令行/控制台(从 manifest/config/config.yaml 读取)。
|
||||
//
|
||||
// 用法(必须在 nl-tcm-agent 项目根目录执行,保证能读到配置文件):
|
||||
// go run ./tools/applysql <sql文件1> [sql文件2 ...]
|
||||
//
|
||||
// 说明:
|
||||
// - 按 ";\n" 粗粒度拆分语句(我们自己的 SQL 文件都是规范的分号+换行结尾)
|
||||
// - "--" 开头的注释行会被剥掉
|
||||
// - 任一语句失败立即退出(DDL 顺序有依赖,跳过会导致后续更混乱)
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"tcm-agent/internal/config"
|
||||
"tcm-agent/internal/dao"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatal("用法: go run ./tools/applysql <sql文件...>")
|
||||
}
|
||||
cfg := config.Load()
|
||||
if cfg.DB.DSN == "" {
|
||||
log.Fatal("配置缺少 db.dsn(检查 manifest/config/config.yaml)")
|
||||
}
|
||||
if err := dao.Init(cfg.DB.DSN); err != nil {
|
||||
log.Fatalf("连接数据库失败: %v", err)
|
||||
}
|
||||
for _, path := range os.Args[1:] {
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Fatalf("读取 %s 失败: %v", path, err)
|
||||
}
|
||||
stmts := splitStatements(string(raw))
|
||||
fmt.Printf("== %s:%d 条语句 ==\n", path, len(stmts))
|
||||
for i, stmt := range stmts {
|
||||
if err := dao.DB.Exec(stmt).Error; err != nil {
|
||||
log.Fatalf("第 %d 条语句执行失败: %v\n语句片段: %.120s", i+1, err, stmt)
|
||||
}
|
||||
fmt.Printf(" [%d/%d] OK %.60s...\n", i+1, len(stmts), firstLine(stmt))
|
||||
}
|
||||
}
|
||||
fmt.Println("全部执行完成")
|
||||
}
|
||||
|
||||
// splitStatements 把 SQL 文本拆成可执行语句:剥注释行后按分号结尾切分
|
||||
func splitStatements(sqlText string) []string {
|
||||
// Windows 编辑器写出的文件是 CRLF,先统一成 LF,否则 ";\n" 切分匹配不到
|
||||
sqlText = strings.ReplaceAll(sqlText, "\r\n", "\n")
|
||||
var sb strings.Builder
|
||||
for _, line := range strings.Split(sqlText, "\n") {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
// 剥掉整行注释(字段内注释在行中不受影响)
|
||||
if strings.HasPrefix(trimmed, "--") || trimmed == "" {
|
||||
continue
|
||||
}
|
||||
sb.WriteString(line)
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
parts := strings.Split(sb.String(), ";\n")
|
||||
out := make([]string, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
p = strings.TrimSpace(p)
|
||||
if p != "" {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// firstLine 取语句首行用于进度展示
|
||||
func firstLine(stmt string) string {
|
||||
if i := strings.Index(stmt, "\n"); i > 0 {
|
||||
return stmt[:i]
|
||||
}
|
||||
return stmt
|
||||
}
|
||||
Reference in New Issue
Block a user