69 lines
2.4 KiB
Go
69 lines
2.4 KiB
Go
// 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
|
||
}
|