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  }