package config import ( "database/sql" "fmt" "edge-infra.dev/pkg/lib/gcp/cloudsql" ) // Returns an initialised connection to the database using the configuration // defined in config. Database may be accessed through CloudSQL or via a port number // Returns an error when config includes invalid configuration or an attempt to // connect to the DB fails func DB(config SQLConfig) (*sql.DB, func() error, error) { check := func() error { return fmt.Errorf("error db not initialised") } // Use cloudsql to handle connection var edgeDb *cloudsql.EdgePostgres // Initialise the correct type of connection: CLoudSQL or local host, port pair, // determined by the presence of the ConnectionName configuration param switch { case config.ConnectionName != "": edgeDb = cloudsql.GCPPostgresConnection(config.ConnectionName) case config.ConnectionName == "" && config.Host != "": if config.Port == "" { return nil, check, fmt.Errorf("database port is required") } edgeDb = cloudsql.PostgresConnection(config.Host, config.Port). Password(config.Password) default: return nil, check, fmt.Errorf("database-connection-name or database-host must be provided") } // Open the connection to the configured DB edgeDb = edgeDb. DBName(config.DatabaseName). Username(config.User) // Only set search_path when the schema is a non-empty string if config.Schema != "" { edgeDb = edgeDb.SearchPath(config.Schema) } db, err := edgeDb.NewConnection() if err != nil { return nil, check, err } // Test connection to DB before returning if err := db.Ping(); err != nil { return nil, check, err } return db, checkDB(db), nil } func checkDB(db *sql.DB) func() error { return func() error { if _, err := db.Exec("SELECT 1;"); err != nil { return fmt.Errorf("database not ready: %w", err) } return nil } }