sharding icon indicating copy to clipboard operation
sharding copied to clipboard

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

Open ChinaRedArmy1930 opened this issue 1 year ago • 0 comments

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 avatar Jul 24 '24 10:07 ChinaRedArmy1930