build(deps): bump github.com/jackc/pgx/v4 from 4.16.0 to 4.17.1
Bumps [github.com/jackc/pgx/v4](https://github.com/jackc/pgx) from 4.16.0 to 4.17.1. - [Release notes](https://github.com/jackc/pgx/releases) - [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md) - [Commits](https://github.com/jackc/pgx/compare/v4.16.0...v4.17.1) --- updated-dependencies: - dependency-name: github.com/jackc/pgx/v4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
parent
5f29dc312a
commit
b133ff5994
50 changed files with 1503 additions and 253 deletions
4
go.mod
4
go.mod
|
|
@ -28,8 +28,8 @@ require (
|
|||
github.com/google/uuid v1.3.0
|
||||
github.com/gophercloud/gophercloud v0.24.0
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1
|
||||
github.com/jackc/pgtype v1.11.0
|
||||
github.com/jackc/pgx/v4 v4.16.0
|
||||
github.com/jackc/pgtype v1.12.0
|
||||
github.com/jackc/pgx/v4 v4.17.1
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b
|
||||
github.com/labstack/echo/v4 v4.7.2
|
||||
|
|
|
|||
18
go.sum
18
go.sum
|
|
@ -963,8 +963,9 @@ github.com/jackc/pgconn v1.6.0/go.mod h1:yeseQo4xhQbgyJs2c87RAXOH2i624N0Fh1KSPJy
|
|||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
|
||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
|
||||
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.12.0 h1:/RvQ24k3TnNdfBSW0ou9EOi5jx2cX7zfE8n2nLKuiP0=
|
||||
github.com/jackc/pgconn v1.12.0/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono=
|
||||
github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
|
||||
github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
|
|
@ -983,8 +984,9 @@ github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwX
|
|||
github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.0 h1:brH0pCGBDkBW07HWlN/oSBXrmo3WB0UvZd1pIuDcL8Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
|
|
@ -993,8 +995,9 @@ github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCM
|
|||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.3.0/go.mod h1:b0JqxHvPmljG+HQ5IsvQ0yqeSi4nGcDTVjFoiLDb0Ik=
|
||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||
github.com/jackc/pgtype v1.11.0 h1:u4uiGPz/1hryuXzyaBhSk6dnIyyG2683olG2OV+UUgs=
|
||||
github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
|
||||
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=
|
||||
github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
|
|
@ -1002,14 +1005,16 @@ github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9
|
|||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.6.0/go.mod h1:vPh43ZzxijXUVJ+t/EmXBtFmbFVO72cuneCT9oAlxAg=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/pgx/v4 v4.16.0 h1:4k1tROTJctHotannFYzu77dY3bgtMRymQP7tXQjqpPk=
|
||||
github.com/jackc/pgx/v4 v4.16.0/go.mod h1:N0A9sFdWzkw/Jy1lwoiB64F2+ugFZi987zRxcPez/wI=
|
||||
github.com/jackc/pgx/v4 v4.17.1 h1:tASdE79tX9LOQu3MMvioWT6YaZkf58ZhmLHhV4sv5WM=
|
||||
github.com/jackc/pgx/v4 v4.17.1/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.2.1 h1:gI8os0wpRXFd4FiAY2dWiqRK037tjj3t7rKFeO4X5iw=
|
||||
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
|
||||
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||
|
|
@ -1798,8 +1803,9 @@ golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0
|
|||
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
|
|
|||
12
vendor/github.com/jackc/pgconn/CHANGELOG.md
generated
vendored
12
vendor/github.com/jackc/pgconn/CHANGELOG.md
generated
vendored
|
|
@ -1,3 +1,15 @@
|
|||
# 1.13.0 (August 6, 2022)
|
||||
|
||||
* Add sslpassword support (Eric McCormack and yun.xu)
|
||||
* Add prefer-standby target_session_attrs support (sergey.bashilov)
|
||||
* Fix GSS ErrorResponse handling (Oliver Tan)
|
||||
|
||||
# 1.12.1 (May 7, 2022)
|
||||
|
||||
* Fix: setting krbspn and krbsrvname in connection string (sireax)
|
||||
* Add support for Unix sockets on Windows (Eno Compton)
|
||||
* Stop ignoring ErrorResponse during SCRAM auth (Rafi Shamim)
|
||||
|
||||
# 1.12.0 (April 21, 2022)
|
||||
|
||||
* Add pluggable GSSAPI support (Oliver Tan)
|
||||
|
|
|
|||
20
vendor/github.com/jackc/pgconn/auth_scram.go
generated
vendored
20
vendor/github.com/jackc/pgconn/auth_scram.go
generated
vendored
|
|
@ -78,12 +78,14 @@ func (c *PgConn) rxSASLContinue() (*pgproto3.AuthenticationSASLContinue, error)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
saslContinue, ok := msg.(*pgproto3.AuthenticationSASLContinue)
|
||||
if ok {
|
||||
return saslContinue, nil
|
||||
switch m := msg.(type) {
|
||||
case *pgproto3.AuthenticationSASLContinue:
|
||||
return m, nil
|
||||
case *pgproto3.ErrorResponse:
|
||||
return nil, ErrorResponseToPgError(m)
|
||||
}
|
||||
|
||||
return nil, errors.New("expected AuthenticationSASLContinue message but received unexpected message")
|
||||
return nil, fmt.Errorf("expected AuthenticationSASLContinue message but received unexpected message %T", msg)
|
||||
}
|
||||
|
||||
func (c *PgConn) rxSASLFinal() (*pgproto3.AuthenticationSASLFinal, error) {
|
||||
|
|
@ -91,12 +93,14 @@ func (c *PgConn) rxSASLFinal() (*pgproto3.AuthenticationSASLFinal, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
saslFinal, ok := msg.(*pgproto3.AuthenticationSASLFinal)
|
||||
if ok {
|
||||
return saslFinal, nil
|
||||
switch m := msg.(type) {
|
||||
case *pgproto3.AuthenticationSASLFinal:
|
||||
return m, nil
|
||||
case *pgproto3.ErrorResponse:
|
||||
return nil, ErrorResponseToPgError(m)
|
||||
}
|
||||
|
||||
return nil, errors.New("expected AuthenticationSASLFinal message but received unexpected message")
|
||||
return nil, fmt.Errorf("expected AuthenticationSASLFinal message but received unexpected message %T", msg)
|
||||
}
|
||||
|
||||
type scramClient struct {
|
||||
|
|
|
|||
173
vendor/github.com/jackc/pgconn/config.go
generated
vendored
173
vendor/github.com/jackc/pgconn/config.go
generated
vendored
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -25,6 +26,7 @@ import (
|
|||
|
||||
type AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error
|
||||
type ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
|
||||
type GetSSLPasswordFunc func(ctx context.Context) string
|
||||
|
||||
// Config is the settings used to establish a connection to a PostgreSQL server. It must be created by ParseConfig. A
|
||||
// manually initialized Config will cause ConnectConfig to panic.
|
||||
|
|
@ -41,7 +43,9 @@ type Config struct {
|
|||
BuildFrontend BuildFrontendFunc
|
||||
RuntimeParams map[string]string // Run-time parameters to set on connection as session default values (e.g. search_path or application_name)
|
||||
|
||||
Fallbacks []*FallbackConfig
|
||||
KerberosSrvName string
|
||||
KerberosSpn string
|
||||
Fallbacks []*FallbackConfig
|
||||
|
||||
// ValidateConnect is called during a connection attempt after a successful authentication with the PostgreSQL server.
|
||||
// It can be used to validate that the server is acceptable. If this returns an error the connection is closed and the next
|
||||
|
|
@ -61,6 +65,13 @@ type Config struct {
|
|||
createdByParseConfig bool // Used to enforce created by ParseConfig rule.
|
||||
}
|
||||
|
||||
// ParseConfigOptions contains options that control how a config is built such as getsslpassword.
|
||||
type ParseConfigOptions struct {
|
||||
// GetSSLPassword gets the password to decrypt a SSL client certificate. This is analogous to the the libpq function
|
||||
// PQsetSSLKeyPassHook_OpenSSL.
|
||||
GetSSLPassword GetSSLPasswordFunc
|
||||
}
|
||||
|
||||
// Copy returns a deep copy of the config that is safe to use and modify.
|
||||
// The only exception is the TLSConfig field:
|
||||
// according to the tls.Config docs it must not be modified after creation.
|
||||
|
|
@ -98,10 +109,29 @@ type FallbackConfig struct {
|
|||
TLSConfig *tls.Config // nil disables TLS
|
||||
}
|
||||
|
||||
// isAbsolutePath checks if the provided value is an absolute path either
|
||||
// beginning with a forward slash (as on Linux-based systems) or with a capital
|
||||
// letter A-Z followed by a colon and a backslash, e.g., "C:\", (as on Windows).
|
||||
func isAbsolutePath(path string) bool {
|
||||
isWindowsPath := func(p string) bool {
|
||||
if len(p) < 3 {
|
||||
return false
|
||||
}
|
||||
drive := p[0]
|
||||
colon := p[1]
|
||||
backslash := p[2]
|
||||
if drive >= 'A' && drive <= 'Z' && colon == ':' && backslash == '\\' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return strings.HasPrefix(path, "/") || isWindowsPath(path)
|
||||
}
|
||||
|
||||
// NetworkAddress converts a PostgreSQL host and port into network and address suitable for use with
|
||||
// net.Dial.
|
||||
func NetworkAddress(host string, port uint16) (network, address string) {
|
||||
if strings.HasPrefix(host, "/") {
|
||||
if isAbsolutePath(host) {
|
||||
network = "unix"
|
||||
address = filepath.Join(host, ".s.PGSQL.") + strconv.FormatInt(int64(port), 10)
|
||||
} else {
|
||||
|
|
@ -111,10 +141,10 @@ func NetworkAddress(host string, port uint16) (network, address string) {
|
|||
return network, address
|
||||
}
|
||||
|
||||
// ParseConfig builds a *Config with similar behavior to the PostgreSQL standard C library libpq. It uses the same
|
||||
// defaults as libpq (e.g. port=5432) and understands most PG* environment variables. ParseConfig closely matches
|
||||
// the parsing behavior of libpq. connString may either be in URL format or keyword = value format (DSN style). See
|
||||
// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING for details. connString also may be
|
||||
// ParseConfig builds a *Config from connString with similar behavior to the PostgreSQL standard C library libpq. It
|
||||
// uses the same defaults as libpq (e.g. port=5432) and understands most PG* environment variables. ParseConfig closely
|
||||
// matches the parsing behavior of libpq. connString may either be in URL format or keyword = value format (DSN style).
|
||||
// See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING for details. connString also may be
|
||||
// empty to only read from the environment. If a password is not supplied it will attempt to read the .pgpass file.
|
||||
//
|
||||
// # Example DSN
|
||||
|
|
@ -138,21 +168,22 @@ func NetworkAddress(host string, port uint16) (network, address string) {
|
|||
// ParseConfig currently recognizes the following environment variable and their parameter key word equivalents passed
|
||||
// via database URL or DSN:
|
||||
//
|
||||
// PGHOST
|
||||
// PGPORT
|
||||
// PGDATABASE
|
||||
// PGUSER
|
||||
// PGPASSWORD
|
||||
// PGPASSFILE
|
||||
// PGSERVICE
|
||||
// PGSERVICEFILE
|
||||
// PGSSLMODE
|
||||
// PGSSLCERT
|
||||
// PGSSLKEY
|
||||
// PGSSLROOTCERT
|
||||
// PGAPPNAME
|
||||
// PGCONNECT_TIMEOUT
|
||||
// PGTARGETSESSIONATTRS
|
||||
// PGHOST
|
||||
// PGPORT
|
||||
// PGDATABASE
|
||||
// PGUSER
|
||||
// PGPASSWORD
|
||||
// PGPASSFILE
|
||||
// PGSERVICE
|
||||
// PGSERVICEFILE
|
||||
// PGSSLMODE
|
||||
// PGSSLCERT
|
||||
// PGSSLKEY
|
||||
// PGSSLROOTCERT
|
||||
// PGSSLPASSWORD
|
||||
// PGAPPNAME
|
||||
// PGCONNECT_TIMEOUT
|
||||
// PGTARGETSESSIONATTRS
|
||||
//
|
||||
// See http://www.postgresql.org/docs/11/static/libpq-envars.html for details on the meaning of environment variables.
|
||||
//
|
||||
|
|
@ -172,7 +203,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
|
|||
// sslmode "prefer" this means it will first try the main Config settings which use TLS, then it will try the fallback
|
||||
// which does not use TLS. This can lead to an unexpected unencrypted connection if the main TLS config is manually
|
||||
// changed later but the unencrypted fallback is present. Ensure there are no stale fallbacks when manually setting
|
||||
// TLCConfig.
|
||||
// TLSConfig.
|
||||
//
|
||||
// Other known differences with libpq:
|
||||
//
|
||||
|
|
@ -181,12 +212,20 @@ func NetworkAddress(host string, port uint16) (network, address string) {
|
|||
//
|
||||
// In addition, ParseConfig accepts the following options:
|
||||
//
|
||||
// min_read_buffer_size
|
||||
// The minimum size of the internal read buffer. Default 8192.
|
||||
// servicefile
|
||||
// libpq only reads servicefile from the PGSERVICEFILE environment variable. ParseConfig accepts servicefile as a
|
||||
// part of the connection string.
|
||||
// min_read_buffer_size
|
||||
// The minimum size of the internal read buffer. Default 8192.
|
||||
// servicefile
|
||||
// libpq only reads servicefile from the PGSERVICEFILE environment variable. ParseConfig accepts servicefile as a
|
||||
// part of the connection string.
|
||||
func ParseConfig(connString string) (*Config, error) {
|
||||
var parseConfigOptions ParseConfigOptions
|
||||
return ParseConfigWithOptions(connString, parseConfigOptions)
|
||||
}
|
||||
|
||||
// ParseConfigWithOptions builds a *Config from connString and options with similar behavior to the PostgreSQL standard
|
||||
// C library libpq. options contains settings that cannot be specified in a connString such as providing a function to
|
||||
// get the SSL password.
|
||||
func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Config, error) {
|
||||
defaultSettings := defaultSettings()
|
||||
envSettings := parseEnvSettings()
|
||||
|
||||
|
|
@ -257,6 +296,7 @@ func ParseConfig(connString string) (*Config, error) {
|
|||
"sslkey": {},
|
||||
"sslcert": {},
|
||||
"sslrootcert": {},
|
||||
"sslpassword": {},
|
||||
"krbspn": {},
|
||||
"krbsrvname": {},
|
||||
"target_session_attrs": {},
|
||||
|
|
@ -265,6 +305,14 @@ func ParseConfig(connString string) (*Config, error) {
|
|||
"servicefile": {},
|
||||
}
|
||||
|
||||
// Adding kerberos configuration
|
||||
if _, present := settings["krbsrvname"]; present {
|
||||
config.KerberosSrvName = settings["krbsrvname"]
|
||||
}
|
||||
if _, present := settings["krbspn"]; present {
|
||||
config.KerberosSpn = settings["krbspn"]
|
||||
}
|
||||
|
||||
for k, v := range settings {
|
||||
if _, present := notRuntimeParams[k]; present {
|
||||
continue
|
||||
|
|
@ -297,7 +345,7 @@ func ParseConfig(connString string) (*Config, error) {
|
|||
tlsConfigs = append(tlsConfigs, nil)
|
||||
} else {
|
||||
var err error
|
||||
tlsConfigs, err = configTLS(settings, host)
|
||||
tlsConfigs, err = configTLS(settings, host, options)
|
||||
if err != nil {
|
||||
return nil, &parseConfigError{connString: connString, msg: "failed to configure TLS", err: err}
|
||||
}
|
||||
|
|
@ -338,7 +386,9 @@ func ParseConfig(connString string) (*Config, error) {
|
|||
config.ValidateConnect = ValidateConnectTargetSessionAttrsPrimary
|
||||
case "standby":
|
||||
config.ValidateConnect = ValidateConnectTargetSessionAttrsStandby
|
||||
case "any", "prefer-standby":
|
||||
case "prefer-standby":
|
||||
config.ValidateConnect = ValidateConnectTargetSessionAttrsPreferStandby
|
||||
case "any":
|
||||
// do nothing
|
||||
default:
|
||||
return nil, &parseConfigError{connString: connString, msg: fmt.Sprintf("unknown target_session_attrs value: %v", tsa)}
|
||||
|
|
@ -375,6 +425,7 @@ func parseEnvSettings() map[string]string {
|
|||
"PGSSLKEY": "sslkey",
|
||||
"PGSSLCERT": "sslcert",
|
||||
"PGSSLROOTCERT": "sslrootcert",
|
||||
"PGSSLPASSWORD": "sslpassword",
|
||||
"PGTARGETSESSIONATTRS": "target_session_attrs",
|
||||
"PGSERVICE": "service",
|
||||
"PGSERVICEFILE": "servicefile",
|
||||
|
|
@ -561,12 +612,13 @@ func parseServiceSettings(servicefilePath, serviceName string) (map[string]strin
|
|||
// configTLS uses libpq's TLS parameters to construct []*tls.Config. It is
|
||||
// necessary to allow returning multiple TLS configs as sslmode "allow" and
|
||||
// "prefer" allow fallback.
|
||||
func configTLS(settings map[string]string, thisHost string) ([]*tls.Config, error) {
|
||||
func configTLS(settings map[string]string, thisHost string, parseConfigOptions ParseConfigOptions) ([]*tls.Config, error) {
|
||||
host := thisHost
|
||||
sslmode := settings["sslmode"]
|
||||
sslrootcert := settings["sslrootcert"]
|
||||
sslcert := settings["sslcert"]
|
||||
sslkey := settings["sslkey"]
|
||||
sslpassword := settings["sslpassword"]
|
||||
|
||||
// Match libpq default behavior
|
||||
if sslmode == "" {
|
||||
|
|
@ -654,11 +706,53 @@ func configTLS(settings map[string]string, thisHost string) ([]*tls.Config, erro
|
|||
}
|
||||
|
||||
if sslcert != "" && sslkey != "" {
|
||||
cert, err := tls.LoadX509KeyPair(sslcert, sslkey)
|
||||
buf, err := ioutil.ReadFile(sslkey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read sslkey: %w", err)
|
||||
}
|
||||
block, _ := pem.Decode(buf)
|
||||
var pemKey []byte
|
||||
var decryptedKey []byte
|
||||
var decryptedError error
|
||||
// If PEM is encrypted, attempt to decrypt using pass phrase
|
||||
if x509.IsEncryptedPEMBlock(block) {
|
||||
// Attempt decryption with pass phrase
|
||||
// NOTE: only supports RSA (PKCS#1)
|
||||
if sslpassword != "" {
|
||||
decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword))
|
||||
}
|
||||
//if sslpassword not provided or has decryption error when use it
|
||||
//try to find sslpassword with callback function
|
||||
if sslpassword == "" || decryptedError != nil {
|
||||
if parseConfigOptions.GetSSLPassword != nil {
|
||||
sslpassword = parseConfigOptions.GetSSLPassword(context.Background())
|
||||
}
|
||||
if sslpassword == "" {
|
||||
return nil, fmt.Errorf("unable to find sslpassword")
|
||||
}
|
||||
}
|
||||
decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword))
|
||||
// Should we also provide warning for PKCS#1 needed?
|
||||
if decryptedError != nil {
|
||||
return nil, fmt.Errorf("unable to decrypt key: %w", err)
|
||||
}
|
||||
|
||||
pemBytes := pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: decryptedKey,
|
||||
}
|
||||
pemKey = pem.EncodeToMemory(&pemBytes)
|
||||
} else {
|
||||
pemKey = pem.EncodeToMemory(block)
|
||||
}
|
||||
certfile, err := ioutil.ReadFile(sslcert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read cert: %w", err)
|
||||
}
|
||||
|
||||
cert, err := tls.X509KeyPair(certfile, pemKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load cert: %w", err)
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||
}
|
||||
|
||||
|
|
@ -781,3 +875,18 @@ func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgCon
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateConnectTargetSessionAttrsPreferStandby is an ValidateConnectFunc that implements libpq compatible
|
||||
// target_session_attrs=prefer-standby.
|
||||
func ValidateConnectTargetSessionAttrsPreferStandby(ctx context.Context, pgConn *PgConn) error {
|
||||
result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
|
||||
if result.Err != nil {
|
||||
return result.Err
|
||||
}
|
||||
|
||||
if string(result.Rows[0][0]) != "t" {
|
||||
return &NotPreferredError{err: errors.New("server is not in hot standby mode")}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
1
vendor/github.com/jackc/pgconn/defaults.go
generated
vendored
1
vendor/github.com/jackc/pgconn/defaults.go
generated
vendored
|
|
@ -1,3 +1,4 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package pgconn
|
||||
|
|
|
|||
17
vendor/github.com/jackc/pgconn/errors.go
generated
vendored
17
vendor/github.com/jackc/pgconn/errors.go
generated
vendored
|
|
@ -219,3 +219,20 @@ func redactURL(u *url.URL) string {
|
|||
}
|
||||
return u.String()
|
||||
}
|
||||
|
||||
type NotPreferredError struct {
|
||||
err error
|
||||
safeToRetry bool
|
||||
}
|
||||
|
||||
func (e *NotPreferredError) Error() string {
|
||||
return fmt.Sprintf("standby server not found: %s", e.err.Error())
|
||||
}
|
||||
|
||||
func (e *NotPreferredError) SafeToRetry() bool {
|
||||
return e.safeToRetry
|
||||
}
|
||||
|
||||
func (e *NotPreferredError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
|
|
|||
6
vendor/github.com/jackc/pgconn/go.mod
generated
vendored
6
vendor/github.com/jackc/pgconn/go.mod
generated
vendored
|
|
@ -7,9 +7,9 @@ require (
|
|||
github.com/jackc/pgio v1.0.0
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65
|
||||
github.com/jackc/pgpassfile v1.0.0
|
||||
github.com/jackc/pgproto3/v2 v2.3.0
|
||||
github.com/jackc/pgproto3/v2 v2.3.1
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
|
||||
github.com/stretchr/testify v1.8.0
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||
golang.org/x/text v0.3.7
|
||||
)
|
||||
|
|
|
|||
13
vendor/github.com/jackc/pgconn/go.sum
generated
vendored
13
vendor/github.com/jackc/pgconn/go.sum
generated
vendored
|
|
@ -36,6 +36,8 @@ github.com/jackc/pgproto3/v2 v2.2.1-0.20220412121321-175856ffd3c8 h1:KxsCQec+1iw
|
|||
github.com/jackc/pgproto3/v2 v2.2.1-0.20220412121321-175856ffd3c8/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.0 h1:brH0pCGBDkBW07HWlN/oSBXrmo3WB0UvZd1pIuDcL8Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
|
|
@ -73,12 +75,17 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
|
|
@ -93,11 +100,14 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP
|
|||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -108,6 +118,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
|
@ -132,3 +143,5 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a
|
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
|||
21
vendor/github.com/jackc/pgconn/krb5.go
generated
vendored
21
vendor/github.com/jackc/pgconn/krb5.go
generated
vendored
|
|
@ -2,6 +2,8 @@ package pgconn
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgproto3/v2"
|
||||
)
|
||||
|
||||
|
|
@ -41,14 +43,14 @@ func (c *PgConn) gssAuth() error {
|
|||
}
|
||||
|
||||
var nextData []byte
|
||||
if spn, ok := c.config.RuntimeParams["krbspn"]; ok {
|
||||
if c.config.KerberosSpn != "" {
|
||||
// Use the supplied SPN if provided.
|
||||
nextData, err = cli.GetInitTokenFromSPN(spn)
|
||||
nextData, err = cli.GetInitTokenFromSPN(c.config.KerberosSpn)
|
||||
} else {
|
||||
// Allow the kerberos service name to be overridden
|
||||
service := "postgres"
|
||||
if val, ok := c.config.RuntimeParams["krbsrvname"]; ok {
|
||||
service = val
|
||||
if c.config.KerberosSrvName != "" {
|
||||
service = c.config.KerberosSrvName
|
||||
}
|
||||
nextData, err = cli.GetInitToken(c.config.Host, service)
|
||||
}
|
||||
|
|
@ -85,10 +87,13 @@ func (c *PgConn) rxGSSContinue() (*pgproto3.AuthenticationGSSContinue, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gssContinue, ok := msg.(*pgproto3.AuthenticationGSSContinue)
|
||||
if ok {
|
||||
return gssContinue, nil
|
||||
|
||||
switch m := msg.(type) {
|
||||
case *pgproto3.AuthenticationGSSContinue:
|
||||
return m, nil
|
||||
case *pgproto3.ErrorResponse:
|
||||
return nil, ErrorResponseToPgError(m)
|
||||
}
|
||||
|
||||
return nil, errors.New("expected AuthenticationGSSContinue message but received unexpected message")
|
||||
return nil, fmt.Errorf("expected AuthenticationGSSContinue message but received unexpected message %T", msg)
|
||||
}
|
||||
|
|
|
|||
36
vendor/github.com/jackc/pgconn/pgconn.go
generated
vendored
36
vendor/github.com/jackc/pgconn/pgconn.go
generated
vendored
|
|
@ -109,6 +109,18 @@ func Connect(ctx context.Context, connString string) (*PgConn, error) {
|
|||
return ConnectConfig(ctx, config)
|
||||
}
|
||||
|
||||
// Connect establishes a connection to a PostgreSQL server using the environment and connString (in URL or DSN format)
|
||||
// and ParseConfigOptions to provide additional configuration. See documentation for ParseConfig for details. ctx can be
|
||||
// used to cancel a connect attempt.
|
||||
func ConnectWithOptions(ctx context.Context, connString string, parseConfigOptions ParseConfigOptions) (*PgConn, error) {
|
||||
config, err := ParseConfigWithOptions(connString, parseConfigOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ConnectConfig(ctx, config)
|
||||
}
|
||||
|
||||
// Connect establishes a connection to a PostgreSQL server using config. config must have been constructed with
|
||||
// ParseConfig. ctx can be used to cancel a connect attempt.
|
||||
//
|
||||
|
|
@ -148,9 +160,12 @@ func ConnectConfig(ctx context.Context, config *Config) (pgConn *PgConn, err err
|
|||
return nil, &connectError{config: config, msg: "hostname resolving error", err: errors.New("ip addr wasn't found")}
|
||||
}
|
||||
|
||||
foundBestServer := false
|
||||
var fallbackConfig *FallbackConfig
|
||||
for _, fc := range fallbackConfigs {
|
||||
pgConn, err = connect(ctx, config, fc)
|
||||
pgConn, err = connect(ctx, config, fc, false)
|
||||
if err == nil {
|
||||
foundBestServer = true
|
||||
break
|
||||
} else if pgerr, ok := err.(*PgError); ok {
|
||||
err = &connectError{config: config, msg: "server error", err: pgerr}
|
||||
|
|
@ -164,6 +179,17 @@ func ConnectConfig(ctx context.Context, config *Config) (pgConn *PgConn, err err
|
|||
pgerr.Code == ERRCODE_INSUFFICIENT_PRIVILEGE {
|
||||
break
|
||||
}
|
||||
} else if cerr, ok := err.(*connectError); ok {
|
||||
if _, ok := cerr.err.(*NotPreferredError); ok {
|
||||
fallbackConfig = fc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !foundBestServer && fallbackConfig != nil {
|
||||
pgConn, err = connect(ctx, config, fallbackConfig, true)
|
||||
if pgerr, ok := err.(*PgError); ok {
|
||||
err = &connectError{config: config, msg: "server error", err: pgerr}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +213,7 @@ func expandWithIPs(ctx context.Context, lookupFn LookupFunc, fallbacks []*Fallba
|
|||
|
||||
for _, fb := range fallbacks {
|
||||
// skip resolve for unix sockets
|
||||
if strings.HasPrefix(fb.Host, "/") {
|
||||
if isAbsolutePath(fb.Host) {
|
||||
configs = append(configs, &FallbackConfig{
|
||||
Host: fb.Host,
|
||||
Port: fb.Port,
|
||||
|
|
@ -227,7 +253,8 @@ func expandWithIPs(ctx context.Context, lookupFn LookupFunc, fallbacks []*Fallba
|
|||
return configs, nil
|
||||
}
|
||||
|
||||
func connect(ctx context.Context, config *Config, fallbackConfig *FallbackConfig) (*PgConn, error) {
|
||||
func connect(ctx context.Context, config *Config, fallbackConfig *FallbackConfig,
|
||||
ignoreNotPreferredErr bool) (*PgConn, error) {
|
||||
pgConn := new(PgConn)
|
||||
pgConn.config = config
|
||||
pgConn.wbuf = make([]byte, 0, wbufLen)
|
||||
|
|
@ -340,6 +367,9 @@ func connect(ctx context.Context, config *Config, fallbackConfig *FallbackConfig
|
|||
|
||||
err := config.ValidateConnect(ctx, pgConn)
|
||||
if err != nil {
|
||||
if _, ok := err.(*NotPreferredError); ignoreNotPreferredErr && ok {
|
||||
return pgConn, nil
|
||||
}
|
||||
pgConn.conn.Close()
|
||||
return nil, &connectError{config: config, msg: "ValidateConnect failed", err: err}
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/jackc/pgproto3/v2/backend.go
generated
vendored
4
vendor/github.com/jackc/pgproto3/v2/backend.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package pgproto3
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
|
@ -114,6 +115,9 @@ func (b *Backend) Receive() (FrontendMessage, error) {
|
|||
b.msgType = header[0]
|
||||
b.bodyLen = int(binary.BigEndian.Uint32(header[1:])) - 4
|
||||
b.partialMsg = true
|
||||
if b.bodyLen < 0 {
|
||||
return nil, errors.New("invalid message with negative body length received")
|
||||
}
|
||||
}
|
||||
|
||||
var msg FrontendMessage
|
||||
|
|
|
|||
3
vendor/github.com/jackc/pgproto3/v2/frontend.go
generated
vendored
3
vendor/github.com/jackc/pgproto3/v2/frontend.go
generated
vendored
|
|
@ -79,6 +79,9 @@ func (f *Frontend) Receive() (BackendMessage, error) {
|
|||
f.msgType = header[0]
|
||||
f.bodyLen = int(binary.BigEndian.Uint32(header[1:])) - 4
|
||||
f.partialMsg = true
|
||||
if f.bodyLen < 0 {
|
||||
return nil, errors.New("invalid message with negative body length received")
|
||||
}
|
||||
}
|
||||
|
||||
msgBody, err := f.cr.Next(f.bodyLen)
|
||||
|
|
|
|||
13
vendor/github.com/jackc/pgtype/CHANGELOG.md
generated
vendored
13
vendor/github.com/jackc/pgtype/CHANGELOG.md
generated
vendored
|
|
@ -1,3 +1,16 @@
|
|||
# 1.12.0 (August 6, 2022)
|
||||
|
||||
* Add JSONArray (Jakob Ackermann)
|
||||
* Support Inet from fmt.Stringer and encoding.TextMarshaler (Ville Skyttä)
|
||||
* Support UUID from fmt.Stringer interface (Lasse Hyldahl Jensen)
|
||||
* Fix: shopspring-numeric extension does not panic on NaN
|
||||
* Numeric can be assigned to string
|
||||
* Fix: Do not send IPv4 networks as IPv4-mapped IPv6 (William Storey)
|
||||
* Fix: PlanScan for interface{}(nil) (James Hartig)
|
||||
* Fix: *sql.Scanner for NULL handling (James Hartig)
|
||||
* Timestamp[tz].Set() supports string (Harmen)
|
||||
* Fix: Hstore AssignTo with map of *string (Diego Becciolini)
|
||||
|
||||
# 1.11.0 (April 21, 2022)
|
||||
|
||||
* Add multirange for numeric, int4, and int8 (Vu)
|
||||
|
|
|
|||
2
vendor/github.com/jackc/pgtype/array_type.go
generated
vendored
2
vendor/github.com/jackc/pgtype/array_type.go
generated
vendored
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
// ArrayType represents an array type. While it implements Value, this is only in service of its type conversion duties
|
||||
// when registered as a data type in a ConnType. It should not be used directly as a Value. ArrayType is a convenience
|
||||
// type for types that do not have an concrete array type.
|
||||
// type for types that do not have a concrete array type.
|
||||
type ArrayType struct {
|
||||
elements []ValueTranscoder
|
||||
dimensions []ArrayDimension
|
||||
|
|
|
|||
4
vendor/github.com/jackc/pgtype/date.go
generated
vendored
4
vendor/github.com/jackc/pgtype/date.go
generated
vendored
|
|
@ -37,14 +37,14 @@ func (dst *Date) Set(src interface{}) error {
|
|||
switch value := src.(type) {
|
||||
case time.Time:
|
||||
*dst = Date{Time: value, Status: Present}
|
||||
case string:
|
||||
return dst.DecodeText(nil, []byte(value))
|
||||
case *time.Time:
|
||||
if value == nil {
|
||||
*dst = Date{Status: Null}
|
||||
} else {
|
||||
return dst.Set(*value)
|
||||
}
|
||||
case string:
|
||||
return dst.DecodeText(nil, []byte(value))
|
||||
case *string:
|
||||
if value == nil {
|
||||
*dst = Date{Status: Null}
|
||||
|
|
|
|||
2
vendor/github.com/jackc/pgtype/enum_type.go
generated
vendored
2
vendor/github.com/jackc/pgtype/enum_type.go
generated
vendored
|
|
@ -2,7 +2,7 @@ package pgtype
|
|||
|
||||
import "fmt"
|
||||
|
||||
// EnumType represents a enum type. While it implements Value, this is only in service of its type conversion duties
|
||||
// EnumType represents an enum type. While it implements Value, this is only in service of its type conversion duties
|
||||
// when registered as a data type in a ConnType. It should not be used directly as a Value.
|
||||
type EnumType struct {
|
||||
value string
|
||||
|
|
|
|||
5
vendor/github.com/jackc/pgtype/hstore.go
generated
vendored
5
vendor/github.com/jackc/pgtype/hstore.go
generated
vendored
|
|
@ -90,7 +90,8 @@ func (src *Hstore) AssignTo(dst interface{}) error {
|
|||
case Null:
|
||||
(*v)[k] = nil
|
||||
case Present:
|
||||
(*v)[k] = &val.String
|
||||
str := val.String
|
||||
(*v)[k] = &str
|
||||
default:
|
||||
return fmt.Errorf("cannot decode %#v into %T", src, dst)
|
||||
}
|
||||
|
|
@ -413,7 +414,7 @@ func parseHstore(s string) (k []string, v []Text, err error) {
|
|||
r, end = p.Consume()
|
||||
switch {
|
||||
case end:
|
||||
err = errors.New("Found EOS after ',', expcting space")
|
||||
err = errors.New("Found EOS after ',', expecting space")
|
||||
case (unicode.IsSpace(r)):
|
||||
r, end = p.Consume()
|
||||
state = hsKey
|
||||
|
|
|
|||
60
vendor/github.com/jackc/pgtype/inet.go
generated
vendored
60
vendor/github.com/jackc/pgtype/inet.go
generated
vendored
|
|
@ -2,8 +2,10 @@ package pgtype
|
|||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Network address family is dependent on server socket.h value for AF_INET.
|
||||
|
|
@ -47,17 +49,26 @@ func (dst *Inet) Set(src interface{}) error {
|
|||
case string:
|
||||
ip, ipnet, err := net.ParseCIDR(value)
|
||||
if err != nil {
|
||||
ip = net.ParseIP(value)
|
||||
ip := net.ParseIP(value)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("unable to parse inet address: %s", value)
|
||||
}
|
||||
ipnet = &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)}
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
ip = ipv4
|
||||
ipnet.Mask = net.CIDRMask(32, 32)
|
||||
|
||||
if ipv4 := maybeGetIPv4(value, ip); ipv4 != nil {
|
||||
ipnet = &net.IPNet{IP: ipv4, Mask: net.CIDRMask(32, 32)}
|
||||
} else {
|
||||
ipnet = &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)}
|
||||
}
|
||||
} else {
|
||||
ipnet.IP = ip
|
||||
if ipv4 := maybeGetIPv4(value, ipnet.IP); ipv4 != nil {
|
||||
ipnet.IP = ipv4
|
||||
if len(ipnet.Mask) == 16 {
|
||||
ipnet.Mask = ipnet.Mask[12:] // Not sure this is ever needed.
|
||||
}
|
||||
}
|
||||
}
|
||||
ipnet.IP = ip
|
||||
|
||||
*dst = Inet{IPNet: ipnet, Status: Present}
|
||||
case *net.IPNet:
|
||||
if value == nil {
|
||||
|
|
@ -78,6 +89,16 @@ func (dst *Inet) Set(src interface{}) error {
|
|||
return dst.Set(*value)
|
||||
}
|
||||
default:
|
||||
if tv, ok := src.(encoding.TextMarshaler); ok {
|
||||
text, err := tv.MarshalText()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot marshal %v: %w", value, err)
|
||||
}
|
||||
return dst.Set(string(text))
|
||||
}
|
||||
if sv, ok := src.(fmt.Stringer); ok {
|
||||
return dst.Set(sv.String())
|
||||
}
|
||||
if originalSrc, ok := underlyingPtrType(src); ok {
|
||||
return dst.Set(originalSrc)
|
||||
}
|
||||
|
|
@ -87,6 +108,25 @@ func (dst *Inet) Set(src interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Convert the net.IP to IPv4, if appropriate.
|
||||
//
|
||||
// When parsing a string to a net.IP using net.ParseIP() and the like, we get a
|
||||
// 16 byte slice for IPv4 addresses as well as IPv6 addresses. This function
|
||||
// calls To4() to convert them to a 4 byte slice. This is useful as it allows
|
||||
// users of the net.IP check for IPv4 addresses based on the length and makes
|
||||
// it clear we are handling IPv4 as opposed to IPv6 or IPv4-mapped IPv6
|
||||
// addresses.
|
||||
func maybeGetIPv4(input string, ip net.IP) net.IP {
|
||||
// Do not do this if the provided input looks like IPv6. This is because
|
||||
// To4() on IPv4-mapped IPv6 addresses converts them to IPv4, which behave
|
||||
// different in some cases.
|
||||
if strings.Contains(input, ":") {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ip.To4()
|
||||
}
|
||||
|
||||
func (dst Inet) Get() interface{} {
|
||||
switch dst.Status {
|
||||
case Present:
|
||||
|
|
@ -118,6 +158,12 @@ func (src *Inet) AssignTo(dst interface{}) error {
|
|||
copy(*v, src.IPNet.IP)
|
||||
return nil
|
||||
default:
|
||||
if tv, ok := dst.(encoding.TextUnmarshaler); ok {
|
||||
if err := tv.UnmarshalText([]byte(src.IPNet.String())); err != nil {
|
||||
return fmt.Errorf("cannot unmarshal %v to %T: %w", src, dst, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if nextDst, retry := GetAssignToDstType(dst); retry {
|
||||
return src.AssignTo(nextDst)
|
||||
}
|
||||
|
|
@ -169,7 +215,7 @@ func (dst *Inet) DecodeBinary(ci *ConnInfo, src []byte) error {
|
|||
}
|
||||
|
||||
if len(src) != 8 && len(src) != 20 {
|
||||
return fmt.Errorf("Received an invalid size for a inet: %d", len(src))
|
||||
return fmt.Errorf("Received an invalid size for an inet: %d", len(src))
|
||||
}
|
||||
|
||||
// ignore family
|
||||
|
|
|
|||
2
vendor/github.com/jackc/pgtype/interval.go
generated
vendored
2
vendor/github.com/jackc/pgtype/interval.go
generated
vendored
|
|
@ -174,7 +174,7 @@ func (dst *Interval) DecodeBinary(ci *ConnInfo, src []byte) error {
|
|||
}
|
||||
|
||||
if len(src) != 16 {
|
||||
return fmt.Errorf("Received an invalid size for a interval: %d", len(src))
|
||||
return fmt.Errorf("Received an invalid size for an interval: %d", len(src))
|
||||
}
|
||||
|
||||
microseconds := int64(binary.BigEndian.Uint64(src))
|
||||
|
|
|
|||
546
vendor/github.com/jackc/pgtype/json_array.go
generated
vendored
Normal file
546
vendor/github.com/jackc/pgtype/json_array.go
generated
vendored
Normal file
|
|
@ -0,0 +1,546 @@
|
|||
// Code generated by erb. DO NOT EDIT.
|
||||
|
||||
package pgtype
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/jackc/pgio"
|
||||
)
|
||||
|
||||
type JSONArray struct {
|
||||
Elements []JSON
|
||||
Dimensions []ArrayDimension
|
||||
Status Status
|
||||
}
|
||||
|
||||
func (dst *JSONArray) Set(src interface{}) error {
|
||||
// untyped nil and typed nil interfaces are different
|
||||
if src == nil {
|
||||
*dst = JSONArray{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
if value, ok := src.(interface{ Get() interface{} }); ok {
|
||||
value2 := value.Get()
|
||||
if value2 != value {
|
||||
return dst.Set(value2)
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to match to select common types:
|
||||
switch value := src.(type) {
|
||||
|
||||
case []string:
|
||||
if value == nil {
|
||||
*dst = JSONArray{Status: Null}
|
||||
} else if len(value) == 0 {
|
||||
*dst = JSONArray{Status: Present}
|
||||
} else {
|
||||
elements := make([]JSON, len(value))
|
||||
for i := range value {
|
||||
if err := elements[i].Set(value[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*dst = JSONArray{
|
||||
Elements: elements,
|
||||
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
|
||||
Status: Present,
|
||||
}
|
||||
}
|
||||
|
||||
case [][]byte:
|
||||
if value == nil {
|
||||
*dst = JSONArray{Status: Null}
|
||||
} else if len(value) == 0 {
|
||||
*dst = JSONArray{Status: Present}
|
||||
} else {
|
||||
elements := make([]JSON, len(value))
|
||||
for i := range value {
|
||||
if err := elements[i].Set(value[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*dst = JSONArray{
|
||||
Elements: elements,
|
||||
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
|
||||
Status: Present,
|
||||
}
|
||||
}
|
||||
|
||||
case []json.RawMessage:
|
||||
if value == nil {
|
||||
*dst = JSONArray{Status: Null}
|
||||
} else if len(value) == 0 {
|
||||
*dst = JSONArray{Status: Present}
|
||||
} else {
|
||||
elements := make([]JSON, len(value))
|
||||
for i := range value {
|
||||
if err := elements[i].Set(value[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*dst = JSONArray{
|
||||
Elements: elements,
|
||||
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
|
||||
Status: Present,
|
||||
}
|
||||
}
|
||||
|
||||
case []JSON:
|
||||
if value == nil {
|
||||
*dst = JSONArray{Status: Null}
|
||||
} else if len(value) == 0 {
|
||||
*dst = JSONArray{Status: Present}
|
||||
} else {
|
||||
*dst = JSONArray{
|
||||
Elements: value,
|
||||
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
|
||||
Status: Present,
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Fallback to reflection if an optimised match was not found.
|
||||
// The reflection is necessary for arrays and multidimensional slices,
|
||||
// but it comes with a 20-50% performance penalty for large arrays/slices
|
||||
reflectedValue := reflect.ValueOf(src)
|
||||
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
|
||||
*dst = JSONArray{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot find dimensions of %v for JSONArray", src)
|
||||
}
|
||||
if elementsLength == 0 {
|
||||
*dst = JSONArray{Status: Present}
|
||||
return nil
|
||||
}
|
||||
if len(dimensions) == 0 {
|
||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||
return dst.Set(originalSrc)
|
||||
}
|
||||
return fmt.Errorf("cannot convert %v to JSONArray", src)
|
||||
}
|
||||
|
||||
*dst = JSONArray{
|
||||
Elements: make([]JSON, elementsLength),
|
||||
Dimensions: dimensions,
|
||||
Status: Present,
|
||||
}
|
||||
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
|
||||
if err != nil {
|
||||
// Maybe the target was one dimension too far, try again:
|
||||
if len(dst.Dimensions) > 1 {
|
||||
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
|
||||
elementsLength = 0
|
||||
for _, dim := range dst.Dimensions {
|
||||
if elementsLength == 0 {
|
||||
elementsLength = int(dim.Length)
|
||||
} else {
|
||||
elementsLength *= int(dim.Length)
|
||||
}
|
||||
}
|
||||
dst.Elements = make([]JSON, elementsLength)
|
||||
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if elementCount != len(dst.Elements) {
|
||||
return fmt.Errorf("cannot convert %v to JSONArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *JSONArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
|
||||
switch value.Kind() {
|
||||
case reflect.Array:
|
||||
fallthrough
|
||||
case reflect.Slice:
|
||||
if len(dst.Dimensions) == dimension {
|
||||
break
|
||||
}
|
||||
|
||||
valueLen := value.Len()
|
||||
if int32(valueLen) != dst.Dimensions[dimension].Length {
|
||||
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
|
||||
}
|
||||
for i := 0; i < valueLen; i++ {
|
||||
var err error
|
||||
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return index, nil
|
||||
}
|
||||
if !value.CanInterface() {
|
||||
return 0, fmt.Errorf("cannot convert all values to JSONArray")
|
||||
}
|
||||
if err := dst.Elements[index].Set(value.Interface()); err != nil {
|
||||
return 0, fmt.Errorf("%v in JSONArray", err)
|
||||
}
|
||||
index++
|
||||
|
||||
return index, nil
|
||||
}
|
||||
|
||||
func (dst JSONArray) Get() interface{} {
|
||||
switch dst.Status {
|
||||
case Present:
|
||||
return dst
|
||||
case Null:
|
||||
return nil
|
||||
default:
|
||||
return dst.Status
|
||||
}
|
||||
}
|
||||
|
||||
func (src *JSONArray) AssignTo(dst interface{}) error {
|
||||
switch src.Status {
|
||||
case Present:
|
||||
if len(src.Dimensions) <= 1 {
|
||||
// Attempt to match to select common types:
|
||||
switch v := dst.(type) {
|
||||
|
||||
case *[]string:
|
||||
*v = make([]string, len(src.Elements))
|
||||
for i := range src.Elements {
|
||||
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
case *[][]byte:
|
||||
*v = make([][]byte, len(src.Elements))
|
||||
for i := range src.Elements {
|
||||
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
case *[]json.RawMessage:
|
||||
*v = make([]json.RawMessage, len(src.Elements))
|
||||
for i := range src.Elements {
|
||||
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Try to convert to something AssignTo can use directly.
|
||||
if nextDst, retry := GetAssignToDstType(dst); retry {
|
||||
return src.AssignTo(nextDst)
|
||||
}
|
||||
|
||||
// Fallback to reflection if an optimised match was not found.
|
||||
// The reflection is necessary for arrays and multidimensional slices,
|
||||
// but it comes with a 20-50% performance penalty for large arrays/slices
|
||||
value := reflect.ValueOf(dst)
|
||||
if value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
}
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
default:
|
||||
return fmt.Errorf("cannot assign %T to %T", src, dst)
|
||||
}
|
||||
|
||||
if len(src.Elements) == 0 {
|
||||
if value.Kind() == reflect.Slice {
|
||||
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
elementCount, err := src.assignToRecursive(value, 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if elementCount != len(src.Elements) {
|
||||
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
|
||||
}
|
||||
|
||||
return nil
|
||||
case Null:
|
||||
return NullAssignTo(dst)
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot decode %#v into %T", src, dst)
|
||||
}
|
||||
|
||||
func (src *JSONArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
|
||||
switch kind := value.Kind(); kind {
|
||||
case reflect.Array:
|
||||
fallthrough
|
||||
case reflect.Slice:
|
||||
if len(src.Dimensions) == dimension {
|
||||
break
|
||||
}
|
||||
|
||||
length := int(src.Dimensions[dimension].Length)
|
||||
if reflect.Array == kind {
|
||||
typ := value.Type()
|
||||
if typ.Len() != length {
|
||||
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
|
||||
}
|
||||
value.Set(reflect.New(typ).Elem())
|
||||
} else {
|
||||
value.Set(reflect.MakeSlice(value.Type(), length, length))
|
||||
}
|
||||
|
||||
var err error
|
||||
for i := 0; i < length; i++ {
|
||||
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return index, nil
|
||||
}
|
||||
if len(src.Dimensions) != dimension {
|
||||
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
|
||||
}
|
||||
if !value.CanAddr() {
|
||||
return 0, fmt.Errorf("cannot assign all values from JSONArray")
|
||||
}
|
||||
addr := value.Addr()
|
||||
if !addr.CanInterface() {
|
||||
return 0, fmt.Errorf("cannot assign all values from JSONArray")
|
||||
}
|
||||
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
index++
|
||||
return index, nil
|
||||
}
|
||||
|
||||
func (dst *JSONArray) DecodeText(ci *ConnInfo, src []byte) error {
|
||||
if src == nil {
|
||||
*dst = JSONArray{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
uta, err := ParseUntypedTextArray(string(src))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var elements []JSON
|
||||
|
||||
if len(uta.Elements) > 0 {
|
||||
elements = make([]JSON, len(uta.Elements))
|
||||
|
||||
for i, s := range uta.Elements {
|
||||
var elem JSON
|
||||
var elemSrc []byte
|
||||
if s != "NULL" || uta.Quoted[i] {
|
||||
elemSrc = []byte(s)
|
||||
}
|
||||
err = elem.DecodeText(ci, elemSrc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
elements[i] = elem
|
||||
}
|
||||
}
|
||||
|
||||
*dst = JSONArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *JSONArray) DecodeBinary(ci *ConnInfo, src []byte) error {
|
||||
if src == nil {
|
||||
*dst = JSONArray{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
var arrayHeader ArrayHeader
|
||||
rp, err := arrayHeader.DecodeBinary(ci, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(arrayHeader.Dimensions) == 0 {
|
||||
*dst = JSONArray{Dimensions: arrayHeader.Dimensions, Status: Present}
|
||||
return nil
|
||||
}
|
||||
|
||||
elementCount := arrayHeader.Dimensions[0].Length
|
||||
for _, d := range arrayHeader.Dimensions[1:] {
|
||||
elementCount *= d.Length
|
||||
}
|
||||
|
||||
elements := make([]JSON, elementCount)
|
||||
|
||||
for i := range elements {
|
||||
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
|
||||
rp += 4
|
||||
var elemSrc []byte
|
||||
if elemLen >= 0 {
|
||||
elemSrc = src[rp : rp+elemLen]
|
||||
rp += elemLen
|
||||
}
|
||||
err = elements[i].DecodeBinary(ci, elemSrc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
*dst = JSONArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src JSONArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
switch src.Status {
|
||||
case Null:
|
||||
return nil, nil
|
||||
case Undefined:
|
||||
return nil, errUndefined
|
||||
}
|
||||
|
||||
if len(src.Dimensions) == 0 {
|
||||
return append(buf, '{', '}'), nil
|
||||
}
|
||||
|
||||
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
|
||||
|
||||
// dimElemCounts is the multiples of elements that each array lies on. For
|
||||
// example, a single dimension array of length 4 would have a dimElemCounts of
|
||||
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
|
||||
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
|
||||
// or '}'.
|
||||
dimElemCounts := make([]int, len(src.Dimensions))
|
||||
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
|
||||
for i := len(src.Dimensions) - 2; i > -1; i-- {
|
||||
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
|
||||
}
|
||||
|
||||
inElemBuf := make([]byte, 0, 32)
|
||||
for i, elem := range src.Elements {
|
||||
if i > 0 {
|
||||
buf = append(buf, ',')
|
||||
}
|
||||
|
||||
for _, dec := range dimElemCounts {
|
||||
if i%dec == 0 {
|
||||
buf = append(buf, '{')
|
||||
}
|
||||
}
|
||||
|
||||
elemBuf, err := elem.EncodeText(ci, inElemBuf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if elemBuf == nil {
|
||||
buf = append(buf, `NULL`...)
|
||||
} else {
|
||||
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
|
||||
}
|
||||
|
||||
for _, dec := range dimElemCounts {
|
||||
if (i+1)%dec == 0 {
|
||||
buf = append(buf, '}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (src JSONArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
switch src.Status {
|
||||
case Null:
|
||||
return nil, nil
|
||||
case Undefined:
|
||||
return nil, errUndefined
|
||||
}
|
||||
|
||||
arrayHeader := ArrayHeader{
|
||||
Dimensions: src.Dimensions,
|
||||
}
|
||||
|
||||
if dt, ok := ci.DataTypeForName("json"); ok {
|
||||
arrayHeader.ElementOID = int32(dt.OID)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unable to find oid for type name %v", "json")
|
||||
}
|
||||
|
||||
for i := range src.Elements {
|
||||
if src.Elements[i].Status == Null {
|
||||
arrayHeader.ContainsNull = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
buf = arrayHeader.EncodeBinary(ci, buf)
|
||||
|
||||
for i := range src.Elements {
|
||||
sp := len(buf)
|
||||
buf = pgio.AppendInt32(buf, -1)
|
||||
|
||||
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if elemBuf != nil {
|
||||
buf = elemBuf
|
||||
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
|
||||
}
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Scan implements the database/sql Scanner interface.
|
||||
func (dst *JSONArray) Scan(src interface{}) error {
|
||||
if src == nil {
|
||||
return dst.DecodeText(nil, nil)
|
||||
}
|
||||
|
||||
switch src := src.(type) {
|
||||
case string:
|
||||
return dst.DecodeText(nil, []byte(src))
|
||||
case []byte:
|
||||
srcCopy := make([]byte, len(src))
|
||||
copy(srcCopy, src)
|
||||
return dst.DecodeText(nil, srcCopy)
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot scan %T", src)
|
||||
}
|
||||
|
||||
// Value implements the database/sql/driver Valuer interface.
|
||||
func (src JSONArray) Value() (driver.Value, error) {
|
||||
buf, err := src.EncodeText(nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if buf == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return string(buf), nil
|
||||
}
|
||||
59
vendor/github.com/jackc/pgtype/numeric.go
generated
vendored
59
vendor/github.com/jackc/pgtype/numeric.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package pgtype
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql/driver"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
|
@ -375,6 +376,12 @@ func (src *Numeric) AssignTo(dst interface{}) error {
|
|||
return err
|
||||
}
|
||||
v.Set(rat)
|
||||
case *string:
|
||||
buf, err := encodeNumericText(*src, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = string(buf)
|
||||
default:
|
||||
if nextDst, retry := GetAssignToDstType(dst); retry {
|
||||
return src.AssignTo(nextDst)
|
||||
|
|
@ -792,3 +799,55 @@ func (src Numeric) Value() (driver.Value, error) {
|
|||
return nil, errUndefined
|
||||
}
|
||||
}
|
||||
|
||||
func encodeNumericText(n Numeric, buf []byte) (newBuf []byte, err error) {
|
||||
// if !n.Valid {
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
if n.NaN {
|
||||
buf = append(buf, "NaN"...)
|
||||
return buf, nil
|
||||
} else if n.InfinityModifier == Infinity {
|
||||
buf = append(buf, "Infinity"...)
|
||||
return buf, nil
|
||||
} else if n.InfinityModifier == NegativeInfinity {
|
||||
buf = append(buf, "-Infinity"...)
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
buf = append(buf, n.numberTextBytes()...)
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// numberString returns a string of the number. undefined if NaN, infinite, or NULL
|
||||
func (n Numeric) numberTextBytes() []byte {
|
||||
intStr := n.Int.String()
|
||||
buf := &bytes.Buffer{}
|
||||
exp := int(n.Exp)
|
||||
if exp > 0 {
|
||||
buf.WriteString(intStr)
|
||||
for i := 0; i < exp; i++ {
|
||||
buf.WriteByte('0')
|
||||
}
|
||||
} else if exp < 0 {
|
||||
if len(intStr) <= -exp {
|
||||
buf.WriteString("0.")
|
||||
leadingZeros := -exp - len(intStr)
|
||||
for i := 0; i < leadingZeros; i++ {
|
||||
buf.WriteByte('0')
|
||||
}
|
||||
buf.WriteString(intStr)
|
||||
} else if len(intStr) > -exp {
|
||||
dpPos := len(intStr) + exp
|
||||
buf.WriteString(intStr[:dpPos])
|
||||
buf.WriteByte('.')
|
||||
buf.WriteString(intStr[dpPos:])
|
||||
}
|
||||
} else {
|
||||
buf.WriteString(intStr)
|
||||
}
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
|
|
|||
57
vendor/github.com/jackc/pgtype/pgtype.go
generated
vendored
57
vendor/github.com/jackc/pgtype/pgtype.go
generated
vendored
|
|
@ -26,6 +26,7 @@ const (
|
|||
XIDOID = 28
|
||||
CIDOID = 29
|
||||
JSONOID = 114
|
||||
JSONArrayOID = 199
|
||||
PointOID = 600
|
||||
LsegOID = 601
|
||||
PathOID = 602
|
||||
|
|
@ -297,6 +298,7 @@ func NewConnInfo() *ConnInfo {
|
|||
ci.RegisterDataType(DataType{Value: &Int8multirange{}, Name: "int8multirange", OID: Int8multirangeOID})
|
||||
ci.RegisterDataType(DataType{Value: &Interval{}, Name: "interval", OID: IntervalOID})
|
||||
ci.RegisterDataType(DataType{Value: &JSON{}, Name: "json", OID: JSONOID})
|
||||
ci.RegisterDataType(DataType{Value: &JSONArray{}, Name: "_json", OID: JSONArrayOID})
|
||||
ci.RegisterDataType(DataType{Value: &JSONB{}, Name: "jsonb", OID: JSONBOID})
|
||||
ci.RegisterDataType(DataType{Value: &JSONBArray{}, Name: "_jsonb", OID: JSONBArrayOID})
|
||||
ci.RegisterDataType(DataType{Value: &Line{}, Name: "line", OID: LineOID})
|
||||
|
|
@ -533,8 +535,22 @@ type scanPlanDataTypeSQLScanner DataType
|
|||
func (plan *scanPlanDataTypeSQLScanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
|
||||
scanner, ok := dst.(sql.Scanner)
|
||||
if !ok {
|
||||
newPlan := ci.PlanScan(oid, formatCode, dst)
|
||||
return newPlan.Scan(ci, oid, formatCode, src, dst)
|
||||
dv := reflect.ValueOf(dst)
|
||||
if dv.Kind() != reflect.Ptr || !dv.Type().Elem().Implements(scannerType) {
|
||||
newPlan := ci.PlanScan(oid, formatCode, dst)
|
||||
return newPlan.Scan(ci, oid, formatCode, src, dst)
|
||||
}
|
||||
if src == nil {
|
||||
// Ensure the pointer points to a zero version of the value
|
||||
dv.Elem().Set(reflect.Zero(dv.Type().Elem()))
|
||||
return nil
|
||||
}
|
||||
dv = dv.Elem()
|
||||
// If the pointer is to a nil pointer then set that before scanning
|
||||
if dv.Kind() == reflect.Ptr && dv.IsNil() {
|
||||
dv.Set(reflect.New(dv.Type().Elem()))
|
||||
}
|
||||
scanner = dv.Interface().(sql.Scanner)
|
||||
}
|
||||
|
||||
dt := (*DataType)(plan)
|
||||
|
|
@ -593,7 +609,25 @@ func (plan *scanPlanDataTypeAssignTo) Scan(ci *ConnInfo, oid uint32, formatCode
|
|||
type scanPlanSQLScanner struct{}
|
||||
|
||||
func (scanPlanSQLScanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
|
||||
scanner := dst.(sql.Scanner)
|
||||
scanner, ok := dst.(sql.Scanner)
|
||||
if !ok {
|
||||
dv := reflect.ValueOf(dst)
|
||||
if dv.Kind() != reflect.Ptr || !dv.Type().Elem().Implements(scannerType) {
|
||||
newPlan := ci.PlanScan(oid, formatCode, dst)
|
||||
return newPlan.Scan(ci, oid, formatCode, src, dst)
|
||||
}
|
||||
if src == nil {
|
||||
// Ensure the pointer points to a zero version of the value
|
||||
dv.Elem().Set(reflect.Zero(dv.Type()))
|
||||
return nil
|
||||
}
|
||||
dv = dv.Elem()
|
||||
// If the pointer is to a nil pointer then set that before scanning
|
||||
if dv.Kind() == reflect.Ptr && dv.IsNil() {
|
||||
dv.Set(reflect.New(dv.Type().Elem()))
|
||||
}
|
||||
scanner = dv.Interface().(sql.Scanner)
|
||||
}
|
||||
if src == nil {
|
||||
// This is necessary because interface value []byte:nil does not equal nil:nil for the binary format path and the
|
||||
// text format path would be converted to empty string.
|
||||
|
|
@ -761,6 +795,18 @@ func (scanPlanString) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byt
|
|||
return newPlan.Scan(ci, oid, formatCode, src, dst)
|
||||
}
|
||||
|
||||
var scannerType = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
|
||||
|
||||
func isScanner(dst interface{}) bool {
|
||||
if _, ok := dst.(sql.Scanner); ok {
|
||||
return true
|
||||
}
|
||||
if t := reflect.TypeOf(dst); t != nil && t.Kind() == reflect.Ptr && t.Elem().Implements(scannerType) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PlanScan prepares a plan to scan a value into dst.
|
||||
func (ci *ConnInfo) PlanScan(oid uint32, formatCode int16, dst interface{}) ScanPlan {
|
||||
switch formatCode {
|
||||
|
|
@ -825,13 +871,13 @@ func (ci *ConnInfo) PlanScan(oid uint32, formatCode int16, dst interface{}) Scan
|
|||
}
|
||||
|
||||
if dt != nil {
|
||||
if _, ok := dst.(sql.Scanner); ok {
|
||||
if isScanner(dst) {
|
||||
return (*scanPlanDataTypeSQLScanner)(dt)
|
||||
}
|
||||
return (*scanPlanDataTypeAssignTo)(dt)
|
||||
}
|
||||
|
||||
if _, ok := dst.(sql.Scanner); ok {
|
||||
if isScanner(dst) {
|
||||
return scanPlanSQLScanner{}
|
||||
}
|
||||
|
||||
|
|
@ -897,6 +943,7 @@ func init() {
|
|||
"_timestamptz": &TimestamptzArray{},
|
||||
"_uuid": &UUIDArray{},
|
||||
"_varchar": &VarcharArray{},
|
||||
"_json": &JSONArray{},
|
||||
"_jsonb": &JSONBArray{},
|
||||
"aclitem": &ACLItem{},
|
||||
"bit": &Bit{},
|
||||
|
|
|
|||
8
vendor/github.com/jackc/pgtype/timestamp.go
generated
vendored
8
vendor/github.com/jackc/pgtype/timestamp.go
generated
vendored
|
|
@ -46,6 +46,14 @@ func (dst *Timestamp) Set(src interface{}) error {
|
|||
} else {
|
||||
return dst.Set(*value)
|
||||
}
|
||||
case string:
|
||||
return dst.DecodeText(nil, []byte(value))
|
||||
case *string:
|
||||
if value == nil {
|
||||
*dst = Timestamp{Status: Null}
|
||||
} else {
|
||||
return dst.Set(*value)
|
||||
}
|
||||
case InfinityModifier:
|
||||
*dst = Timestamp{InfinityModifier: value, Status: Present}
|
||||
default:
|
||||
|
|
|
|||
8
vendor/github.com/jackc/pgtype/timestamptz.go
generated
vendored
8
vendor/github.com/jackc/pgtype/timestamptz.go
generated
vendored
|
|
@ -48,6 +48,14 @@ func (dst *Timestamptz) Set(src interface{}) error {
|
|||
} else {
|
||||
return dst.Set(*value)
|
||||
}
|
||||
case string:
|
||||
return dst.DecodeText(nil, []byte(value))
|
||||
case *string:
|
||||
if value == nil {
|
||||
*dst = Timestamptz{Status: Null}
|
||||
} else {
|
||||
return dst.Set(*value)
|
||||
}
|
||||
case InfinityModifier:
|
||||
*dst = Timestamptz{InfinityModifier: value, Status: Present}
|
||||
default:
|
||||
|
|
|
|||
1
vendor/github.com/jackc/pgtype/typed_array_gen.sh
generated
vendored
1
vendor/github.com/jackc/pgtype/typed_array_gen.sh
generated
vendored
|
|
@ -20,6 +20,7 @@ erb pgtype_array_type=ACLItemArray pgtype_element_type=ACLItem go_array_types=[]
|
|||
erb pgtype_array_type=HstoreArray pgtype_element_type=Hstore go_array_types=[]map[string]string element_type_name=hstore typed_array.go.erb > hstore_array.go
|
||||
erb pgtype_array_type=NumericArray pgtype_element_type=Numeric go_array_types=[]float32,[]*float32,[]float64,[]*float64,[]int64,[]*int64,[]uint64,[]*uint64 element_type_name=numeric typed_array.go.erb > numeric_array.go
|
||||
erb pgtype_array_type=UUIDArray pgtype_element_type=UUID go_array_types=[][16]byte,[][]byte,[]string,[]*string element_type_name=uuid typed_array.go.erb > uuid_array.go
|
||||
erb pgtype_array_type=JSONArray pgtype_element_type=JSON go_array_types=[]string,[][]byte,[]json.RawMessage element_type_name=json typed_array.go.erb > json_array.go
|
||||
erb pgtype_array_type=JSONBArray pgtype_element_type=JSONB go_array_types=[]string,[][]byte,[]json.RawMessage element_type_name=jsonb typed_array.go.erb > jsonb_array.go
|
||||
|
||||
# While the binary format is theoretically possible it is only practical to use the text format.
|
||||
|
|
|
|||
9
vendor/github.com/jackc/pgtype/uuid.go
generated
vendored
9
vendor/github.com/jackc/pgtype/uuid.go
generated
vendored
|
|
@ -18,14 +18,15 @@ func (dst *UUID) Set(src interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if value, ok := src.(interface{ Get() interface{} }); ok {
|
||||
switch value := src.(type) {
|
||||
case interface{ Get() interface{} }:
|
||||
value2 := value.Get()
|
||||
if value2 != value {
|
||||
return dst.Set(value2)
|
||||
}
|
||||
}
|
||||
|
||||
switch value := src.(type) {
|
||||
case fmt.Stringer:
|
||||
value2 := value.String()
|
||||
return dst.Set(value2)
|
||||
case [16]byte:
|
||||
*dst = UUID{Bytes: value, Status: Present}
|
||||
case []byte:
|
||||
|
|
|
|||
21
vendor/github.com/jackc/pgx/v4/CHANGELOG.md
generated
vendored
21
vendor/github.com/jackc/pgx/v4/CHANGELOG.md
generated
vendored
|
|
@ -1,3 +1,24 @@
|
|||
# 4.17.1 (August 27, 2022)
|
||||
|
||||
* Upgrade puddle to v1.3.0 - fixes context failing to cancel Acquire when acquire is creating resource which was introduced in v4.17.0 (James Hartig)
|
||||
* Fix atomic alignment on 32-bit platforms
|
||||
|
||||
# 4.17.0 (August 6, 2022)
|
||||
|
||||
* Upgrade pgconn to v1.13.0
|
||||
* Upgrade pgproto3 to v2.3.1
|
||||
* Upgrade pgtype to v1.12.0
|
||||
* Allow background pool connections to continue even if cause is canceled (James Hartig)
|
||||
* Add LoggerFunc (Gabor Szabad)
|
||||
* pgxpool: health check should avoid going below minConns (James Hartig)
|
||||
* Add pgxpool.Conn.Hijack()
|
||||
* Logging improvements (Stepan Rabotkin)
|
||||
|
||||
# 4.16.1 (May 7, 2022)
|
||||
|
||||
* Upgrade pgconn to v1.12.1
|
||||
* Fix explicitly prepared statements with describe statement cache mode
|
||||
|
||||
# 4.16.0 (April 21, 2022)
|
||||
|
||||
* Upgrade pgconn to v1.12.0
|
||||
|
|
|
|||
9
vendor/github.com/jackc/pgx/v4/README.md
generated
vendored
9
vendor/github.com/jackc/pgx/v4/README.md
generated
vendored
|
|
@ -1,6 +1,11 @@
|
|||
[](https://pkg.go.dev/github.com/jackc/pgx/v4)
|
||||
[](https://travis-ci.org/jackc/pgx)
|
||||
|
||||
---
|
||||
|
||||
This is the stable `v4` release. `v5` is now in beta testing with final release expected in September. See https://github.com/jackc/pgx/issues/1273 for more information. Please consider testing `v5`.
|
||||
|
||||
---
|
||||
# pgx - PostgreSQL Driver and Toolkit
|
||||
|
||||
pgx is a pure Go driver and toolkit for PostgreSQL.
|
||||
|
|
@ -185,3 +190,7 @@ Library for scanning data from a database into Go structs and more.
|
|||
### [https://github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5)
|
||||
|
||||
Adds GSSAPI / Kerberos authentication support.
|
||||
|
||||
### [https://github.com/vgarvardt/pgx-google-uuid](https://github.com/vgarvardt/pgx-google-uuid)
|
||||
|
||||
Adds support for [`github.com/google/uuid`](https://github.com/google/uuid).
|
||||
|
|
|
|||
44
vendor/github.com/jackc/pgx/v4/conn.go
generated
vendored
44
vendor/github.com/jackc/pgx/v4/conn.go
generated
vendored
|
|
@ -116,14 +116,14 @@ func ConnectConfig(ctx context.Context, connConfig *ConnConfig) (*Conn, error) {
|
|||
// ParseConfig creates a ConnConfig from a connection string. ParseConfig handles all options that pgconn.ParseConfig
|
||||
// does. In addition, it accepts the following options:
|
||||
//
|
||||
// statement_cache_capacity
|
||||
// The maximum size of the automatic statement cache. Set to 0 to disable automatic statement caching. Default: 512.
|
||||
// statement_cache_capacity
|
||||
// The maximum size of the automatic statement cache. Set to 0 to disable automatic statement caching. Default: 512.
|
||||
//
|
||||
// statement_cache_mode
|
||||
// Possible values: "prepare" and "describe". "prepare" will create prepared statements on the PostgreSQL server.
|
||||
// "describe" will use the anonymous prepared statement to describe a statement without creating a statement on the
|
||||
// server. "describe" is primarily useful when the environment does not allow prepared statements such as when
|
||||
// running a connection pooler like PgBouncer. Default: "prepare"
|
||||
// statement_cache_mode
|
||||
// Possible values: "prepare" and "describe". "prepare" will create prepared statements on the PostgreSQL server.
|
||||
// "describe" will use the anonymous prepared statement to describe a statement without creating a statement on the
|
||||
// server. "describe" is primarily useful when the environment does not allow prepared statements such as when
|
||||
// running a connection pooler like PgBouncer. Default: "prepare"
|
||||
//
|
||||
// prefer_simple_protocol
|
||||
// Possible values: "true" and "false". Use the simple protocol instead of extended protocol. Default: false
|
||||
|
|
@ -645,7 +645,7 @@ optionLoop:
|
|||
resultFormats = c.eqb.resultFormats
|
||||
}
|
||||
|
||||
if c.stmtcache != nil && c.stmtcache.Mode() == stmtcache.ModeDescribe {
|
||||
if c.stmtcache != nil && c.stmtcache.Mode() == stmtcache.ModeDescribe && !ok {
|
||||
rows.resultReader = c.pgConn.ExecParams(ctx, sql, c.eqb.paramValues, sd.ParamOIDs, c.eqb.paramFormats, resultFormats)
|
||||
} else {
|
||||
rows.resultReader = c.pgConn.ExecPrepared(ctx, sd.Name, c.eqb.paramValues, c.eqb.paramFormats, resultFormats)
|
||||
|
|
@ -710,6 +710,8 @@ func (c *Conn) QueryFunc(ctx context.Context, sql string, args []interface{}, sc
|
|||
// explicit transaction control statements are executed. The returned BatchResults must be closed before the connection
|
||||
// is used again.
|
||||
func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults {
|
||||
startTime := time.Now()
|
||||
|
||||
simpleProtocol := c.config.PreferSimpleProtocol
|
||||
var sb strings.Builder
|
||||
if simpleProtocol {
|
||||
|
|
@ -768,23 +770,23 @@ func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults {
|
|||
var err error
|
||||
sd, err = stmtCache.Get(ctx, bi.query)
|
||||
if err != nil {
|
||||
return &batchResults{ctx: ctx, conn: c, err: err}
|
||||
return c.logBatchResults(ctx, startTime, &batchResults{ctx: ctx, conn: c, err: err})
|
||||
}
|
||||
}
|
||||
|
||||
if len(sd.ParamOIDs) != len(bi.arguments) {
|
||||
return &batchResults{ctx: ctx, conn: c, err: fmt.Errorf("mismatched param and argument count")}
|
||||
return c.logBatchResults(ctx, startTime, &batchResults{ctx: ctx, conn: c, err: fmt.Errorf("mismatched param and argument count")})
|
||||
}
|
||||
|
||||
args, err := convertDriverValuers(bi.arguments)
|
||||
if err != nil {
|
||||
return &batchResults{ctx: ctx, conn: c, err: err}
|
||||
return c.logBatchResults(ctx, startTime, &batchResults{ctx: ctx, conn: c, err: err})
|
||||
}
|
||||
|
||||
for i := range args {
|
||||
err = c.eqb.AppendParam(c.connInfo, sd.ParamOIDs[i], args[i])
|
||||
if err != nil {
|
||||
return &batchResults{ctx: ctx, conn: c, err: err}
|
||||
return c.logBatchResults(ctx, startTime, &batchResults{ctx: ctx, conn: c, err: err})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -803,13 +805,29 @@ func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults {
|
|||
|
||||
mrr := c.pgConn.ExecBatch(ctx, batch)
|
||||
|
||||
return &batchResults{
|
||||
return c.logBatchResults(ctx, startTime, &batchResults{
|
||||
ctx: ctx,
|
||||
conn: c,
|
||||
mrr: mrr,
|
||||
b: b,
|
||||
ix: 0,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Conn) logBatchResults(ctx context.Context, startTime time.Time, results *batchResults) BatchResults {
|
||||
if results.err != nil {
|
||||
if c.shouldLog(LogLevelError) {
|
||||
endTime := time.Now()
|
||||
c.log(ctx, LogLevelError, "SendBatch", map[string]interface{}{"err": results.err, "time": endTime.Sub(startTime)})
|
||||
}
|
||||
}
|
||||
|
||||
if c.shouldLog(LogLevelInfo) {
|
||||
endTime := time.Now()
|
||||
c.log(ctx, LogLevelInfo, "SendBatch", map[string]interface{}{"batchLen": results.b.Len(), "time": endTime.Sub(startTime)})
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
func (c *Conn) sanitizeForSimpleQuery(sql string, args ...interface{}) (string, error) {
|
||||
|
|
|
|||
4
vendor/github.com/jackc/pgx/v4/copy_from.go
generated
vendored
4
vendor/github.com/jackc/pgx/v4/copy_from.go
generated
vendored
|
|
@ -153,13 +153,13 @@ func (ct *copyFrom) run(ctx context.Context) (int64, error) {
|
|||
<-doneChan
|
||||
|
||||
rowsAffected := commandTag.RowsAffected()
|
||||
endTime := time.Now()
|
||||
if err == nil {
|
||||
if ct.conn.shouldLog(LogLevelInfo) {
|
||||
endTime := time.Now()
|
||||
ct.conn.log(ctx, LogLevelInfo, "CopyFrom", map[string]interface{}{"tableName": ct.tableName, "columnNames": ct.columnNames, "time": endTime.Sub(startTime), "rowCount": rowsAffected})
|
||||
}
|
||||
} else if ct.conn.shouldLog(LogLevelError) {
|
||||
ct.conn.log(ctx, LogLevelError, "CopyFrom", map[string]interface{}{"err": err, "tableName": ct.tableName, "columnNames": ct.columnNames})
|
||||
ct.conn.log(ctx, LogLevelError, "CopyFrom", map[string]interface{}{"err": err, "tableName": ct.tableName, "columnNames": ct.columnNames, "time": endTime.Sub(startTime)})
|
||||
}
|
||||
|
||||
return rowsAffected, err
|
||||
|
|
|
|||
10
vendor/github.com/jackc/pgx/v4/go.mod
generated
vendored
10
vendor/github.com/jackc/pgx/v4/go.mod
generated
vendored
|
|
@ -7,15 +7,15 @@ require (
|
|||
github.com/cockroachdb/apd v1.1.0
|
||||
github.com/go-kit/log v0.1.0
|
||||
github.com/gofrs/uuid v4.0.0+incompatible
|
||||
github.com/jackc/pgconn v1.12.0
|
||||
github.com/jackc/pgconn v1.13.0
|
||||
github.com/jackc/pgio v1.0.0
|
||||
github.com/jackc/pgproto3/v2 v2.3.0
|
||||
github.com/jackc/pgtype v1.11.0
|
||||
github.com/jackc/puddle v1.2.1
|
||||
github.com/jackc/pgproto3/v2 v2.3.1
|
||||
github.com/jackc/pgtype v1.12.0
|
||||
github.com/jackc/puddle v1.3.0
|
||||
github.com/rs/zerolog v1.15.0
|
||||
github.com/shopspring/decimal v1.2.0
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
go.uber.org/zap v1.13.0
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec
|
||||
)
|
||||
|
|
|
|||
50
vendor/github.com/jackc/pgx/v4/go.sum
generated
vendored
50
vendor/github.com/jackc/pgx/v4/go.sum
generated
vendored
|
|
@ -30,14 +30,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU
|
|||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
|
||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
|
||||
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU=
|
||||
github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8=
|
||||
github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ=
|
||||
github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.12.0 h1:/RvQ24k3TnNdfBSW0ou9EOi5jx2cX7zfE8n2nLKuiP0=
|
||||
github.com/jackc/pgconn v1.12.0/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono=
|
||||
github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
|
||||
github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
|
|
@ -53,42 +47,28 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod
|
|||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns=
|
||||
github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.0 h1:brH0pCGBDkBW07HWlN/oSBXrmo3WB0UvZd1pIuDcL8Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||
github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs=
|
||||
github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.9.0 h1:/SH1RxEtltvJgsDqp3TbiTFApD3mey3iygpuEGeuBXk=
|
||||
github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0=
|
||||
github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38=
|
||||
github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.11.0 h1:u4uiGPz/1hryuXzyaBhSk6dnIyyG2683olG2OV+UUgs=
|
||||
github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
|
||||
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3 h1:JnPg/5Q9xVJGfjsO5CPUOjnJps1JaRUm8I9FXVCFK94=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.4 h1:5Ey/o5IfV7dYX6Znivq+N9MdK1S18OJI5OJq6EAAADw=
|
||||
github.com/jackc/puddle v1.1.4/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.2.0 h1:DNDKdn/pDrWvDWyT2FYvpZVE81OAhWrjCv19I9n108Q=
|
||||
github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.2.1 h1:gI8os0wpRXFd4FiAY2dWiqRK037tjj3t7rKFeO4X5iw=
|
||||
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
|
|
@ -130,12 +110,15 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
|
|
@ -160,8 +143,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
|
|
@ -171,6 +155,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -183,6 +168,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
|
|
@ -191,7 +177,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
|
|
@ -216,7 +201,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
|||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCMMIYYEVcAR5MDsuHlVkaIPDAF+5Dehzg8L5A=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
|
|
|
|||
8
vendor/github.com/jackc/pgx/v4/large_objects.go
generated
vendored
8
vendor/github.com/jackc/pgx/v4/large_objects.go
generated
vendored
|
|
@ -56,10 +56,10 @@ func (o *LargeObjects) Unlink(ctx context.Context, oid uint32) error {
|
|||
// A LargeObject is a large object stored on the server. It is only valid within the transaction that it was initialized
|
||||
// in. It uses the context it was initialized with for all operations. It implements these interfaces:
|
||||
//
|
||||
// io.Writer
|
||||
// io.Reader
|
||||
// io.Seeker
|
||||
// io.Closer
|
||||
// io.Writer
|
||||
// io.Reader
|
||||
// io.Seeker
|
||||
// io.Closer
|
||||
type LargeObject struct {
|
||||
ctx context.Context
|
||||
tx Tx
|
||||
|
|
|
|||
9
vendor/github.com/jackc/pgx/v4/logger.go
generated
vendored
9
vendor/github.com/jackc/pgx/v4/logger.go
generated
vendored
|
|
@ -47,9 +47,18 @@ type Logger interface {
|
|||
Log(ctx context.Context, level LogLevel, msg string, data map[string]interface{})
|
||||
}
|
||||
|
||||
// LoggerFunc is a wrapper around a function to satisfy the pgx.Logger interface
|
||||
type LoggerFunc func(ctx context.Context, level LogLevel, msg string, data map[string]interface{})
|
||||
|
||||
// Log delegates the logging request to the wrapped function
|
||||
func (f LoggerFunc) Log(ctx context.Context, level LogLevel, msg string, data map[string]interface{}) {
|
||||
f(ctx, level, msg, data)
|
||||
}
|
||||
|
||||
// LogLevelFromString converts log level string to constant
|
||||
//
|
||||
// Valid levels:
|
||||
//
|
||||
// trace
|
||||
// debug
|
||||
// info
|
||||
|
|
|
|||
39
vendor/github.com/jackc/pgx/v4/pgxpool/conn.go
generated
vendored
39
vendor/github.com/jackc/pgx/v4/pgxpool/conn.go
generated
vendored
|
|
@ -2,7 +2,7 @@ package pgxpool
|
|||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/jackc/pgconn"
|
||||
"github.com/jackc/pgx/v4"
|
||||
|
|
@ -26,9 +26,23 @@ func (c *Conn) Release() {
|
|||
res := c.res
|
||||
c.res = nil
|
||||
|
||||
now := time.Now()
|
||||
if conn.IsClosed() || conn.PgConn().IsBusy() || conn.PgConn().TxStatus() != 'I' || (now.Sub(res.CreationTime()) > c.p.maxConnLifetime) {
|
||||
if conn.IsClosed() || conn.PgConn().IsBusy() || conn.PgConn().TxStatus() != 'I' {
|
||||
res.Destroy()
|
||||
// Signal to the health check to run since we just destroyed a connections
|
||||
// and we might be below minConns now
|
||||
c.p.triggerHealthCheck()
|
||||
return
|
||||
}
|
||||
|
||||
// If the pool is consistently being used, we might never get to check the
|
||||
// lifetime of a connection since we only check idle connections in checkConnsHealth
|
||||
// so we also check the lifetime here and force a health check
|
||||
if c.p.isExpired(res) {
|
||||
atomic.AddInt64(&c.p.lifetimeDestroyCount, 1)
|
||||
res.Destroy()
|
||||
// Signal to the health check to run since we just destroyed a connections
|
||||
// and we might be below minConns now
|
||||
c.p.triggerHealthCheck()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -42,10 +56,29 @@ func (c *Conn) Release() {
|
|||
res.Release()
|
||||
} else {
|
||||
res.Destroy()
|
||||
// Signal to the health check to run since we just destroyed a connections
|
||||
// and we might be below minConns now
|
||||
c.p.triggerHealthCheck()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Hijack assumes ownership of the connection from the pool. Caller is responsible for closing the connection. Hijack
|
||||
// will panic if called on an already released or hijacked connection.
|
||||
func (c *Conn) Hijack() *pgx.Conn {
|
||||
if c.res == nil {
|
||||
panic("cannot hijack already released or hijacked connection")
|
||||
}
|
||||
|
||||
conn := c.Conn()
|
||||
res := c.res
|
||||
c.res = nil
|
||||
|
||||
res.Hijack()
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
func (c *Conn) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error) {
|
||||
return c.Conn().Exec(ctx, sql, arguments...)
|
||||
}
|
||||
|
|
|
|||
213
vendor/github.com/jackc/pgx/v4/pgxpool/pool.go
generated
vendored
213
vendor/github.com/jackc/pgx/v4/pgxpool/pool.go
generated
vendored
|
|
@ -3,9 +3,11 @@ package pgxpool
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgconn"
|
||||
|
|
@ -68,18 +70,37 @@ func (cr *connResource) getPoolRows(c *Conn, r pgx.Rows) *poolRows {
|
|||
return pr
|
||||
}
|
||||
|
||||
// detachedCtx wraps a context and will never be canceled, regardless of if
|
||||
// the wrapped one is cancelled. The Err() method will never return any errors.
|
||||
type detachedCtx struct {
|
||||
context.Context
|
||||
}
|
||||
|
||||
func (detachedCtx) Done() <-chan struct{} { return nil }
|
||||
func (detachedCtx) Deadline() (time.Time, bool) { return time.Time{}, false }
|
||||
func (detachedCtx) Err() error { return nil }
|
||||
|
||||
// Pool allows for connection reuse.
|
||||
type Pool struct {
|
||||
p *puddle.Pool
|
||||
config *Config
|
||||
beforeConnect func(context.Context, *pgx.ConnConfig) error
|
||||
afterConnect func(context.Context, *pgx.Conn) error
|
||||
beforeAcquire func(context.Context, *pgx.Conn) bool
|
||||
afterRelease func(*pgx.Conn) bool
|
||||
minConns int32
|
||||
maxConnLifetime time.Duration
|
||||
maxConnIdleTime time.Duration
|
||||
healthCheckPeriod time.Duration
|
||||
// 64 bit fields accessed with atomics must be at beginning of struct to guarantee alignment for certain 32-bit
|
||||
// architectures. See BUGS section of https://pkg.go.dev/sync/atomic and https://github.com/jackc/pgx/issues/1288.
|
||||
newConnsCount int64
|
||||
lifetimeDestroyCount int64
|
||||
idleDestroyCount int64
|
||||
|
||||
p *puddle.Pool
|
||||
config *Config
|
||||
beforeConnect func(context.Context, *pgx.ConnConfig) error
|
||||
afterConnect func(context.Context, *pgx.Conn) error
|
||||
beforeAcquire func(context.Context, *pgx.Conn) bool
|
||||
afterRelease func(*pgx.Conn) bool
|
||||
minConns int32
|
||||
maxConns int32
|
||||
maxConnLifetime time.Duration
|
||||
maxConnLifetimeJitter time.Duration
|
||||
maxConnIdleTime time.Duration
|
||||
healthCheckPeriod time.Duration
|
||||
healthCheckChan chan struct{}
|
||||
|
||||
closeOnce sync.Once
|
||||
closeChan chan struct{}
|
||||
|
|
@ -109,14 +130,19 @@ type Config struct {
|
|||
// MaxConnLifetime is the duration since creation after which a connection will be automatically closed.
|
||||
MaxConnLifetime time.Duration
|
||||
|
||||
// MaxConnLifetimeJitter is the duration after MaxConnLifetime to randomly decide to close a connection.
|
||||
// This helps prevent all connections from being closed at the exact same time, starving the pool.
|
||||
MaxConnLifetimeJitter time.Duration
|
||||
|
||||
// MaxConnIdleTime is the duration after which an idle connection will be automatically closed by the health check.
|
||||
MaxConnIdleTime time.Duration
|
||||
|
||||
// MaxConns is the maximum size of the pool. The default is the greater of 4 or runtime.NumCPU().
|
||||
MaxConns int32
|
||||
|
||||
// MinConns is the minimum size of the pool. The health check will increase the number of connections to this
|
||||
// amount if it had dropped below.
|
||||
// MinConns is the minimum size of the pool. After connection closes, the pool might dip below MinConns. A low
|
||||
// number of MinConns might mean the pool is empty after MaxConnLifetime until the health check has a chance
|
||||
// to create new connections.
|
||||
MinConns int32
|
||||
|
||||
// HealthCheckPeriod is the duration between checks of the health of idle connections.
|
||||
|
|
@ -164,24 +190,40 @@ func ConnectConfig(ctx context.Context, config *Config) (*Pool, error) {
|
|||
}
|
||||
|
||||
p := &Pool{
|
||||
config: config,
|
||||
beforeConnect: config.BeforeConnect,
|
||||
afterConnect: config.AfterConnect,
|
||||
beforeAcquire: config.BeforeAcquire,
|
||||
afterRelease: config.AfterRelease,
|
||||
minConns: config.MinConns,
|
||||
maxConnLifetime: config.MaxConnLifetime,
|
||||
maxConnIdleTime: config.MaxConnIdleTime,
|
||||
healthCheckPeriod: config.HealthCheckPeriod,
|
||||
closeChan: make(chan struct{}),
|
||||
config: config,
|
||||
beforeConnect: config.BeforeConnect,
|
||||
afterConnect: config.AfterConnect,
|
||||
beforeAcquire: config.BeforeAcquire,
|
||||
afterRelease: config.AfterRelease,
|
||||
minConns: config.MinConns,
|
||||
maxConns: config.MaxConns,
|
||||
maxConnLifetime: config.MaxConnLifetime,
|
||||
maxConnLifetimeJitter: config.MaxConnLifetimeJitter,
|
||||
maxConnIdleTime: config.MaxConnIdleTime,
|
||||
healthCheckPeriod: config.HealthCheckPeriod,
|
||||
healthCheckChan: make(chan struct{}, 1),
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
p.p = puddle.NewPool(
|
||||
func(ctx context.Context) (interface{}, error) {
|
||||
connConfig := p.config.ConnConfig
|
||||
// we ignore cancellation on the original context because its either from
|
||||
// the health check or its from a query and we don't want to cancel creating
|
||||
// a connection just because the original query was cancelled since that
|
||||
// could end up stampeding the server
|
||||
// this will keep any Values in the original context and will just ignore
|
||||
// cancellation
|
||||
// see https://github.com/jackc/pgx/issues/1259
|
||||
ctx = detachedCtx{ctx}
|
||||
|
||||
connConfig := p.config.ConnConfig.Copy()
|
||||
|
||||
// But we do want to ensure that a connect won't hang forever.
|
||||
if connConfig.ConnectTimeout <= 0 {
|
||||
connConfig.ConnectTimeout = 2 * time.Minute
|
||||
}
|
||||
|
||||
if p.beforeConnect != nil {
|
||||
connConfig = p.config.ConnConfig.Copy()
|
||||
if err := p.beforeConnect(ctx, connConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -223,7 +265,7 @@ func ConnectConfig(ctx context.Context, config *Config) (*Pool, error) {
|
|||
)
|
||||
|
||||
if !config.LazyConnect {
|
||||
if err := p.createIdleResources(ctx, int(p.minConns)); err != nil {
|
||||
if err := p.checkMinConns(); err != nil {
|
||||
// Couldn't create resources for minpool size. Close unhealthy pool.
|
||||
p.Close()
|
||||
return nil, err
|
||||
|
|
@ -251,14 +293,15 @@ func ConnectConfig(ctx context.Context, config *Config) (*Pool, error) {
|
|||
// pool_max_conn_lifetime: duration string
|
||||
// pool_max_conn_idle_time: duration string
|
||||
// pool_health_check_period: duration string
|
||||
// pool_max_conn_lifetime_jitter: duration string
|
||||
//
|
||||
// See Config for definitions of these arguments.
|
||||
//
|
||||
// # Example DSN
|
||||
// user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10
|
||||
// # Example DSN
|
||||
// user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10
|
||||
//
|
||||
// # Example URL
|
||||
// postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10
|
||||
// # Example URL
|
||||
// postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10
|
||||
func ParseConfig(connString string) (*Config, error) {
|
||||
connConfig, err := pgx.ParseConfig(connString)
|
||||
if err != nil {
|
||||
|
|
@ -331,6 +374,15 @@ func ParseConfig(connString string) (*Config, error) {
|
|||
config.HealthCheckPeriod = defaultHealthCheckPeriod
|
||||
}
|
||||
|
||||
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime_jitter"]; ok {
|
||||
delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime_jitter")
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid pool_max_conn_lifetime_jitter: %w", err)
|
||||
}
|
||||
config.MaxConnLifetimeJitter = d
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
|
|
@ -343,44 +395,105 @@ func (p *Pool) Close() {
|
|||
})
|
||||
}
|
||||
|
||||
func (p *Pool) isExpired(res *puddle.Resource) bool {
|
||||
now := time.Now()
|
||||
// Small optimization to avoid rand. If it's over lifetime AND jitter, immediately
|
||||
// return true.
|
||||
if now.Sub(res.CreationTime()) > p.maxConnLifetime+p.maxConnLifetimeJitter {
|
||||
return true
|
||||
}
|
||||
if p.maxConnLifetimeJitter == 0 {
|
||||
return false
|
||||
}
|
||||
jitterSecs := rand.Float64() * p.maxConnLifetimeJitter.Seconds()
|
||||
return now.Sub(res.CreationTime()) > p.maxConnLifetime+(time.Duration(jitterSecs)*time.Second)
|
||||
}
|
||||
|
||||
func (p *Pool) triggerHealthCheck() {
|
||||
go func() {
|
||||
// Destroy is asynchronous so we give it time to actually remove itself from
|
||||
// the pool otherwise we might try to check the pool size too soon
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
select {
|
||||
case p.healthCheckChan <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (p *Pool) backgroundHealthCheck() {
|
||||
ticker := time.NewTicker(p.healthCheckPeriod)
|
||||
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-p.closeChan:
|
||||
ticker.Stop()
|
||||
return
|
||||
case <-p.healthCheckChan:
|
||||
p.checkHealth()
|
||||
case <-ticker.C:
|
||||
p.checkIdleConnsHealth()
|
||||
p.checkMinConns()
|
||||
p.checkHealth()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pool) checkIdleConnsHealth() {
|
||||
resources := p.p.AcquireAllIdle()
|
||||
func (p *Pool) checkHealth() {
|
||||
for {
|
||||
// If checkMinConns failed we don't destroy any connections since we couldn't
|
||||
// even get to minConns
|
||||
if err := p.checkMinConns(); err != nil {
|
||||
// Should we log this error somewhere?
|
||||
break
|
||||
}
|
||||
if !p.checkConnsHealth() {
|
||||
// Since we didn't destroy any connections we can stop looping
|
||||
break
|
||||
}
|
||||
// Technically Destroy is asynchronous but 500ms should be enough for it to
|
||||
// remove it from the underlying pool
|
||||
select {
|
||||
case <-p.closeChan:
|
||||
return
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
// checkConnsHealth will check all idle connections, destroy a connection if
|
||||
// it's idle or too old, and returns true if any were destroyed
|
||||
func (p *Pool) checkConnsHealth() bool {
|
||||
var destroyed bool
|
||||
totalConns := p.Stat().TotalConns()
|
||||
resources := p.p.AcquireAllIdle()
|
||||
for _, res := range resources {
|
||||
if now.Sub(res.CreationTime()) > p.maxConnLifetime {
|
||||
// We're okay going under minConns if the lifetime is up
|
||||
if p.isExpired(res) && totalConns >= p.minConns {
|
||||
atomic.AddInt64(&p.lifetimeDestroyCount, 1)
|
||||
res.Destroy()
|
||||
} else if res.IdleDuration() > p.maxConnIdleTime {
|
||||
destroyed = true
|
||||
// Since Destroy is async we manually decrement totalConns.
|
||||
totalConns--
|
||||
} else if res.IdleDuration() > p.maxConnIdleTime && totalConns > p.minConns {
|
||||
atomic.AddInt64(&p.idleDestroyCount, 1)
|
||||
res.Destroy()
|
||||
destroyed = true
|
||||
// Since Destroy is async we manually decrement totalConns.
|
||||
totalConns--
|
||||
} else {
|
||||
res.ReleaseUnused()
|
||||
}
|
||||
}
|
||||
return destroyed
|
||||
}
|
||||
|
||||
func (p *Pool) checkMinConns() {
|
||||
for i := p.minConns - p.Stat().TotalConns(); i > 0; i-- {
|
||||
go func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
p.p.CreateResource(ctx)
|
||||
}()
|
||||
func (p *Pool) checkMinConns() error {
|
||||
// TotalConns can include ones that are being destroyed but we should have
|
||||
// sleep(500ms) around all of the destroys to help prevent that from throwing
|
||||
// off this check
|
||||
toCreate := p.minConns - p.Stat().TotalConns()
|
||||
if toCreate > 0 {
|
||||
return p.createIdleResources(context.Background(), int(toCreate))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pool) createIdleResources(parentCtx context.Context, targetResources int) error {
|
||||
|
|
@ -391,6 +504,7 @@ func (p *Pool) createIdleResources(parentCtx context.Context, targetResources in
|
|||
|
||||
for i := 0; i < targetResources; i++ {
|
||||
go func() {
|
||||
atomic.AddInt64(&p.newConnsCount, 1)
|
||||
err := p.p.CreateResource(ctx)
|
||||
errs <- err
|
||||
}()
|
||||
|
|
@ -460,7 +574,12 @@ func (p *Pool) Config() *Config { return p.config.Copy() }
|
|||
|
||||
// Stat returns a pgxpool.Stat struct with a snapshot of Pool statistics.
|
||||
func (p *Pool) Stat() *Stat {
|
||||
return &Stat{s: p.p.Stat()}
|
||||
return &Stat{
|
||||
s: p.p.Stat(),
|
||||
newConnsCount: atomic.LoadInt64(&p.newConnsCount),
|
||||
lifetimeDestroyCount: atomic.LoadInt64(&p.lifetimeDestroyCount),
|
||||
idleDestroyCount: atomic.LoadInt64(&p.idleDestroyCount),
|
||||
}
|
||||
}
|
||||
|
||||
// Exec acquires a connection from the Pool and executes the given SQL.
|
||||
|
|
@ -568,7 +687,7 @@ func (p *Pool) BeginTx(ctx context.Context, txOptions pgx.TxOptions) (pgx.Tx, er
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &Tx{t: t, c: c}, err
|
||||
return &Tx{t: t, c: c}, nil
|
||||
}
|
||||
|
||||
func (p *Pool) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error {
|
||||
|
|
|
|||
22
vendor/github.com/jackc/pgx/v4/pgxpool/stat.go
generated
vendored
22
vendor/github.com/jackc/pgx/v4/pgxpool/stat.go
generated
vendored
|
|
@ -8,7 +8,10 @@ import (
|
|||
|
||||
// Stat is a snapshot of Pool statistics.
|
||||
type Stat struct {
|
||||
s *puddle.Stat
|
||||
s *puddle.Stat
|
||||
newConnsCount int64
|
||||
lifetimeDestroyCount int64
|
||||
idleDestroyCount int64
|
||||
}
|
||||
|
||||
// AcquireCount returns the cumulative count of successful acquires from the pool.
|
||||
|
|
@ -62,3 +65,20 @@ func (s *Stat) MaxConns() int32 {
|
|||
func (s *Stat) TotalConns() int32 {
|
||||
return s.s.TotalResources()
|
||||
}
|
||||
|
||||
// NewConnsCount returns the cumulative count of new connections opened.
|
||||
func (s *Stat) NewConnsCount() int64 {
|
||||
return s.newConnsCount
|
||||
}
|
||||
|
||||
// MaxLifetimeDestroyCount returns the cumulative count of connections destroyed
|
||||
// because they exceeded MaxConnLifetime.
|
||||
func (s *Stat) MaxLifetimeDestroyCount() int64 {
|
||||
return s.lifetimeDestroyCount
|
||||
}
|
||||
|
||||
// MaxIdleDestroyCount returns the cumulative count of connections destroyed because
|
||||
// they exceeded MaxConnIdleTime.
|
||||
func (s *Stat) MaxIdleDestroyCount() int64 {
|
||||
return s.idleDestroyCount
|
||||
}
|
||||
|
|
|
|||
5
vendor/github.com/jackc/pgx/v4/rows.go
generated
vendored
5
vendor/github.com/jackc/pgx/v4/rows.go
generated
vendored
|
|
@ -143,14 +143,15 @@ func (rows *connRows) Close() {
|
|||
}
|
||||
|
||||
if rows.logger != nil {
|
||||
endTime := time.Now()
|
||||
|
||||
if rows.err == nil {
|
||||
if rows.logger.shouldLog(LogLevelInfo) {
|
||||
endTime := time.Now()
|
||||
rows.logger.log(rows.ctx, LogLevelInfo, "Query", map[string]interface{}{"sql": rows.sql, "args": logQueryArgs(rows.args), "time": endTime.Sub(rows.startTime), "rowCount": rows.rowCount})
|
||||
}
|
||||
} else {
|
||||
if rows.logger.shouldLog(LogLevelError) {
|
||||
rows.logger.log(rows.ctx, LogLevelError, "Query", map[string]interface{}{"err": rows.err, "sql": rows.sql, "args": logQueryArgs(rows.args)})
|
||||
rows.logger.log(rows.ctx, LogLevelError, "Query", map[string]interface{}{"err": rows.err, "sql": rows.sql, "time": endTime.Sub(rows.startTime), "args": logQueryArgs(rows.args)})
|
||||
}
|
||||
if rows.err != nil && rows.conn.stmtcache != nil {
|
||||
rows.conn.stmtcache.StatementErrored(rows.sql, rows.err)
|
||||
|
|
|
|||
16
vendor/github.com/jackc/puddle/.travis.yml
generated
vendored
16
vendor/github.com/jackc/puddle/.travis.yml
generated
vendored
|
|
@ -1,16 +0,0 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
- tip
|
||||
|
||||
env:
|
||||
global:
|
||||
- STRESS_TEST_DURATION=15s
|
||||
|
||||
script:
|
||||
- go test -v -race
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
4
vendor/github.com/jackc/puddle/CHANGELOG.md
generated
vendored
4
vendor/github.com/jackc/puddle/CHANGELOG.md
generated
vendored
|
|
@ -1,3 +1,7 @@
|
|||
# 1.3.0 (August 27, 2022)
|
||||
|
||||
* Acquire creates resources in background to allow creation to continue after Acquire is canceled (James Hartig)
|
||||
|
||||
# 1.2.1 (December 2, 2021)
|
||||
|
||||
* TryAcquire now does not block when background constructing resource
|
||||
|
|
|
|||
10
vendor/github.com/jackc/puddle/README.md
generated
vendored
10
vendor/github.com/jackc/puddle/README.md
generated
vendored
|
|
@ -1,5 +1,5 @@
|
|||
[](https://godoc.org/github.com/jackc/puddle)
|
||||
[](https://travis-ci.org/jackc/puddle)
|
||||

|
||||
|
||||
# Puddle
|
||||
|
||||
|
|
@ -49,6 +49,14 @@ res.Release()
|
|||
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
Puddle v1 is complete. No changes are planned.
|
||||
|
||||
* Bug reports and fixes are welcome.
|
||||
* New features will not be accepted if they can be feasibly implemented in a wrapper.
|
||||
* Performance optimizations will not be accepted unless the performance issue rises to the level of a bug.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
|
|
|||
74
vendor/github.com/jackc/puddle/pool.go
generated
vendored
74
vendor/github.com/jackc/puddle/pool.go
generated
vendored
|
|
@ -308,32 +308,64 @@ func (p *Pool) Acquire(ctx context.Context) (*Resource, error) {
|
|||
p.destructWG.Add(1)
|
||||
p.cond.L.Unlock()
|
||||
|
||||
value, err := p.constructResourceValue(ctx)
|
||||
p.cond.L.Lock()
|
||||
if err != nil {
|
||||
p.allResources = removeResource(p.allResources, res)
|
||||
p.destructWG.Done()
|
||||
// we create the resource in the background because the constructor might
|
||||
// outlive the context and we want to continue constructing it as long as
|
||||
// necessary but the acquire should be cancelled when the context is cancelled
|
||||
// see: https://github.com/jackc/pgx/issues/1287 and https://github.com/jackc/pgx/issues/1259
|
||||
constructErrCh := make(chan error)
|
||||
go func() {
|
||||
value, err := p.constructResourceValue(ctx)
|
||||
p.cond.L.Lock()
|
||||
if err != nil {
|
||||
p.allResources = removeResource(p.allResources, res)
|
||||
p.destructWG.Done()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if err == ctx.Err() {
|
||||
// we can't use default here in case we get here before the caller is
|
||||
// in the select
|
||||
select {
|
||||
case constructErrCh <- err:
|
||||
case <-ctx.Done():
|
||||
p.canceledAcquireCount += 1
|
||||
}
|
||||
default:
|
||||
p.cond.L.Unlock()
|
||||
p.cond.Signal()
|
||||
return
|
||||
}
|
||||
res.value = value
|
||||
|
||||
p.cond.L.Unlock()
|
||||
p.cond.Signal()
|
||||
return nil, err
|
||||
// assume that we will acquire it
|
||||
res.status = resourceStatusAcquired
|
||||
// we can't use default here in case we get here before the caller is
|
||||
// in the select
|
||||
select {
|
||||
case constructErrCh <- nil:
|
||||
p.emptyAcquireCount += 1
|
||||
p.acquireCount += 1
|
||||
p.acquireDuration += time.Duration(nanotime() - startNano)
|
||||
p.cond.L.Unlock()
|
||||
// we don't call Signal here we didn't change any of the resource pools
|
||||
case <-ctx.Done():
|
||||
p.canceledAcquireCount += 1
|
||||
p.cond.L.Unlock()
|
||||
// we don't call Signal here we didn't change any of the resopurce pools
|
||||
// since we couldn't send the constructed resource to the acquire
|
||||
// function that means the caller has stopped waiting and we should
|
||||
// just put this resource back in the pool
|
||||
p.releaseAcquiredResource(res, res.lastUsedNano)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case err := <-constructErrCh:
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// we don't call signal here because we didn't change the resource pools
|
||||
// at all so waking anything else up won't help
|
||||
return res, nil
|
||||
}
|
||||
|
||||
res.value = value
|
||||
res.status = resourceStatusAcquired
|
||||
p.emptyAcquireCount += 1
|
||||
p.acquireCount += 1
|
||||
p.acquireDuration += time.Duration(nanotime() - startNano)
|
||||
p.cond.L.Unlock()
|
||||
return res, nil
|
||||
}
|
||||
|
||||
if ctx.Done() == nil {
|
||||
|
|
@ -352,8 +384,8 @@ func (p *Pool) Acquire(ctx context.Context) (*Resource, error) {
|
|||
// do anything with it. Another goroutine might be waiting.
|
||||
go func() {
|
||||
<-waitChan
|
||||
p.cond.Signal()
|
||||
p.cond.L.Unlock()
|
||||
p.cond.Signal()
|
||||
}()
|
||||
|
||||
p.cond.L.Lock()
|
||||
|
|
|
|||
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at https://tip.golang.org/AUTHORS.
|
||||
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at https://tip.golang.org/CONTRIBUTORS.
|
||||
14
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
14
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
|
|
@ -306,6 +306,20 @@ func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error)
|
|||
return c.updateRegRFC(ctx, acct)
|
||||
}
|
||||
|
||||
// AccountKeyRollover attempts to transition a client's account key to a new key.
|
||||
// On success client's Key is updated which is not concurrency safe.
|
||||
// On failure an error will be returned.
|
||||
// The new key is already registered with the ACME provider if the following is true:
|
||||
// - error is of type acme.Error
|
||||
// - StatusCode should be 409 (Conflict)
|
||||
// - Location header will have the KID of the associated account
|
||||
//
|
||||
// More about account key rollover can be found at
|
||||
// https://tools.ietf.org/html/rfc8555#section-7.3.5.
|
||||
func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error {
|
||||
return c.accountKeyRollover(ctx, newKey)
|
||||
}
|
||||
|
||||
// Authorize performs the initial step in the pre-authorization flow,
|
||||
// as opposed to order-based flow.
|
||||
// The caller will then need to choose from and perform a set of returned
|
||||
|
|
|
|||
6
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
6
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
|
|
@ -41,7 +41,7 @@ type DirCache string
|
|||
|
||||
// Get reads a certificate data from the specified file name.
|
||||
func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
|
||||
name = filepath.Join(string(d), name)
|
||||
name = filepath.Join(string(d), filepath.Clean("/"+name))
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
|
|
@ -82,7 +82,7 @@ func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
|
|||
case <-ctx.Done():
|
||||
// Don't overwrite the file if the context was canceled.
|
||||
default:
|
||||
newName := filepath.Join(string(d), name)
|
||||
newName := filepath.Join(string(d), filepath.Clean("/"+name))
|
||||
err = os.Rename(tmp, newName)
|
||||
}
|
||||
}()
|
||||
|
|
@ -96,7 +96,7 @@ func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
|
|||
|
||||
// Delete removes the specified file name.
|
||||
func (d DirCache) Delete(ctx context.Context, name string) error {
|
||||
name = filepath.Join(string(d), name)
|
||||
name = filepath.Join(string(d), filepath.Clean("/"+name))
|
||||
var (
|
||||
err error
|
||||
done = make(chan struct{})
|
||||
|
|
|
|||
37
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
37
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
|
|
@ -33,6 +33,10 @@ const noKeyID = KeyID("")
|
|||
// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details.
|
||||
const noPayload = ""
|
||||
|
||||
// noNonce indicates that the nonce should be omitted from the protected header.
|
||||
// See jwsEncodeJSON for details.
|
||||
const noNonce = ""
|
||||
|
||||
// jsonWebSignature can be easily serialized into a JWS following
|
||||
// https://tools.ietf.org/html/rfc7515#section-3.2.
|
||||
type jsonWebSignature struct {
|
||||
|
|
@ -45,10 +49,15 @@ type jsonWebSignature struct {
|
|||
// The result is serialized in JSON format containing either kid or jwk
|
||||
// fields based on the provided KeyID value.
|
||||
//
|
||||
// If kid is non-empty, its quoted value is inserted in the protected head
|
||||
// The claimset is marshalled using json.Marshal unless it is a string.
|
||||
// In which case it is inserted directly into the message.
|
||||
//
|
||||
// If kid is non-empty, its quoted value is inserted in the protected header
|
||||
// as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted
|
||||
// as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive.
|
||||
//
|
||||
// If nonce is non-empty, its quoted value is inserted in the protected header.
|
||||
//
|
||||
// See https://tools.ietf.org/html/rfc7515#section-7.
|
||||
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, url string) ([]byte, error) {
|
||||
if key == nil {
|
||||
|
|
@ -58,20 +67,36 @@ func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, ur
|
|||
if alg == "" || !sha.Available() {
|
||||
return nil, ErrUnsupportedKey
|
||||
}
|
||||
var phead string
|
||||
headers := struct {
|
||||
Alg string `json:"alg"`
|
||||
KID string `json:"kid,omitempty"`
|
||||
JWK json.RawMessage `json:"jwk,omitempty"`
|
||||
Nonce string `json:"nonce,omitempty"`
|
||||
URL string `json:"url"`
|
||||
}{
|
||||
Alg: alg,
|
||||
Nonce: nonce,
|
||||
URL: url,
|
||||
}
|
||||
switch kid {
|
||||
case noKeyID:
|
||||
jwk, err := jwkEncode(key.Public())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phead = fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q,"url":%q}`, alg, jwk, nonce, url)
|
||||
headers.JWK = json.RawMessage(jwk)
|
||||
default:
|
||||
phead = fmt.Sprintf(`{"alg":%q,"kid":%q,"nonce":%q,"url":%q}`, alg, kid, nonce, url)
|
||||
headers.KID = string(kid)
|
||||
}
|
||||
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
||||
phJSON, err := json.Marshal(headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phead := base64.RawURLEncoding.EncodeToString([]byte(phJSON))
|
||||
var payload string
|
||||
if claimset != noPayload {
|
||||
if val, ok := claimset.(string); ok {
|
||||
payload = val
|
||||
} else {
|
||||
cs, err := json.Marshal(claimset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
39
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
39
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
|
|
@ -24,6 +24,9 @@ import (
|
|||
//
|
||||
// It only works with CAs implementing RFC 8555.
|
||||
func (c *Client) DeactivateReg(ctx context.Context) error {
|
||||
if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
|
||||
return err
|
||||
}
|
||||
url := string(c.accountKID(ctx))
|
||||
if url == "" {
|
||||
return ErrNoAccount
|
||||
|
|
@ -148,6 +151,42 @@ func responseAccount(res *http.Response) (*Account, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// accountKeyRollover attempts to perform account key rollover.
|
||||
// On success it will change client.Key to the new key.
|
||||
func (c *Client) accountKeyRollover(ctx context.Context, newKey crypto.Signer) error {
|
||||
dir, err := c.Discover(ctx) // Also required by c.accountKID
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kid := c.accountKID(ctx)
|
||||
if kid == noKeyID {
|
||||
return ErrNoAccount
|
||||
}
|
||||
oldKey, err := jwkEncode(c.Key.Public())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
payload := struct {
|
||||
Account string `json:"account"`
|
||||
OldKey json.RawMessage `json:"oldKey"`
|
||||
}{
|
||||
Account: string(kid),
|
||||
OldKey: json.RawMessage(oldKey),
|
||||
}
|
||||
inner, err := jwsEncodeJSON(payload, newKey, noKeyID, noNonce, dir.KeyChangeURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := c.post(ctx, nil, dir.KeyChangeURL, base64.RawURLEncoding.EncodeToString(inner), wantStatus(http.StatusOK))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
c.Key = newKey
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthorizeOrder initiates the order-based application for certificate issuance,
|
||||
// as opposed to pre-authorization in Authorize.
|
||||
// It is only supported by CAs implementing RFC 8555.
|
||||
|
|
|
|||
12
vendor/modules.txt
vendored
12
vendor/modules.txt
vendored
|
|
@ -361,7 +361,7 @@ github.com/hashicorp/go-retryablehttp
|
|||
github.com/inconshreveable/mousetrap
|
||||
# github.com/jackc/chunkreader/v2 v2.0.1
|
||||
github.com/jackc/chunkreader/v2
|
||||
# github.com/jackc/pgconn v1.12.0
|
||||
# github.com/jackc/pgconn v1.13.0
|
||||
github.com/jackc/pgconn
|
||||
github.com/jackc/pgconn/internal/ctxwatch
|
||||
github.com/jackc/pgconn/stmtcache
|
||||
|
|
@ -369,19 +369,19 @@ github.com/jackc/pgconn/stmtcache
|
|||
github.com/jackc/pgio
|
||||
# github.com/jackc/pgpassfile v1.0.0
|
||||
github.com/jackc/pgpassfile
|
||||
# github.com/jackc/pgproto3/v2 v2.3.0
|
||||
# github.com/jackc/pgproto3/v2 v2.3.1
|
||||
github.com/jackc/pgproto3/v2
|
||||
# github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b
|
||||
github.com/jackc/pgservicefile
|
||||
# github.com/jackc/pgtype v1.11.0
|
||||
# github.com/jackc/pgtype v1.12.0
|
||||
## explicit
|
||||
github.com/jackc/pgtype
|
||||
# github.com/jackc/pgx/v4 v4.16.0
|
||||
# github.com/jackc/pgx/v4 v4.17.1
|
||||
## explicit
|
||||
github.com/jackc/pgx/v4
|
||||
github.com/jackc/pgx/v4/internal/sanitize
|
||||
github.com/jackc/pgx/v4/pgxpool
|
||||
# github.com/jackc/puddle v1.2.1
|
||||
# github.com/jackc/puddle v1.3.0
|
||||
github.com/jackc/puddle
|
||||
# github.com/jmespath/go-jmespath v0.4.0
|
||||
github.com/jmespath/go-jmespath
|
||||
|
|
@ -626,7 +626,7 @@ go.opencensus.io/trace
|
|||
go.opencensus.io/trace/internal
|
||||
go.opencensus.io/trace/propagation
|
||||
go.opencensus.io/trace/tracestate
|
||||
# golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f
|
||||
# golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||
golang.org/x/crypto/acme
|
||||
golang.org/x/crypto/acme/autocert
|
||||
golang.org/x/crypto/cast5
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue