87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package database
|
|
|
|
import (
|
|
domainUpdate "RenewCMS/internal/domain/update"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
mysqldriver "github.com/go-sql-driver/mysql"
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
const (
|
|
DriverMySQL = "mysql"
|
|
|
|
mysqlCharset = "utf8mb4"
|
|
mysqlLocation = "UTC"
|
|
mysqlCollation = "utf8mb4_bin"
|
|
mysqlConnectTimeout = 5 * time.Second
|
|
mysqlSessionSQLMode = "'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'"
|
|
mysqlTableOptionsKey = "gorm:table_options"
|
|
redactedPassword = "***"
|
|
)
|
|
|
|
type mysqlDriver struct{}
|
|
|
|
type MySQLConfig struct {
|
|
Host string
|
|
Port string
|
|
User string
|
|
Password string
|
|
Name string
|
|
TLS string
|
|
}
|
|
|
|
func MySQLDSN(config MySQLConfig) string {
|
|
dsn := mysqldriver.NewConfig()
|
|
dsn.User = config.User
|
|
dsn.Passwd = config.Password
|
|
dsn.Net = "tcp"
|
|
dsn.Addr = net.JoinHostPort(config.Host, config.Port)
|
|
dsn.DBName = config.Name
|
|
dsn.TLSConfig = config.TLS
|
|
dsn.ParseTime = true
|
|
dsn.ClientFoundRows = true
|
|
dsn.Collation = mysqlCollation
|
|
dsn.Timeout = mysqlConnectTimeout
|
|
dsn.Params = map[string]string{
|
|
"charset": mysqlCharset,
|
|
"loc": mysqlLocation,
|
|
"sql_mode": mysqlSessionSQLMode,
|
|
}
|
|
return dsn.FormatDSN()
|
|
}
|
|
|
|
func (mysqlDriver) Open(source string) (*gorm.DB, error) {
|
|
parsed, err := mysqldriver.ParseDSN(source)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("the mysql connection settings are invalid")
|
|
}
|
|
db, err := gorm.Open(mysql.Open(source), &gorm.Config{})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot use the mysql server at %s: %s", parsed.Addr, redact(err.Error(), parsed.Passwd))
|
|
}
|
|
return db, nil
|
|
}
|
|
|
|
func (mysqlDriver) NewBackup(db *gorm.DB, directory string, now func() time.Time) domainUpdate.DatabaseBackup {
|
|
return NewMySQLBackup(db, directory, now)
|
|
}
|
|
|
|
func redact(message string, secret string) string {
|
|
if secret == "" {
|
|
return message
|
|
}
|
|
return strings.ReplaceAll(message, secret, redactedPassword)
|
|
}
|
|
|
|
func tableOptionsFor(db *gorm.DB) *gorm.DB {
|
|
if db.Dialector.Name() == DriverMySQL {
|
|
return db.Set(mysqlTableOptionsKey, "DEFAULT CHARSET="+mysqlCharset+" COLLATE="+mysqlCollation)
|
|
}
|
|
return db
|
|
}
|