Files
2026-06-08 13:34:53 -05:00

69 lines
1.5 KiB
Go

package dbutil
import (
"database/sql"
"errors"
"fmt"
"strings"
"github.com/go-sql-driver/mysql"
)
func OpenMySQLAndCreateDatabaseIfMissing(dsn string) (*sql.DB, error) {
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
if err := db.Ping(); err == nil {
return db, nil
} else {
_ = db.Close()
var mysqlErr *mysql.MySQLError
if !errors.As(err, &mysqlErr) || mysqlErr.Number != 1049 {
return nil, err
}
}
cfg, err := mysql.ParseDSN(dsn)
if err != nil {
return nil, err
}
if cfg.DBName == "" {
return nil, errors.New("DSN does not include a database name")
}
databaseName := cfg.DBName
cfg.DBName = ""
adminDB, err := sql.Open("mysql", cfg.FormatDSN())
if err != nil {
return nil, err
}
defer adminDB.Close()
if err := adminDB.Ping(); err != nil {
return nil, err
}
if _, err := adminDB.Exec("CREATE DATABASE IF NOT EXISTS " + QuoteMySQLIdentifier(databaseName) + " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); err != nil {
return nil, err
}
fmt.Printf("created database %q\n", databaseName)
db, err = sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
if err := db.Ping(); err != nil {
_ = db.Close()
return nil, err
}
return db, nil
}
func QuoteMySQLIdentifier(name string) string {
return "`" + strings.ReplaceAll(name, "`", "``") + "`"
}
func IsDuplicateColumnError(err error) bool {
var mysqlErr *mysql.MySQLError
return errors.As(err, &mysqlErr) && mysqlErr.Number == 1060
}