...

Source file src/github.com/lib/pq/connector.go

Documentation: github.com/lib/pq

     1  package pq
     2  
     3  import (
     4  	"context"
     5  	"database/sql/driver"
     6  	"errors"
     7  	"fmt"
     8  	"os"
     9  	"strings"
    10  )
    11  
    12  // Connector represents a fixed configuration for the pq driver with a given
    13  // name. Connector satisfies the database/sql/driver Connector interface and
    14  // can be used to create any number of DB Conn's via the database/sql OpenDB
    15  // function.
    16  //
    17  // See https://golang.org/pkg/database/sql/driver/#Connector.
    18  // See https://golang.org/pkg/database/sql/#OpenDB.
    19  type Connector struct {
    20  	opts   values
    21  	dialer Dialer
    22  }
    23  
    24  // Connect returns a connection to the database using the fixed configuration
    25  // of this Connector. Context is not used.
    26  func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
    27  	return c.open(ctx)
    28  }
    29  
    30  // Dialer allows change the dialer used to open connections.
    31  func (c *Connector) Dialer(dialer Dialer) {
    32  	c.dialer = dialer
    33  }
    34  
    35  // Driver returns the underlying driver of this Connector.
    36  func (c *Connector) Driver() driver.Driver {
    37  	return &Driver{}
    38  }
    39  
    40  // NewConnector returns a connector for the pq driver in a fixed configuration
    41  // with the given dsn. The returned connector can be used to create any number
    42  // of equivalent Conn's. The returned connector is intended to be used with
    43  // database/sql.OpenDB.
    44  //
    45  // See https://golang.org/pkg/database/sql/driver/#Connector.
    46  // See https://golang.org/pkg/database/sql/#OpenDB.
    47  func NewConnector(dsn string) (*Connector, error) {
    48  	var err error
    49  	o := make(values)
    50  
    51  	// A number of defaults are applied here, in this order:
    52  	//
    53  	// * Very low precedence defaults applied in every situation
    54  	// * Environment variables
    55  	// * Explicitly passed connection information
    56  	o["host"] = "localhost"
    57  	o["port"] = "5432"
    58  	// N.B.: Extra float digits should be set to 3, but that breaks
    59  	// Postgres 8.4 and older, where the max is 2.
    60  	o["extra_float_digits"] = "2"
    61  	for k, v := range parseEnviron(os.Environ()) {
    62  		o[k] = v
    63  	}
    64  
    65  	if strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") {
    66  		dsn, err = ParseURL(dsn)
    67  		if err != nil {
    68  			return nil, err
    69  		}
    70  	}
    71  
    72  	if err := parseOpts(dsn, o); err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	// Use the "fallback" application name if necessary
    77  	if fallback, ok := o["fallback_application_name"]; ok {
    78  		if _, ok := o["application_name"]; !ok {
    79  			o["application_name"] = fallback
    80  		}
    81  	}
    82  
    83  	// We can't work with any client_encoding other than UTF-8 currently.
    84  	// However, we have historically allowed the user to set it to UTF-8
    85  	// explicitly, and there's no reason to break such programs, so allow that.
    86  	// Note that the "options" setting could also set client_encoding, but
    87  	// parsing its value is not worth it.  Instead, we always explicitly send
    88  	// client_encoding as a separate run-time parameter, which should override
    89  	// anything set in options.
    90  	if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) {
    91  		return nil, errors.New("client_encoding must be absent or 'UTF8'")
    92  	}
    93  	o["client_encoding"] = "UTF8"
    94  	// DateStyle needs a similar treatment.
    95  	if datestyle, ok := o["datestyle"]; ok {
    96  		if datestyle != "ISO, MDY" {
    97  			return nil, fmt.Errorf("setting datestyle must be absent or %v; got %v", "ISO, MDY", datestyle)
    98  		}
    99  	} else {
   100  		o["datestyle"] = "ISO, MDY"
   101  	}
   102  
   103  	// If a user is not provided by any other means, the last
   104  	// resort is to use the current operating system provided user
   105  	// name.
   106  	if _, ok := o["user"]; !ok {
   107  		u, err := userCurrent()
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		o["user"] = u
   112  	}
   113  
   114  	// SSL is not necessary or supported over UNIX domain sockets
   115  	if network, _ := network(o); network == "unix" {
   116  		o["sslmode"] = "disable"
   117  	}
   118  
   119  	return &Connector{opts: o, dialer: defaultDialer{}}, nil
   120  }
   121  

View as plain text