Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修复在Migrate中,且db.DryRun=true时,GetColumnComment方法因获取不到当前库名而报错 #28

Merged
merged 1 commit into from
Feb 10, 2025

Conversation

websoe
Copy link
Contributor

@websoe websoe commented Feb 8, 2025

Bug场景与原因

有表改动(例如string型字段长度变化)时, 需要执行db.AutoMigrate(...).
在交互式的命令行程序中,一般设置db.DryRun = true并执行db.AutoMigrate(...), 先打印出SQL语句, 人为确认没啥问题后, 重设db.DryRun = false再次执行db.AutoMigrate(...).

本库中的Migrator.CurrentDatabase()方法在db.DryRun = true时, 因不实际执行查询逻辑而报错并奔溃, 日志如下:

2025-02-08T18:25:35+08:00       ERROR   dry run mode unsupported
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0xdafe29]

goroutine 1 [running]:
database/sql.(*Row).Scan(0xc0000a8c00?, {0xc00083b448?, 0x30?, 0x0?})
        D:/Go/src/database/sql/sql.go:3443 +0x29
github.com/godoes/gorm-dameng.Migrator.CurrentDatabase({{{0x1, 0xc0000a8a50, {0x2143070, 0xc000793040}}}, {0xc000793040}})
        F:/goproject/gorm-dameng/migrator.go:64 +0x93
github.com/godoes/gorm-dameng.Migrator.GetColumnComment({{{0x1, 0xc0000a8a50, {0x2143070, 0xc000793040}}}, {0xc000793040}}, 0xc000685180, {0xc00078dff8, 0x2})
        F:/goproject/gorm-dameng/migrator.go:242 +0x119
github.com/godoes/gorm-dameng.Migrator.MigrateColumn.func1(0xc000685180)
        F:/goproject/gorm-dameng/migrator.go:380 +0x4d
gorm.io/gorm/migrator.Migrator.RunWithValue({{0xa8?, 0xc0000a8a50?, {0x2143070?, 0xc000793040?}}}, {0x1ac1460, 0xc0007b6900}, 0xc00083b6e0)
        F:/gopath/pkg/mod/gorm.io/gorm@v1.25.12/migrator/migrator.go:74 +0x12b
github.com/godoes/gorm-dameng.Migrator.MigrateColumn({{{0x1, 0xc0000a8a50, {0x2143070, 0xc000793040}}}, {0xc000793040}}, {0x1ac1460, 0xc0007b6900}, 0xc00080c600, {0x2148878, 0xc0000d4410})
        F:/goproject/gorm-dameng/migrator.go:379 +0xb0f
gorm.io/gorm/migrator.Migrator.AutoMigrate.func1(0xc0006841c0)
        F:/gopath/pkg/mod/gorm.io/gorm@v1.25.12/migrator/migrator.go:161 +0x265
gorm.io/gorm/migrator.Migrator.RunWithValue({{0xa0?, 0xc0007ed170?, {0x2143070?, 0xc000793040?}}}, {0x1ac1460, 0xc0007b6900}, 0xc00083bb28)
        F:/gopath/pkg/mod/gorm.io/gorm@v1.25.12/migrator/migrator.go:74 +0x12b
gorm.io/gorm/migrator.Migrator.AutoMigrate({{0x0?, 0xc0007ed170?, {0x2143070?, 0xc000793040?}}}, {0xc0007faf20?, 0xc000055c28?, 0x7c1e7b?})
        F:/gopath/pkg/mod/gorm.io/gorm@v1.25.12/migrator/migrator.go:129 +0x196
github.com/godoes/gorm-dameng.Migrator.AutoMigrate({{{0x1, 0xc0007ed170, {0x2143070, 0xc000793040}}}, {0xc000793040}}, {0xc0007faf20, 0x1, 0x0?})
        F:/goproject/gorm-dameng/migrator.go:33 +0x7a
gorm.io/gorm.(*DB).AutoMigrate(0x7f9a0b?, {0xc0007faf20, 0x1, 0x1})
        F:/gopath/pkg/mod/gorm.io/gorm@v1.25.12/migrator.go:24 +0x42

一般情况下gorm官方对DryRun有相应的处理逻辑:

// go-gorm: /migrator/migrator.go 第123行
func (m Migrator) GetQueryAndExecTx() (queryTx, execTx *gorm.DB) {
	queryTx = m.DB.Session(&gorm.Session{})
	execTx = queryTx
	if m.DB.DryRun {
		queryTx.DryRun = false
		execTx = m.DB.Session(&gorm.Session{Logger: &printSQLLogger{Interface: m.DB.Logger}})
	}
	return queryTx, execTx
}

// AutoMigrate auto migrate values
func (m Migrator) AutoMigrate(values ...interface{}) error {
	for _, value := range m.ReorderModels(values, true) {
		queryTx, execTx := m.GetQueryAndExecTx()
		... ...

分场景使用 db session: queryTxexecTx, 在执行信息查询时使用queryTx, 在执行表结构调整时使用execTx.
本库的Migrator.MigrateColumn()方法中, 使用默认session:execTx 间接调用Migrator.CurrentDatabase()查询当前库名, 因此会报错并奔溃.

解决方案

方案一: 在内部方法Migrator.GetColumnComment()中不直接调用Migrator.CurrentDatabase(), 改成使用queryTx直接查询出当前库名. 详情见本次提交的代码改动

方案二: 修改Migrator.CurrentDatabase()方法, 创建并使用queryTx来查询当前库名. 如下所示:

func (m Migrator) CurrentDatabase() (name string) {
	queryTx := m.DB.Session(&gorm.Session{Logger: m.DB.Logger.LogMode(logger.Warn)})
	if m.DB.DryRun {
		queryTx.DryRun = false
	}
	_ = queryTx.Raw("SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA');").Row().Scan(&name)
	return
}

@iTanken iTanken merged commit 66da4f8 into godoes:main Feb 10, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants