2026-08-15 17:18:00 +08:00
|
|
|
|
// Applies nl-pms-api/init.sql to MySQL.
|
|
|
|
|
|
// Usage (from view repo root):
|
|
|
|
|
|
//
|
|
|
|
|
|
// go run ./tools/applyinit -dsn "user:pass@tcp(host:3306)/"
|
|
|
|
|
|
//
|
|
|
|
|
|
// Or set MYSQL_DSN. Schema source of truth is ../nl-pms-api/init.sql.
|
2026-08-14 07:52:01 +08:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"database/sql"
|
2026-08-15 17:18:00 +08:00
|
|
|
|
"flag"
|
2026-08-14 07:52:01 +08:00
|
|
|
|
"fmt"
|
|
|
|
|
|
"os"
|
2026-08-15 07:29:45 +08:00
|
|
|
|
"path/filepath"
|
2026-08-14 07:52:01 +08:00
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-08-15 17:18:00 +08:00
|
|
|
|
func main() {
|
|
|
|
|
|
dsnFlag := flag.String("dsn", "", "MySQL DSN without database (or set MYSQL_DSN)")
|
|
|
|
|
|
sqlPath := flag.String("sql", "", "path to init.sql (default: ../nl-pms-api/init.sql)")
|
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
dsn := strings.TrimSpace(*dsnFlag)
|
|
|
|
|
|
if dsn == "" {
|
|
|
|
|
|
dsn = strings.TrimSpace(os.Getenv("MYSQL_DSN"))
|
2026-08-15 07:29:45 +08:00
|
|
|
|
}
|
2026-08-15 17:18:00 +08:00
|
|
|
|
if dsn == "" {
|
|
|
|
|
|
fmt.Fprintln(os.Stderr, "缺少 -dsn 或 MYSQL_DSN(例: root:root@tcp(127.0.0.1:3306)/)")
|
|
|
|
|
|
os.Exit(2)
|
2026-08-15 07:29:45 +08:00
|
|
|
|
}
|
2026-08-15 17:18:00 +08:00
|
|
|
|
if !strings.Contains(dsn, "multiStatements") {
|
|
|
|
|
|
if strings.Contains(dsn, "?") {
|
|
|
|
|
|
dsn += "&multiStatements=false&charset=utf8mb4"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dsn += "?multiStatements=false&charset=utf8mb4"
|
|
|
|
|
|
}
|
2026-08-15 07:29:45 +08:00
|
|
|
|
}
|
2026-08-15 17:18:00 +08:00
|
|
|
|
path := *sqlPath
|
|
|
|
|
|
if path == "" {
|
|
|
|
|
|
path = filepath.Join("..", "nl-pms-api", "init.sql")
|
2026-08-14 07:52:01 +08:00
|
|
|
|
}
|
2026-08-15 17:18:00 +08:00
|
|
|
|
raw, err := os.ReadFile(path)
|
2026-08-14 07:52:01 +08:00
|
|
|
|
if err != nil {
|
2026-08-15 17:18:00 +08:00
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
|
|
os.Exit(1)
|
2026-08-14 07:52:01 +08:00
|
|
|
|
}
|
2026-08-15 17:18:00 +08:00
|
|
|
|
db, err := sql.Open("mysql", dsn)
|
2026-08-14 07:52:01 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
panic(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
defer db.Close()
|
|
|
|
|
|
db.SetMaxOpenConns(1)
|
|
|
|
|
|
|
|
|
|
|
|
var kept []string
|
|
|
|
|
|
for _, line := range strings.Split(string(raw), "\n") {
|
|
|
|
|
|
if t := strings.TrimSpace(line); strings.HasPrefix(t, "--") {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
kept = append(kept, line)
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, stmt := range strings.Split(strings.Join(kept, "\n"), ";") {
|
|
|
|
|
|
s := strings.TrimSpace(stmt)
|
|
|
|
|
|
if s == "" {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if _, err := db.Exec(s); err != nil {
|
|
|
|
|
|
fmt.Println("ERR:", err, "stmt:", s[:min(80, len(s))])
|
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
var n int
|
2026-08-15 17:18:00 +08:00
|
|
|
|
if err := db.QueryRow("SELECT COUNT(*) FROM code_count.users").Scan(&n); err != nil {
|
2026-08-14 07:52:01 +08:00
|
|
|
|
fmt.Println("verify failed:", err)
|
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
|
}
|
2026-08-15 17:18:00 +08:00
|
|
|
|
fmt.Println("ok, users rows:", n, "sql:", path)
|
2026-08-14 07:52:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func min(a, b int) int {
|
|
|
|
|
|
if a < b {
|
|
|
|
|
|
return a
|
|
|
|
|
|
}
|
|
|
|
|
|
return b
|
|
|
|
|
|
}
|