feat(config): expose charset, loc, and parseTime as configurable DSN parameters
- add Config.Charset (MYSQL_CHARSET, default "utf8mb4"): connection character set sent as SET NAMES during handshake; previously hardcoded - add Config.Loc (MYSQL_LOC, default "UTC"): IANA timezone for time.Time ↔ DATE/DATETIME conversion; previously hardcoded - add Config.ParseTime (MYSQL_PARSE_TIME, default "true"): driver-level DATE/DATETIME → time.Time mapping; valid values "true"/"false"; previously hardcoded - update DSN() to derive parameters from Config fields with empty-means-default semantics; existing Config literals produce identical DSN output (backward compatible) - remove unused url.URL construction from DSN(); params now built directly via url.Values - document collation DSN limitation in Config godoc, CLAUDE.md, RELEASE.md, CHANGELOG.md: go-sql-driver v1.8.x uses 1-byte handshake collation IDs (max 255); MariaDB 11.4+ collations such as utf8mb4_uca1400_as_cs exceed that range — set collation at the database/table level in schema migrations instead
This commit is contained in:
46
mysql.go
46
mysql.go
@@ -50,6 +50,16 @@ type UnitOfWork interface {
|
||||
}
|
||||
|
||||
// Config holds MySQL connection settings.
|
||||
//
|
||||
// DSN parameters Charset, Loc, and ParseTime default to "utf8mb4", "UTC", and
|
||||
// "true" respectively when left empty, preserving the behaviour of v0.9.0.
|
||||
// Set them explicitly when you need non-default values (e.g. Loc="Local").
|
||||
//
|
||||
// Note on Collation: go-sql-driver v1.8.x negotiates the connection collation
|
||||
// via a 1-byte handshake ID (max 255). MariaDB 11.4+ collations such as
|
||||
// utf8mb4_uca1400_as_cs carry IDs > 255 and cannot be set through the DSN
|
||||
// collation parameter. Set the desired collation at the database/table level
|
||||
// in your schema migrations instead.
|
||||
type Config struct {
|
||||
Host string `env:"MYSQL_HOST,required"`
|
||||
Port int `env:"MYSQL_PORT" envDefault:"3306"`
|
||||
@@ -60,20 +70,38 @@ type Config struct {
|
||||
MinConns int `env:"MYSQL_MIN_CONNS" envDefault:"2"`
|
||||
MaxConnLifetime string `env:"MYSQL_MAX_CONN_LIFETIME" envDefault:"1h"`
|
||||
MaxConnIdleTime string `env:"MYSQL_MAX_CONN_IDLE_TIME" envDefault:"30m"`
|
||||
// Charset is the connection character set sent as SET NAMES <charset>.
|
||||
// Defaults to "utf8mb4" when empty.
|
||||
Charset string `env:"MYSQL_CHARSET" envDefault:"utf8mb4"`
|
||||
// Loc is the IANA timezone name used for time.Time ↔ MySQL DATETIME
|
||||
// conversion. Defaults to "UTC" when empty.
|
||||
Loc string `env:"MYSQL_LOC" envDefault:"UTC"`
|
||||
// ParseTime controls whether the driver maps DATE/DATETIME columns to
|
||||
// time.Time. Valid values: "true", "false". Defaults to "true" when empty.
|
||||
ParseTime string `env:"MYSQL_PARSE_TIME" envDefault:"true"`
|
||||
}
|
||||
|
||||
// DSN constructs a MySQL DSN from the configuration.
|
||||
// Empty Charset, Loc, and ParseTime fields fall back to their safe defaults
|
||||
// ("utf8mb4", "UTC", "true"), matching the behaviour of v0.9.0.
|
||||
func (c Config) DSN() string {
|
||||
u := &url.URL{
|
||||
Scheme: "mysql",
|
||||
User: url.UserPassword(c.User, c.Password),
|
||||
Host: fmt.Sprintf("%s:%d", c.Host, c.Port),
|
||||
Path: "/" + c.Name,
|
||||
charset := c.Charset
|
||||
if charset == "" {
|
||||
charset = "utf8mb4"
|
||||
}
|
||||
q := u.Query()
|
||||
q.Set("parseTime", "true")
|
||||
q.Set("loc", "UTC")
|
||||
u.RawQuery = q.Encode()
|
||||
loc := c.Loc
|
||||
if loc == "" {
|
||||
loc = "UTC"
|
||||
}
|
||||
parseTime := c.ParseTime
|
||||
if parseTime == "" {
|
||||
parseTime = "true"
|
||||
}
|
||||
|
||||
q := url.Values{}
|
||||
q.Set("charset", charset)
|
||||
q.Set("loc", loc)
|
||||
q.Set("parseTime", parseTime)
|
||||
// go-sql-driver uses user:pass@tcp(host:port)/db?params
|
||||
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s",
|
||||
c.User, c.Password, c.Host, c.Port, c.Name, q.Encode())
|
||||
|
||||
Reference in New Issue
Block a user