goyave.dev/goyave/v5@v5.0.0-rc9.0.20240517145003-d3f977d0b9f3/database/dialect.go (about) 1 package database 2 3 import ( 4 "strconv" 5 "strings" 6 "sync" 7 8 "gorm.io/gorm" 9 "goyave.dev/goyave/v5/config" 10 "goyave.dev/goyave/v5/util/errors" 11 ) 12 13 var ( 14 mu sync.Mutex 15 16 dialects = map[string]dialect{} 17 18 optionPlaceholders = map[string]string{ 19 "{username}": "database.username", 20 "{password}": "database.password", 21 "{host}": "database.host", 22 "{name}": "database.name", 23 "{options}": "database.options", 24 } 25 ) 26 27 // DialectorInitializer function initializing a GORM Dialector using the given 28 // data source name (DSN). 29 type DialectorInitializer func(dsn string) gorm.Dialector 30 31 type dialect struct { 32 initializer DialectorInitializer 33 template string 34 } 35 36 func (d dialect) buildDSN(cfg *config.Config) string { 37 connStr := d.template 38 for k, v := range optionPlaceholders { 39 connStr = strings.Replace(connStr, k, cfg.GetString(v), 1) 40 } 41 connStr = strings.Replace(connStr, "{port}", strconv.Itoa(cfg.GetInt("database.port")), 1) 42 43 return connStr 44 } 45 46 // RegisterDialect registers a connection string template for the given dialect. 47 // 48 // You cannot override a dialect that already exists. 49 // 50 // Template format accepts the following placeholders, which will be replaced with 51 // the corresponding configuration entries automatically: 52 // - "{username}" 53 // - "{password}" 54 // - "{host}" 55 // - "{port}" 56 // - "{name}" 57 // - "{options}" 58 // 59 // Example template for the "mysql" dialect: 60 // 61 // {username}:{password}@({host}:{port})/{name}?{options} 62 func RegisterDialect(name, template string, initializer DialectorInitializer) { 63 mu.Lock() 64 defer mu.Unlock() 65 if _, ok := dialects[name]; ok { 66 panic(errors.Errorf("dialect %q already exists", name)) 67 } 68 dialects[name] = dialect{initializer, template} 69 }