94 lines
2.0 KiB
Go
94 lines
2.0 KiB
Go
package mysql
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/schema"
|
|
"gorm.io/plugin/dbresolver"
|
|
"pkg.local/utils"
|
|
)
|
|
|
|
type Config struct {
|
|
Host string
|
|
Port int
|
|
User string
|
|
Password string
|
|
Database string
|
|
Charset string
|
|
Prefix string
|
|
|
|
ReadHost string
|
|
ReadPort int
|
|
ReadUser string
|
|
ReadPassword string
|
|
ReadDatabase string
|
|
}
|
|
|
|
func New(c Config) (*gorm.DB, error) {
|
|
|
|
dsn := buildDSN(c.User, c.Password, c.Host, c.Port, c.Database, c.Charset)
|
|
db, err := gorm.Open(mysql.New(mysql.Config{
|
|
DSN: dsn,
|
|
DefaultStringSize: 256,
|
|
DisableDatetimePrecision: true,
|
|
DontSupportRenameIndex: true,
|
|
DontSupportRenameColumn: true,
|
|
SkipInitializeWithVersion: false,
|
|
}), &gorm.Config{
|
|
NamingStrategy: schema.NamingStrategy{
|
|
TablePrefix: c.Prefix,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("mysql open: %w", err)
|
|
}
|
|
|
|
readDSN := buildReadDSN(c)
|
|
if readDSN != "" {
|
|
if err := db.Use(dbresolver.Register(dbresolver.Config{
|
|
Sources: []gorm.Dialector{mysql.Open(dsn)},
|
|
Replicas: []gorm.Dialector{mysql.Open(readDSN)},
|
|
Policy: dbresolver.RandomPolicy{},
|
|
})); err != nil {
|
|
return nil, fmt.Errorf("mysql dbresolver: %w", err)
|
|
}
|
|
}
|
|
|
|
return db, nil
|
|
}
|
|
|
|
func buildReadDSN(c Config) string {
|
|
if c.ReadHost == utils.StringEmpty {
|
|
return utils.StringEmpty
|
|
}
|
|
|
|
port := c.ReadPort
|
|
if port == utils.NumberZero {
|
|
port = c.Port
|
|
}
|
|
user := c.ReadUser
|
|
if user == utils.StringEmpty {
|
|
user = c.User
|
|
}
|
|
password := c.ReadPassword
|
|
if password == utils.StringEmpty {
|
|
password = c.Password
|
|
}
|
|
database := c.ReadDatabase
|
|
if database == utils.StringEmpty {
|
|
database = c.Database
|
|
}
|
|
charset := c.Charset
|
|
if charset == utils.StringEmpty {
|
|
charset = "utf8mb4"
|
|
}
|
|
return buildDSN(user, password, c.ReadHost, port, database, charset)
|
|
}
|
|
|
|
func buildDSN(user, password, host string, port int, database, charset string) string {
|
|
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local",
|
|
user, password, host, port, database, charset)
|
|
}
|