|
- package pq
-
- import (
- "context"
- "database/sql/driver"
- "errors"
- "fmt"
- "os"
- "strings"
- )
-
- // Connector represents a fixed configuration for the pq driver with a given
- // name. Connector satisfies the database/sql/driver Connector interface and
- // can be used to create any number of DB Conn's via the database/sql OpenDB
- // function.
- //
- // See https://golang.org/pkg/database/sql/driver/#Connector.
- // See https://golang.org/pkg/database/sql/#OpenDB.
- type Connector struct {
- opts values
- dialer Dialer
- }
-
- // Connect returns a connection to the database using the fixed configuration
- // of this Connector. Context is not used.
- func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
- return c.open(ctx)
- }
-
- // Driver returnst the underlying driver of this Connector.
- func (c *Connector) Driver() driver.Driver {
- return &Driver{}
- }
-
- // NewConnector returns a connector for the pq driver in a fixed configuration
- // with the given dsn. The returned connector can be used to create any number
- // of equivalent Conn's. The returned connector is intended to be used with
- // database/sql.OpenDB.
- //
- // See https://golang.org/pkg/database/sql/driver/#Connector.
- // See https://golang.org/pkg/database/sql/#OpenDB.
- func NewConnector(dsn string) (*Connector, error) {
- var err error
- o := make(values)
-
- // A number of defaults are applied here, in this order:
- //
- // * Very low precedence defaults applied in every situation
- // * Environment variables
- // * Explicitly passed connection information
- o["host"] = "localhost"
- o["port"] = "5432"
- // N.B.: Extra float digits should be set to 3, but that breaks
- // Postgres 8.4 and older, where the max is 2.
- o["extra_float_digits"] = "2"
- for k, v := range parseEnviron(os.Environ()) {
- o[k] = v
- }
-
- if strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") {
- dsn, err = ParseURL(dsn)
- if err != nil {
- return nil, err
- }
- }
-
- if err := parseOpts(dsn, o); err != nil {
- return nil, err
- }
-
- // Use the "fallback" application name if necessary
- if fallback, ok := o["fallback_application_name"]; ok {
- if _, ok := o["application_name"]; !ok {
- o["application_name"] = fallback
- }
- }
-
- // We can't work with any client_encoding other than UTF-8 currently.
- // However, we have historically allowed the user to set it to UTF-8
- // explicitly, and there's no reason to break such programs, so allow that.
- // Note that the "options" setting could also set client_encoding, but
- // parsing its value is not worth it. Instead, we always explicitly send
- // client_encoding as a separate run-time parameter, which should override
- // anything set in options.
- if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) {
- return nil, errors.New("client_encoding must be absent or 'UTF8'")
- }
- o["client_encoding"] = "UTF8"
- // DateStyle needs a similar treatment.
- if datestyle, ok := o["datestyle"]; ok {
- if datestyle != "ISO, MDY" {
- return nil, fmt.Errorf("setting datestyle must be absent or %v; got %v", "ISO, MDY", datestyle)
- }
- } else {
- o["datestyle"] = "ISO, MDY"
- }
-
- // If a user is not provided by any other means, the last
- // resort is to use the current operating system provided user
- // name.
- if _, ok := o["user"]; !ok {
- u, err := userCurrent()
- if err != nil {
- return nil, err
- }
- o["user"] = u
- }
-
- return &Connector{opts: o, dialer: defaultDialer{}}, nil
- }
|