connector.go 3.6 KB

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