// migrate-sqlite-to-mysql 把历史 SQLite v8 数据一次性导入空的 MySQL 8 数据库。 package main import ( "flag" "fmt" "log" "cmautobuy/admin/config" "cmautobuy/admin/repository" ) func main() { sourcePath := flag.String("source", "", "历史 admin.db 路径(必填,只读打开)") dryRun := flag.Bool("dry-run", false, "只检查源库和空目标库,不写入") execute := flag.Bool("execute", false, "执行一次性迁移") verifyOnly := flag.Bool("verify-only", false, "只核对已迁移的 MySQL 与 SQLite") flag.Parse() if *sourcePath == "" { log.Fatal("必须提供 --source 指向历史 admin.db") } modeCount := 0 for _, enabled := range []bool{*dryRun, *execute, *verifyOnly} { if enabled { modeCount++ } } if modeCount != 1 { log.Fatal("必须且只能选择 --dry-run、--execute、--verify-only 其中一个") } source, err := repository.OpenLegacySQLiteReadOnly(*sourcePath) if err != nil { log.Fatal(err) } defer source.Close() databaseConfig, err := config.LoadDatabase() if err != nil { log.Fatalf("读取 MySQL 配置失败: %v", err) } target, err := repository.OpenMySQL(databaseConfig) if err != nil { log.Fatal(err) } defer target.Close() if err := repository.MigrateMySQL(target); err != nil { log.Fatalf("准备 MySQL schema 失败: %v", err) } var summary *repository.SQLiteMigrationSummary switch { case *verifyOnly: summary, err = repository.VerifySQLiteToMySQL(source, target) case *dryRun: summary, err = repository.MigrateSQLiteToMySQL(source, target, true) default: summary, err = repository.MigrateSQLiteToMySQL(source, target, false) } if err != nil { log.Fatal(err) } mode := "迁移完成并核对通过" if *dryRun { mode = "演练检查通过,未写入数据" } else if *verifyOnly { mode = "迁移数据核对通过,未写入数据" } fmt.Println(mode) for _, table := range repository.SortedMigrationSummary(summary) { fmt.Printf("%-28s %d\n", table.Name, table.Count) } }