package dbutil import ( "database/sql" "fmt" "log" "time" _ "github.com/lib/pq" ) // The dbutil package provides an interface between go code and a relational database. var db *sql.DB // ConnConfig holds everything Init needs to open the Postgres connection pool. // The app builds it from its own config (dbutil.ConnConfig{Username: cfg.X, ...}) // so the framework never imports application config. type ConnConfig struct { Username string Password string Host string Port int Name string Schema string SSLMode string MaxConns int TimeoutSeconds int } // BuildConnectionString renders a lib/pq Postgres DSN with the session TimeZone // pinned to UTC. Exported so cmd/migrate reuses it instead of duplicating the // format string. func BuildConnectionString(c ConnConfig) string { return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?search_path=%s&sslmode=%s&options=-c%%20TimeZone%%3DUTC", c.Username, c.Password, c.Host, c.Port, c.Name, c.Schema, c.SSLMode, ) } // Init opens the global connection pool from c and pings it. It fatals on // failure, matching the previous package behaviour. func Init(c ConnConfig) { var err error db, err = sql.Open("postgres", BuildConnectionString(c)) if err != nil { log.Fatal(err.Error()) } if pingErr := db.Ping(); pingErr != nil { log.Fatal(pingErr.Error()) } db.SetMaxOpenConns(c.MaxConns) db.SetMaxIdleConns(2) db.SetConnMaxIdleTime(time.Duration(c.TimeoutSeconds) * time.Second) } func DB() *sql.DB { return db }