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

gorm的clone,导致中间件读取不到Statement的 Setting #166

Open
ChinaRedArmy1930 opened this issue Jul 24, 2024 · 0 comments
Open
Assignees

Comments

@ChinaRedArmy1930
Copy link

ChinaRedArmy1930 commented Jul 24, 2024

Your Question

开发代码的时候在外层设置了 gorm:table_options 代码如下:

db.Debug().Model(info).WithContext(context.TODO()).
		Set("gorm:table_options", " ENGINE=InnoDB DEFAULT CHARSET=utf8mb4  COLLATE=utf8_bin COMMENT='测试' "+
			"shardkey=f_userid").AutoMigrate(&info)

在 AutoMigrate, stmt中的 DB 拿到的 m.sharding.DB

stmt := &gorm.Statement{DB: m.sharding.DB}

跟了下代码, 发现这个 db是在 use的时候被设置的

db.Use(sharding.Register(sharding.Config{} ....)

现在遇到了这样的一个问题,我是想调用AutoMigrate接口进行建表, 但是我AutoMigrate代码是在 use 代码下面(示例代码参考最后), 如果我调用了任意一个 chainable_api,比如 Model(), 他内部调用getInstance, 那么由于初始化的时候 clone 为 1,那么就会重新生成一个新的 DB。

现在的问题是,use的时候使用了最开始的 DB, 一层一层的调用chainable_api,生成新的 DB,我在新的 DB 上的设置,老的 DB 完全不知道。 到真正AutoMigrate的时候,使用的是老的 DB。 结果发现设置的 gorm:table_options 根本没有生效。

这里目前导致了我在外面调用 Set 期望设置一下 gorm:table_options ,结果完全没有设置进去 。

The document you expected this should be explained

Expected answer

这里想知道这样设计的考虑是什么,以及有没有什么优雅的办法把 Set透传进去。

如果是先将 DB 全部都设置完,然后在调用 use,最后调用 AutoMigrate ,这样不知道行不行,但是感觉不太好,我们的代码中,use是放在了初始化那里, AutoMigrate 和其他的 Find Update 一样是单独的函数。

代码如下:

package main

import (
	"errors"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	glog "gorm.io/gorm/logger"
	"gorm.io/sharding"
	"hash/crc32"
	"time"
)

var dsn = "root:XXXXxxxx@tcp(xxxxxxx:3306)/xxxxx?charset=utf8mb4&parseTime=True&loc=Local"

func (*Test) TableName() string {
	return "TestTable"
}

type Test struct {
	Test string
}

type GormLogger struct {
}

func (g GormLogger) Printf(s string, i ...interface{}) {
	fmt.Printf(s, i...)
}

func test() {
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: glog.New(&GormLogger{}, glog.Config{
			SlowThreshold:             200 * time.Millisecond,
			LogLevel:                  glog.Warn,
			IgnoreRecordNotFoundError: false,
			Colorful:                  true,
		})})

	if err != nil {
		fmt.Printf("tdsql init failed, err: %v\n", err)
		return
	}
	db.Use(sharding.Register(sharding.Config{
		ShardingKey:    "test",
		NumberOfShards: 100,
		ShardingAlgorithm: func(columnValue any) (suffix string, err error) {
			if test, ok := columnValue.(string); ok {
				hash := crc32.ChecksumIEEE([]byte(test)) % 100
				return fmt.Sprintf("_%02d", hash), nil
			}
			return "", errors.New("invalid test")
		},
		PrimaryKeyGenerator: sharding.PKCustom,
		PrimaryKeyGeneratorFn: func(tableIdx int64) int64 {
			return 0
		},
		ShardingSuffixs: func() (suffixs []string) {
			numberOfShards := 100
			for i := 0; i < numberOfShards; i++ {
				suffixs = append(suffixs, fmt.Sprintf("_%02d", i%numberOfShards))
			}
			return
		},
	}, "TestTable"))

	info := &Test{}

	db.Model(info).
		Set("gorm:table_options", " ENGINE=InnoDB DEFAULT CHARSET=utf8mb4  COLLATE=utf8_bin COMMENT='测试' ").AutoMigrate(&info)
	if err != nil {
		return
	}
}

func main() {
	test()
}

@ChinaRedArmy1930 ChinaRedArmy1930 changed the title 中间件为什么AutoMigrate的时候新创建一个tx gorm的clone,导致中间件读取不到Statement的 Setting Jul 24, 2024
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

No branches or pull requests

2 participants