Skip to content

dbresolver config "Policy" is never nil #154

@yydr314

Description

@yydr314

Description

The current dbresolver configuration has an incorrect default value for the policy, which causes read operations to use the sources instead of the replicas when setting up read-write splitting according to the official documentation. The original code is as follows:

type Config struct {
	Sources           []gorm.Dialector
	Replicas          []gorm.Dialector
	Policy            Policy
	datas             []interface{}
	TraceResolverMode bool
}

func Register(config Config, datas ...interface{}) *DBResolver {
	return (&DBResolver{}).Register(config, datas...)
}

func (dr *DBResolver) Register(config Config, datas ...interface{}) *DBResolver {
	if dr.prepareStmtStore == nil {
		dr.prepareStmtStore = map[gorm.ConnPool]*gorm.PreparedStmtDB{}
	}

	if dr.resolvers == nil {
		dr.resolvers = map[string]*resolver{}
	}

	if config.Policy == nil {
		config.Policy = RandomPolicy{}
	}

	config.datas = datas
	dr.configs = append(dr.configs, config)
	if dr.DB != nil {
		dr.compileConfig(config)
	}
	return dr
}

The Config.Policy field might need to be a pointer type to ensure that it can be properly set.
In Go, an interface is considered nil only if both its static type and dynamic value are nil.
When Config is used externally, the Policy field may have a "static type of Policy" but a nil dynamic value, which means the comparison config.Policy == nil will return false.
This issue can be solved by using reflect as follw:

if config.Policy == nil || reflect.ValueOf(config.Policy).IsNil() {
    config.Policy = RandomPolicy{}
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions