Files

69 lines
2.4 KiB
Go
Raw Permalink Normal View History

2026-08-14 13:17:03 +08:00
// dev 环境自动建表(仅 go run 生效)
//
// 安全约定表结构迁移只允许发生在开发模式go run 启动)。
// go build 打包出的二进制启动时绝不会执行任何迁移——生产库的结构
// 变更一律通过 sql/ 目录下的脚本人工执行,防止 GORM 自动改表出问题。
//
// dev 下也只做最保守的一件事:补建"库里不存在的表"。
// 已存在的表一律不动(不加列、不加索引),因为手写 SQL 的索引命名
// uk_username 等)与 GORM 默认命名不同,全量 AutoMigrate 会重复建索引。
package database
import (
"log"
"os"
"strings"
"nl-game-api-gin/internal/model"
)
// IsDevRun 判断当前进程是否由 go run 启动:
// go run 会先把临时二进制编译到 go-build 缓存目录(如 %TEMP%\go-buildXXXX再运行
// 而 go build 的产物路径不含该特征,因此打包后的服务永远不会命中 dev 分支。
func IsDevRun() bool {
exe, err := os.Executable()
if err != nil {
return false
}
return strings.Contains(exe, "go-build")
}
// AutoMigrateMissing 遍历全部 GORM 模型,为缺失的表建表(含索引),已存在的表跳过。
// 新增 model 后在下方清单登记一行dev 启动即可自动建表;种子数据仍需执行对应 SQL 脚本。
func AutoMigrateMissing() error {
models := []interface{ TableName() string }{
// 用户与登录
&model.User{}, &model.LoginLog{},
// 游戏与对局记录
&model.Game{}, &model.GameRecord{}, &model.BattleRecord{},
// 积分与签到
&model.PointRecord{}, &model.SignIn{},
// 商城:购物车 / 订单 / 已购游戏 / 道具
&model.Cart{}, &model.Order{}, &model.OrderItem{}, &model.UserGame{}, &model.Prop{}, &model.UserProp{},
// 社交:好友 / 私聊
&model.Friend{}, &model.ChatMessage{},
// 主题与站点配置
&model.Theme{}, &model.SiteConfig{},
// VIP 等级
&model.VipLevel{},
// 关卡进度 / 云存档 / 皮肤
&model.GameProgress{}, &model.GameSave{},
&model.GameSkin{}, &model.UserSkin{},
}
created := 0
for _, m := range models {
if DB.Migrator().HasTable(m) {
continue
}
if err := DB.Migrator().CreateTable(m); err != nil {
return err
}
created++
log.Printf("[dev迁移] 已创建缺失表 %s种子数据请执行 sql/ 对应脚本)", m.TableName())
}
if created == 0 {
log.Println("[dev迁移] 全部表已存在,无需创建")
}
return nil
}