347 lines
8.3 KiB
Go
347 lines
8.3 KiB
Go
package mysqlx
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
mysqldriver "github.com/go-sql-driver/mysql"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
"gorm.io/gorm/schema"
|
|
)
|
|
|
|
// Option configures the SDK client.
|
|
type Option func(*config)
|
|
|
|
type config struct {
|
|
DSN string
|
|
DSNConfig *mysqldriver.Config
|
|
DSNUser string
|
|
DSNPassword string
|
|
DSNNet string
|
|
DSNAddr string
|
|
DSNDBName string
|
|
DSNParams map[string]string
|
|
DSNParseTime *bool
|
|
DSNTLSConfig string
|
|
DSNLoc *time.Location
|
|
DSNCollation string
|
|
DSNTimeout time.Duration
|
|
DSNReadTimeout time.Duration
|
|
DSNWriteTimeout time.Duration
|
|
|
|
Dialector gorm.Dialector
|
|
Logger logger.Interface
|
|
NamingStrategy schema.NamingStrategy
|
|
MaxIdleConns int
|
|
MaxOpenConns int
|
|
ConnMaxIdleTime time.Duration
|
|
ConnMaxLifetime time.Duration
|
|
DisableForeignKeyConstraintWhenMigrating bool
|
|
SkipDefaultTransaction bool
|
|
DryRun bool
|
|
}
|
|
|
|
type DSN struct {
|
|
}
|
|
|
|
func defaultConfig() *config {
|
|
return &config{
|
|
Logger: logger.Default,
|
|
NamingStrategy: schema.NamingStrategy{SingularTable: true},
|
|
MaxIdleConns: 10,
|
|
MaxOpenConns: 100,
|
|
}
|
|
}
|
|
|
|
func buildDSN(cfg *config) (string, error) {
|
|
var mysqlConfig *mysqldriver.Config
|
|
if cfg.DSN != "" {
|
|
parsed, err := mysqldriver.ParseDSN(cfg.DSN)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
mysqlConfig = parsed
|
|
} else if cfg.DSNConfig != nil {
|
|
mysqlConfig = cfg.DSNConfig.Clone()
|
|
} else {
|
|
mysqlConfig = mysqldriver.NewConfig()
|
|
}
|
|
|
|
applyMySQLConfigOverrides(mysqlConfig, cfg)
|
|
|
|
if mysqlConfig.User == "" && mysqlConfig.Passwd == "" && mysqlConfig.Addr == "" && mysqlConfig.DBName == "" && len(mysqlConfig.Params) == 0 {
|
|
if cfg.DSN == "" {
|
|
return "", errors.New("mysqlx: DSN or expanded DSN configuration must be provided")
|
|
}
|
|
}
|
|
|
|
return mysqlConfig.FormatDSN(), nil
|
|
}
|
|
|
|
func applyMySQLConfigOverrides(mysqlConfig *mysqldriver.Config, cfg *config) {
|
|
if cfg.DSNConfig != nil {
|
|
mergeMySQLConfig(mysqlConfig, cfg.DSNConfig)
|
|
}
|
|
if cfg.DSNUser != "" {
|
|
mysqlConfig.User = cfg.DSNUser
|
|
}
|
|
if cfg.DSNPassword != "" {
|
|
mysqlConfig.Passwd = cfg.DSNPassword
|
|
}
|
|
if cfg.DSNNet != "" {
|
|
mysqlConfig.Net = cfg.DSNNet
|
|
}
|
|
if cfg.DSNAddr != "" {
|
|
mysqlConfig.Addr = cfg.DSNAddr
|
|
}
|
|
if cfg.DSNDBName != "" {
|
|
mysqlConfig.DBName = cfg.DSNDBName
|
|
}
|
|
if cfg.DSNParams != nil {
|
|
if mysqlConfig.Params == nil {
|
|
mysqlConfig.Params = map[string]string{}
|
|
}
|
|
for key, value := range cfg.DSNParams {
|
|
mysqlConfig.Params[key] = value
|
|
}
|
|
}
|
|
if cfg.DSNParseTime != nil {
|
|
mysqlConfig.ParseTime = *cfg.DSNParseTime
|
|
}
|
|
if cfg.DSNTLSConfig != "" {
|
|
mysqlConfig.TLSConfig = cfg.DSNTLSConfig
|
|
}
|
|
if cfg.DSNLoc != nil {
|
|
mysqlConfig.Loc = cfg.DSNLoc
|
|
}
|
|
if cfg.DSNCollation != "" {
|
|
mysqlConfig.Collation = cfg.DSNCollation
|
|
}
|
|
if cfg.DSNTimeout > 0 {
|
|
mysqlConfig.Timeout = cfg.DSNTimeout
|
|
}
|
|
if cfg.DSNReadTimeout > 0 {
|
|
mysqlConfig.ReadTimeout = cfg.DSNReadTimeout
|
|
}
|
|
if cfg.DSNWriteTimeout > 0 {
|
|
mysqlConfig.WriteTimeout = cfg.DSNWriteTimeout
|
|
}
|
|
}
|
|
|
|
func mergeMySQLConfig(base, override *mysqldriver.Config) {
|
|
if override.User != "" {
|
|
base.User = override.User
|
|
}
|
|
if override.Passwd != "" {
|
|
base.Passwd = override.Passwd
|
|
}
|
|
if override.Net != "" {
|
|
base.Net = override.Net
|
|
}
|
|
if override.Addr != "" {
|
|
base.Addr = override.Addr
|
|
}
|
|
if override.DBName != "" {
|
|
base.DBName = override.DBName
|
|
}
|
|
if override.Params != nil {
|
|
if base.Params == nil {
|
|
base.Params = map[string]string{}
|
|
}
|
|
for key, value := range override.Params {
|
|
base.Params[key] = value
|
|
}
|
|
}
|
|
if override.Collation != "" {
|
|
base.Collation = override.Collation
|
|
}
|
|
if override.Loc != nil {
|
|
base.Loc = override.Loc
|
|
}
|
|
if override.TLSConfig != "" {
|
|
base.TLSConfig = override.TLSConfig
|
|
}
|
|
if override.Timeout > 0 {
|
|
base.Timeout = override.Timeout
|
|
}
|
|
if override.ReadTimeout > 0 {
|
|
base.ReadTimeout = override.ReadTimeout
|
|
}
|
|
if override.WriteTimeout > 0 {
|
|
base.WriteTimeout = override.WriteTimeout
|
|
}
|
|
if override.ParseTime {
|
|
base.ParseTime = override.ParseTime
|
|
}
|
|
}
|
|
|
|
// WithDSN sets the MySQL DSN used to open the database.
|
|
func WithDSN(dsn string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSN = dsn
|
|
}
|
|
}
|
|
|
|
// WithDSNConfig sets the underlying mysql.Config used to generate the DSN.
|
|
func WithDSNConfig(mysqlConfig *mysqldriver.Config) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNConfig = mysqlConfig
|
|
}
|
|
}
|
|
|
|
// WithDSNUser sets the MySQL username.
|
|
func WithDSNUser(user string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNUser = user
|
|
}
|
|
}
|
|
|
|
// WithDSNPassword sets the MySQL password.
|
|
func WithDSNPassword(password string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNPassword = password
|
|
}
|
|
}
|
|
|
|
// WithDSNNet sets the network type for the DSN.
|
|
func WithDSNNet(net string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNNet = net
|
|
}
|
|
}
|
|
|
|
// WithDSNAddr sets the database address for the DSN.
|
|
func WithDSNAddr(addr string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNAddr = addr
|
|
}
|
|
}
|
|
|
|
// WithDSNDBName sets the database name for the DSN.
|
|
func WithDSNDBName(dbName string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNDBName = dbName
|
|
}
|
|
}
|
|
|
|
// WithDSNParams sets additional DSN query parameters.
|
|
func WithDSNParams(params map[string]string) Option {
|
|
return func(cfg *config) {
|
|
if cfg.DSNParams == nil {
|
|
cfg.DSNParams = map[string]string{}
|
|
}
|
|
for key, value := range params {
|
|
cfg.DSNParams[key] = value
|
|
}
|
|
}
|
|
}
|
|
|
|
// WithDSNParseTime configures parseTime for the DSN.
|
|
func WithDSNParseTime(parseTime bool) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNParseTime = &parseTime
|
|
}
|
|
}
|
|
|
|
// WithDSNTLSConfig sets the TLS configuration name for the DSN.
|
|
func WithDSNTLSConfig(tlsConfig string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNTLSConfig = tlsConfig
|
|
}
|
|
}
|
|
|
|
// WithDSNLocation sets the time location for DSN parsing.
|
|
func WithDSNLocation(loc *time.Location) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNLoc = loc
|
|
}
|
|
}
|
|
|
|
// WithDSNCollation sets the connection collation for the DSN.
|
|
func WithDSNCollation(collation string) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNCollation = collation
|
|
}
|
|
}
|
|
|
|
// WithDSNTimeout sets the dial timeout for the DSN.
|
|
func WithDSNTimeout(timeout time.Duration) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNTimeout = timeout
|
|
}
|
|
}
|
|
|
|
// WithDSNReadTimeout sets the read timeout for the DSN.
|
|
func WithDSNReadTimeout(timeout time.Duration) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNReadTimeout = timeout
|
|
}
|
|
}
|
|
|
|
// WithDSNWriteTimeout sets the write timeout for the DSN.
|
|
func WithDSNWriteTimeout(timeout time.Duration) Option {
|
|
return func(cfg *config) {
|
|
cfg.DSNWriteTimeout = timeout
|
|
}
|
|
}
|
|
|
|
// WithDialector sets a custom gorm Dialector.
|
|
func WithDialector(dialector gorm.Dialector) Option {
|
|
return func(cfg *config) {
|
|
cfg.Dialector = dialector
|
|
}
|
|
}
|
|
|
|
// WithLogger sets the gorm logger.
|
|
func WithLogger(logger logger.Interface) Option {
|
|
return func(cfg *config) {
|
|
cfg.Logger = logger
|
|
}
|
|
}
|
|
|
|
// WithNamingStrategy sets the naming strategy for gorm models.
|
|
func WithNamingStrategy(strategy schema.NamingStrategy) Option {
|
|
return func(cfg *config) {
|
|
cfg.NamingStrategy = strategy
|
|
}
|
|
}
|
|
|
|
// WithSingularTable enables or disables singular table names for gorm models.
|
|
func WithSingularTable(singular bool) Option {
|
|
return func(cfg *config) {
|
|
cfg.NamingStrategy.SingularTable = singular
|
|
}
|
|
}
|
|
|
|
// WithConnectionPool configures database connection pooling.
|
|
func WithConnectionPool(maxIdleConns, maxOpenConns int, maxIdleTime, maxLifetime time.Duration) Option {
|
|
return func(cfg *config) {
|
|
cfg.MaxIdleConns = maxIdleConns
|
|
cfg.MaxOpenConns = maxOpenConns
|
|
cfg.ConnMaxIdleTime = maxIdleTime
|
|
cfg.ConnMaxLifetime = maxLifetime
|
|
}
|
|
}
|
|
|
|
// WithDisableForeignKeyConstraintWhenMigrating toggles foreign key constraint creation during migrations.
|
|
func WithDisableForeignKeyConstraintWhenMigrating(disable bool) Option {
|
|
return func(cfg *config) {
|
|
cfg.DisableForeignKeyConstraintWhenMigrating = disable
|
|
}
|
|
}
|
|
|
|
// WithSkipDefaultTransaction toggles default transactions in gorm.
|
|
func WithSkipDefaultTransaction(skip bool) Option {
|
|
return func(cfg *config) {
|
|
cfg.SkipDefaultTransaction = skip
|
|
}
|
|
}
|
|
|
|
// WithDryRun toggles gorm dry run mode.
|
|
func WithDryRun(dryRun bool) Option {
|
|
return func(cfg *config) {
|
|
cfg.DryRun = dryRun
|
|
}
|
|
}
|