首页 > 解决方案 > 如何从 GORM 结构模型生成 SQL 代码?

问题描述

我正在使用 goose 来管理我的数据库迁移,但我需要直接在迁移文件中编写 SQL 语句。有没有办法直接从 GORM 模型生成 SQL?

标签: gogo-gorm

解决方案


不幸的是,使用该gorm.Session{DryRun: true}选项不会像使用普通查询那样使调用者可以使用迁移 SQL 语句。

我现在能看到的唯一方法是通过重新实现gorm.io/gorm/logger.Interface接口来捕获迁移运行的 SQL。具体来说,Trace方法。

type Interface interface {
    LogMode(LogLevel) Interface
    Info(context.Context, string, ...interface{})
    Warn(context.Context, string, ...interface{})
    Error(context.Context, string, ...interface{})
    Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error)
}

在内部Trace,您可以调用该fc函数参数来获取 SQL 和RowsAffected,您可以随心所欲地使用它。

例如:

import (
    "time"
    "context"
    "gorm.io/gorm/logger"
)

type RecorderLogger struct {
    logger.Interface
    Statements []string
}

func (r *RecorderLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
    sql, _ := fc()
    r.Statements = append(r.Statements, sql)
}

现在将其用作:

recorder := RecorderLogger{logger.Default.LogMode(logger.Info)}
session := db.Session(&gorm.Session{
    Logger: &recorder
})
session.AutoMigrate(&Model{}, ...)
// or 
session.Migrator().CreateTable(&Model{}, ...) // or any method therein
// now recorder.Statements contains the statements run during migration

这非常 hacky,您可能会遇到问题,因为AutoMigrate修改了数据库的当前状态并将其迁移到您的模型所需的(直到某一点),并且要使其正常工作,您当前的数据库必须反映您的生产的当前状态数据库(或您希望迁移的任何数据库)。因此,如果您小心的话,您可以构建该工具来帮助您启动迁移脚本,但要正确获得迁移系统的优势,就像goose您需要使用 SQL 一样:)


推荐阅读