diff options
Diffstat (limited to 'vendor/github.com/jackc')
26 files changed, 382 insertions, 110 deletions
diff --git a/vendor/github.com/jackc/pgconn/CHANGELOG.md b/vendor/github.com/jackc/pgconn/CHANGELOG.md index 45c02f1e9..63933a3a9 100644 --- a/vendor/github.com/jackc/pgconn/CHANGELOG.md +++ b/vendor/github.com/jackc/pgconn/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.10.1 (November 20, 2021) + +* Close without waiting for response (Kei Kamikawa) +* Save waiting for network round-trip in CopyFrom (Rueian) +* Fix concurrency issue with ContextWatcher +* LRU.Get always checks context for cancellation / expiration (Georges Varouchas) + # 1.10.0 (July 24, 2021) * net.Timeout errors are no longer returned when a query is canceled via context. A wrapped context error is returned. diff --git a/vendor/github.com/jackc/pgconn/internal/ctxwatch/context_watcher.go b/vendor/github.com/jackc/pgconn/internal/ctxwatch/context_watcher.go index 391f0b791..b39cb3ee5 100644 --- a/vendor/github.com/jackc/pgconn/internal/ctxwatch/context_watcher.go +++ b/vendor/github.com/jackc/pgconn/internal/ctxwatch/context_watcher.go @@ -2,6 +2,7 @@ package ctxwatch import ( "context" + "sync" ) // ContextWatcher watches a context and performs an action when the context is canceled. It can watch one context at a @@ -10,8 +11,10 @@ type ContextWatcher struct { onCancel func() onUnwatchAfterCancel func() unwatchChan chan struct{} - watchInProgress bool - onCancelWasCalled bool + + lock sync.Mutex + watchInProgress bool + onCancelWasCalled bool } // NewContextWatcher returns a ContextWatcher. onCancel will be called when a watched context is canceled. @@ -29,6 +32,9 @@ func NewContextWatcher(onCancel func(), onUnwatchAfterCancel func()) *ContextWat // Watch starts watching ctx. If ctx is canceled then the onCancel function passed to NewContextWatcher will be called. func (cw *ContextWatcher) Watch(ctx context.Context) { + cw.lock.Lock() + defer cw.lock.Unlock() + if cw.watchInProgress { panic("Watch already in progress") } @@ -54,6 +60,9 @@ func (cw *ContextWatcher) Watch(ctx context.Context) { // Unwatch stops watching the previously watched context. If the onCancel function passed to NewContextWatcher was // called then onUnwatchAfterCancel will also be called. func (cw *ContextWatcher) Unwatch() { + cw.lock.Lock() + defer cw.lock.Unlock() + if cw.watchInProgress { cw.unwatchChan <- struct{}{} if cw.onCancelWasCalled { diff --git a/vendor/github.com/jackc/pgconn/pgconn.go b/vendor/github.com/jackc/pgconn/pgconn.go index 43b13e43a..382ad33c0 100644 --- a/vendor/github.com/jackc/pgconn/pgconn.go +++ b/vendor/github.com/jackc/pgconn/pgconn.go @@ -578,7 +578,6 @@ func (pgConn *PgConn) Close(ctx context.Context) error { // // See https://github.com/jackc/pgx/issues/637 pgConn.conn.Write([]byte{'X', 0, 0, 0, 4}) - pgConn.conn.Read(make([]byte, 1)) return pgConn.conn.Close() } @@ -605,7 +604,6 @@ func (pgConn *PgConn) asyncClose() { pgConn.conn.SetDeadline(deadline) pgConn.conn.Write([]byte{'X', 0, 0, 0, 4}) - pgConn.conn.Read(make([]byte, 1)) }() } @@ -1187,27 +1185,6 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co return nil, &writeError{err: err, safeToRetry: n == 0} } - // Read until copy in response or error. - var commandTag CommandTag - var pgErr error - pendingCopyInResponse := true - for pendingCopyInResponse { - msg, err := pgConn.receiveMessage() - if err != nil { - pgConn.asyncClose() - return nil, preferContextOverNetTimeoutError(ctx, err) - } - - switch msg := msg.(type) { - case *pgproto3.CopyInResponse: - pendingCopyInResponse = false - case *pgproto3.ErrorResponse: - pgErr = ErrorResponseToPgError(msg) - case *pgproto3.ReadyForQuery: - return commandTag, pgErr - } - } - // Send copy data abortCopyChan := make(chan struct{}) copyErrChan := make(chan error, 1) @@ -1246,6 +1223,7 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co } }() + var pgErr error var copyErr error for copyErr == nil && pgErr == nil { select { @@ -1282,6 +1260,7 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co } // Read results + var commandTag CommandTag for { msg, err := pgConn.receiveMessage() if err != nil { diff --git a/vendor/github.com/jackc/pgconn/stmtcache/lru.go b/vendor/github.com/jackc/pgconn/stmtcache/lru.go index f58f2ac34..90fb76c2f 100644 --- a/vendor/github.com/jackc/pgconn/stmtcache/lru.go +++ b/vendor/github.com/jackc/pgconn/stmtcache/lru.go @@ -42,6 +42,14 @@ func NewLRU(conn *pgconn.PgConn, mode int, cap int) *LRU { // Get returns the prepared statement description for sql preparing or describing the sql on the server as needed. func (c *LRU) Get(ctx context.Context, sql string) (*pgconn.StatementDescription, error) { + if ctx != context.Background() { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + } + // flush an outstanding bad statements txStatus := c.conn.TxStatus() if (txStatus == 'I' || txStatus == 'T') && len(c.stmtsToClear) > 0 { diff --git a/vendor/github.com/jackc/pgproto3/v2/backend.go b/vendor/github.com/jackc/pgproto3/v2/backend.go index e9ba38fc3..9c42ad02e 100644 --- a/vendor/github.com/jackc/pgproto3/v2/backend.go +++ b/vendor/github.com/jackc/pgproto3/v2/backend.go @@ -21,6 +21,7 @@ type Backend struct { describe Describe execute Execute flush Flush + functionCall FunctionCall gssEncRequest GSSEncRequest parse Parse query Query @@ -29,10 +30,11 @@ type Backend struct { sync Sync terminate Terminate - bodyLen int - msgType byte - partialMsg bool - authType uint32 + bodyLen int + msgType byte + partialMsg bool + authType uint32 + } const ( @@ -125,6 +127,8 @@ func (b *Backend) Receive() (FrontendMessage, error) { msg = &b.describe case 'E': msg = &b.execute + case 'F': + msg = &b.functionCall case 'f': msg = &b.copyFail case 'd': diff --git a/vendor/github.com/jackc/pgproto3/v2/function_call.go b/vendor/github.com/jackc/pgproto3/v2/function_call.go new file mode 100644 index 000000000..b3a22c4fb --- /dev/null +++ b/vendor/github.com/jackc/pgproto3/v2/function_call.go @@ -0,0 +1,94 @@ +package pgproto3 + +import ( + "encoding/binary" + "github.com/jackc/pgio" +) + +type FunctionCall struct { + Function uint32 + ArgFormatCodes []uint16 + Arguments [][]byte + ResultFormatCode uint16 +} + +// Frontend identifies this message as sendable by a PostgreSQL frontend. +func (*FunctionCall) Frontend() {} + +// Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message +// type identifier and 4 byte message length. +func (dst *FunctionCall) Decode(src []byte) error { + *dst = FunctionCall{} + rp := 0 + // Specifies the object ID of the function to call. + dst.Function = binary.BigEndian.Uint32(src[rp:]) + rp += 4 + // The number of argument format codes that follow (denoted C below). + // This can be zero to indicate that there are no arguments or that the arguments all use the default format (text); + // or one, in which case the specified format code is applied to all arguments; + // or it can equal the actual number of arguments. + nArgumentCodes := int(binary.BigEndian.Uint16(src[rp:])) + rp += 2 + argumentCodes := make([]uint16, nArgumentCodes) + for i := 0; i < nArgumentCodes; i++ { + // The argument format codes. Each must presently be zero (text) or one (binary). + ac := binary.BigEndian.Uint16(src[rp:]) + if ac != 0 && ac != 1 { + return &invalidMessageFormatErr{messageType: "FunctionCall"} + } + argumentCodes[i] = ac + rp += 2 + } + dst.ArgFormatCodes = argumentCodes + + // Specifies the number of arguments being supplied to the function. + nArguments := int(binary.BigEndian.Uint16(src[rp:])) + rp += 2 + arguments := make([][]byte, nArguments) + for i := 0; i < nArguments; i++ { + // The length of the argument value, in bytes (this count does not include itself). Can be zero. + // As a special case, -1 indicates a NULL argument value. No value bytes follow in the NULL case. + argumentLength := int(binary.BigEndian.Uint32(src[rp:])) + rp += 4 + if argumentLength == -1 { + arguments[i] = nil + } else { + // The value of the argument, in the format indicated by the associated format code. n is the above length. + argumentValue := src[rp : rp+argumentLength] + rp += argumentLength + arguments[i] = argumentValue + } + } + dst.Arguments = arguments + // The format code for the function result. Must presently be zero (text) or one (binary). + resultFormatCode := binary.BigEndian.Uint16(src[rp:]) + if resultFormatCode != 0 && resultFormatCode != 1 { + return &invalidMessageFormatErr{messageType: "FunctionCall"} + } + dst.ResultFormatCode = resultFormatCode + return nil +} + +// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length. +func (src *FunctionCall) Encode(dst []byte) []byte { + dst = append(dst, 'F') + sp := len(dst) + dst = pgio.AppendUint32(dst, 0) // Unknown length, set it at the end + dst = pgio.AppendUint32(dst, src.Function) + dst = pgio.AppendUint16(dst, uint16(len(src.ArgFormatCodes))) + for _, argFormatCode := range src.ArgFormatCodes { + dst = pgio.AppendUint16(dst, argFormatCode) + } + dst = pgio.AppendUint16(dst, uint16(len(src.Arguments))) + for _, argument := range src.Arguments { + if argument == nil { + dst = pgio.AppendInt32(dst, -1) + } else { + dst = pgio.AppendInt32(dst, int32(len(argument))) + dst = append(dst, argument...) + } + } + dst = pgio.AppendUint16(dst, src.ResultFormatCode) + pgio.SetInt32(dst[sp:], int32(len(dst[sp:]))) + return dst +} diff --git a/vendor/github.com/jackc/pgproto3/v2/sasl_initial_response.go b/vendor/github.com/jackc/pgproto3/v2/sasl_initial_response.go index f7e5f36a9..f862f2a85 100644 --- a/vendor/github.com/jackc/pgproto3/v2/sasl_initial_response.go +++ b/vendor/github.com/jackc/pgproto3/v2/sasl_initial_response.go @@ -64,7 +64,7 @@ func (src SASLInitialResponse) MarshalJSON() ([]byte, error) { }{ Type: "SASLInitialResponse", AuthMechanism: src.AuthMechanism, - Data: hex.EncodeToString(src.Data), + Data: string(src.Data), }) } diff --git a/vendor/github.com/jackc/pgproto3/v2/sasl_response.go b/vendor/github.com/jackc/pgproto3/v2/sasl_response.go index 41fb4c397..d402759a5 100644 --- a/vendor/github.com/jackc/pgproto3/v2/sasl_response.go +++ b/vendor/github.com/jackc/pgproto3/v2/sasl_response.go @@ -38,7 +38,7 @@ func (src SASLResponse) MarshalJSON() ([]byte, error) { Data string }{ Type: "SASLResponse", - Data: hex.EncodeToString(src.Data), + Data: string(src.Data), }) } diff --git a/vendor/github.com/jackc/pgtype/.travis.yml b/vendor/github.com/jackc/pgtype/.travis.yml deleted file mode 100644 index d67627350..000000000 --- a/vendor/github.com/jackc/pgtype/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -# source: https://github.com/jackc/pgx/blob/master/.travis.yml - -language: go - -go: - - 1.14.x - - 1.13.x - - tip - -# Derived from https://github.com/lib/pq/blob/master/.travis.yml -before_install: - - ./travis/before_install.bash - -env: - global: - - GO111MODULE=on - - PGX_TEST_DATABASE=postgres://pgx_md5:secret@127.0.0.1/pgx_test - - matrix: - - PGVERSION=12 - - PGVERSION=11 - - PGVERSION=10 - - PGVERSION=9.6 - - PGVERSION=9.5 - -before_script: - - ./travis/before_script.bash - -script: - - ./travis/script.bash - -matrix: - allow_failures: - - go: tip
\ No newline at end of file diff --git a/vendor/github.com/jackc/pgtype/CHANGELOG.md b/vendor/github.com/jackc/pgtype/CHANGELOG.md index 64d96fa00..84173f186 100644 --- a/vendor/github.com/jackc/pgtype/CHANGELOG.md +++ b/vendor/github.com/jackc/pgtype/CHANGELOG.md @@ -1,3 +1,17 @@ +# 1.9.0 (November 20, 2021) + +* Fix binary hstore null decoding +* Add shopspring/decimal.NullDecimal support to integration (Eli Treuherz) +* Inet.Set supports bare IP address (Carl Dunham) +* Add zeronull.Float8 +* Fix NULL being lost when scanning unknown OID into sql.Scanner +* Fix BPChar.AssignTo **rune +* Add support for fmt.Stringer and driver.Valuer in String fields encoding (Jan Dubsky) +* Fix really big timestamp(tz)s binary format parsing (e.g. year 294276) (Jim Tsao) +* Support `map[string]*string` as hstore (Adrian Sieger) +* Fix parsing text array with negative bounds +* Add infinity support for numeric (Jim Tsao) + # 1.8.1 (July 24, 2021) * Cleaned up Go module dependency chain diff --git a/vendor/github.com/jackc/pgtype/array.go b/vendor/github.com/jackc/pgtype/array.go index 3d5930c1c..174007c17 100644 --- a/vendor/github.com/jackc/pgtype/array.go +++ b/vendor/github.com/jackc/pgtype/array.go @@ -305,7 +305,7 @@ func arrayParseInteger(buf *bytes.Buffer) (int32, error) { return 0, err } - if '0' <= r && r <= '9' { + if ('0' <= r && r <= '9') || r == '-' { s.WriteRune(r) } else { buf.UnreadRune() diff --git a/vendor/github.com/jackc/pgtype/bpchar.go b/vendor/github.com/jackc/pgtype/bpchar.go index e4d058e92..c5fa42eac 100644 --- a/vendor/github.com/jackc/pgtype/bpchar.go +++ b/vendor/github.com/jackc/pgtype/bpchar.go @@ -2,6 +2,7 @@ package pgtype import ( "database/sql/driver" + "fmt" ) // BPChar is fixed-length, blank padded char type @@ -20,7 +21,8 @@ func (dst BPChar) Get() interface{} { // AssignTo assigns from src to dst. func (src *BPChar) AssignTo(dst interface{}) error { - if src.Status == Present { + switch src.Status { + case Present: switch v := dst.(type) { case *rune: runes := []rune(src.String) @@ -28,9 +30,24 @@ func (src *BPChar) AssignTo(dst interface{}) error { *v = runes[0] return nil } + case *string: + *v = src.String + return nil + case *[]byte: + *v = make([]byte, len(src.String)) + copy(*v, src.String) + return nil + default: + if nextDst, retry := GetAssignToDstType(dst); retry { + return src.AssignTo(nextDst) + } + return fmt.Errorf("unable to assign to %T", dst) } + case Null: + return NullAssignTo(dst) } - return (*Text)(src).AssignTo(dst) + + return fmt.Errorf("cannot decode %#v into %T", src, dst) } func (BPChar) PreferredResultFormat() int16 { diff --git a/vendor/github.com/jackc/pgtype/hstore.go b/vendor/github.com/jackc/pgtype/hstore.go index 18b413c6b..f46eeaf62 100644 --- a/vendor/github.com/jackc/pgtype/hstore.go +++ b/vendor/github.com/jackc/pgtype/hstore.go @@ -40,6 +40,16 @@ func (dst *Hstore) Set(src interface{}) error { m[k] = Text{String: v, Status: Present} } *dst = Hstore{Map: m, Status: Present} + case map[string]*string: + m := make(map[string]Text, len(value)) + for k, v := range value { + if v == nil { + m[k] = Text{Status: Null} + } else { + m[k] = Text{String: *v, Status: Present} + } + } + *dst = Hstore{Map: m, Status: Present} default: return fmt.Errorf("cannot convert %v to Hstore", src) } @@ -71,6 +81,19 @@ func (src *Hstore) AssignTo(dst interface{}) error { (*v)[k] = val.String } return nil + case *map[string]*string: + *v = make(map[string]*string, len(src.Map)) + for k, val := range src.Map { + switch val.Status { + case Null: + (*v)[k] = nil + case Present: + (*v)[k] = &val.String + default: + return fmt.Errorf("cannot decode %#v into %T", src, dst) + } + } + return nil default: if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) @@ -142,8 +165,8 @@ func (dst *Hstore) DecodeBinary(ci *ConnInfo, src []byte) error { var valueBuf []byte if valueLen >= 0 { valueBuf = src[rp : rp+valueLen] + rp += valueLen } - rp += valueLen var value Text err := value.DecodeBinary(ci, valueBuf) diff --git a/vendor/github.com/jackc/pgtype/inet.go b/vendor/github.com/jackc/pgtype/inet.go index 1645334e3..f35f88bad 100644 --- a/vendor/github.com/jackc/pgtype/inet.go +++ b/vendor/github.com/jackc/pgtype/inet.go @@ -47,7 +47,15 @@ func (dst *Inet) Set(src interface{}) error { case string: ip, ipnet, err := net.ParseCIDR(value) if err != nil { - return err + 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) + } } ipnet.IP = ip *dst = Inet{IPNet: ipnet, Status: Present} diff --git a/vendor/github.com/jackc/pgtype/numeric.go b/vendor/github.com/jackc/pgtype/numeric.go index a7efa704c..a939625be 100644 --- a/vendor/github.com/jackc/pgtype/numeric.go +++ b/vendor/github.com/jackc/pgtype/numeric.go @@ -18,6 +18,12 @@ const nbase = 10000 const ( pgNumericNaN = 0x00000000c0000000 pgNumericNaNSign = 0xc000 + + pgNumericPosInf = 0x00000000d0000000 + pgNumericPosInfSign = 0xd000 + + pgNumericNegInf = 0x00000000f0000000 + pgNumericNegInfSign = 0xf000 ) var big0 *big.Int = big.NewInt(0) @@ -49,10 +55,11 @@ var bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase) var bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase) type Numeric struct { - Int *big.Int - Exp int32 - Status Status - NaN bool + Int *big.Int + Exp int32 + Status Status + NaN bool + InfinityModifier InfinityModifier } func (dst *Numeric) Set(src interface{}) error { @@ -73,6 +80,12 @@ func (dst *Numeric) Set(src interface{}) error { if math.IsNaN(float64(value)) { *dst = Numeric{Status: Present, NaN: true} return nil + } else if math.IsInf(float64(value), 1) { + *dst = Numeric{Status: Present, InfinityModifier: Infinity} + return nil + } else if math.IsInf(float64(value), -1) { + *dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity} + return nil } num, exp, err := parseNumericString(strconv.FormatFloat(float64(value), 'f', -1, 64)) if err != nil { @@ -83,6 +96,12 @@ func (dst *Numeric) Set(src interface{}) error { if math.IsNaN(value) { *dst = Numeric{Status: Present, NaN: true} return nil + } else if math.IsInf(value, 1) { + *dst = Numeric{Status: Present, InfinityModifier: Infinity} + return nil + } else if math.IsInf(value, -1) { + *dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity} + return nil } num, exp, err := parseNumericString(strconv.FormatFloat(value, 'f', -1, 64)) if err != nil { @@ -193,6 +212,8 @@ func (dst *Numeric) Set(src interface{}) error { } else { return dst.Set(*value) } + case InfinityModifier: + *dst = Numeric{InfinityModifier: value, Status: Present} default: if originalSrc, ok := underlyingNumberType(src); ok { return dst.Set(originalSrc) @@ -206,6 +227,9 @@ func (dst *Numeric) Set(src interface{}) error { func (dst Numeric) Get() interface{} { switch dst.Status { case Present: + if dst.InfinityModifier != None { + return dst.InfinityModifier + } return dst case Null: return nil @@ -385,6 +409,10 @@ func (dst *Numeric) toBigInt() (*big.Int, error) { func (src *Numeric) toFloat64() (float64, error) { if src.NaN { return math.NaN(), nil + } else if src.InfinityModifier == Infinity { + return math.Inf(1), nil + } else if src.InfinityModifier == NegativeInfinity { + return math.Inf(-1), nil } buf := make([]byte, 0, 32) @@ -409,6 +437,12 @@ func (dst *Numeric) DecodeText(ci *ConnInfo, src []byte) error { if string(src) == "NaN" { *dst = Numeric{Status: Present, NaN: true} return nil + } else if string(src) == "Infinity" { + *dst = Numeric{Status: Present, InfinityModifier: Infinity} + return nil + } else if string(src) == "-Infinity" { + *dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity} + return nil } num, exp, err := parseNumericString(string(src)) @@ -452,11 +486,11 @@ func (dst *Numeric) DecodeBinary(ci *ConnInfo, src []byte) error { } rp := 0 - ndigits := int16(binary.BigEndian.Uint16(src[rp:])) + ndigits := binary.BigEndian.Uint16(src[rp:]) rp += 2 weight := int16(binary.BigEndian.Uint16(src[rp:])) rp += 2 - sign := uint16(binary.BigEndian.Uint16(src[rp:])) + sign := binary.BigEndian.Uint16(src[rp:]) rp += 2 dscale := int16(binary.BigEndian.Uint16(src[rp:])) rp += 2 @@ -464,6 +498,12 @@ func (dst *Numeric) DecodeBinary(ci *ConnInfo, src []byte) error { if sign == pgNumericNaNSign { *dst = Numeric{Status: Present, NaN: true} return nil + } else if sign == pgNumericPosInfSign { + *dst = Numeric{Status: Present, InfinityModifier: Infinity} + return nil + } else if sign == pgNumericNegInfSign { + *dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity} + return nil } if ndigits == 0 { @@ -504,7 +544,7 @@ func (dst *Numeric) DecodeBinary(ci *ConnInfo, src []byte) error { exp := (int32(weight) - int32(ndigits) + 1) * 4 if dscale > 0 { - fracNBaseDigits := ndigits - weight - 1 + fracNBaseDigits := int16(int32(ndigits) - int32(weight) - 1) fracDecimalDigits := fracNBaseDigits * 4 if dscale > fracDecimalDigits { @@ -575,6 +615,12 @@ func (src Numeric) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { if src.NaN { buf = append(buf, "NaN"...) return buf, nil + } else if src.InfinityModifier == Infinity { + buf = append(buf, "Infinity"...) + return buf, nil + } else if src.InfinityModifier == NegativeInfinity { + buf = append(buf, "-Infinity"...) + return buf, nil } buf = append(buf, src.Int.String()...) @@ -594,6 +640,12 @@ func (src Numeric) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) { if src.NaN { buf = pgio.AppendUint64(buf, pgNumericNaN) return buf, nil + } else if src.InfinityModifier == Infinity { + buf = pgio.AppendUint64(buf, pgNumericPosInf) + return buf, nil + } else if src.InfinityModifier == NegativeInfinity { + buf = pgio.AppendUint64(buf, pgNumericNegInf) + return buf, nil } var sign int16 diff --git a/vendor/github.com/jackc/pgtype/pgtype.go b/vendor/github.com/jackc/pgtype/pgtype.go index 4a6808449..200fb5626 100644 --- a/vendor/github.com/jackc/pgtype/pgtype.go +++ b/vendor/github.com/jackc/pgtype/pgtype.go @@ -588,7 +588,11 @@ type scanPlanSQLScanner struct{} func (scanPlanSQLScanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { scanner := dst.(sql.Scanner) - if formatCode == BinaryFormatCode { + 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. + return scanner.Scan(nil) + } else if formatCode == BinaryFormatCode { return scanner.Scan(src) } else { return scanner.Scan(string(src)) diff --git a/vendor/github.com/jackc/pgtype/text.go b/vendor/github.com/jackc/pgtype/text.go index 6b01d1b49..a01815d94 100644 --- a/vendor/github.com/jackc/pgtype/text.go +++ b/vendor/github.com/jackc/pgtype/text.go @@ -39,7 +39,37 @@ func (dst *Text) Set(src interface{}) error { } else { *dst = Text{String: string(value), Status: Present} } + case fmt.Stringer: + if value == fmt.Stringer(nil) { + *dst = Text{Status: Null} + } else { + *dst = Text{String: value.String(), Status: Present} + } default: + // Cannot be part of the switch: If Value() returns nil on + // non-string, we should still try to checks the underlying type + // using reflection. + // + // For example the struct might implement driver.Valuer with + // pointer receiver and fmt.Stringer with value receiver. + if value, ok := src.(driver.Valuer); ok { + if value == driver.Valuer(nil) { + *dst = Text{Status: Null} + return nil + } else { + v, err := value.Value() + if err != nil { + return fmt.Errorf("driver.Valuer Value() method failed: %w", err) + } + + // Handles also v == nil case. + if s, ok := v.(string); ok { + *dst = Text{String: s, Status: Present} + return nil + } + } + } + if originalSrc, ok := underlyingStringType(src); ok { return dst.Set(originalSrc) } diff --git a/vendor/github.com/jackc/pgtype/timestamp.go b/vendor/github.com/jackc/pgtype/timestamp.go index 466441158..a184d232d 100644 --- a/vendor/github.com/jackc/pgtype/timestamp.go +++ b/vendor/github.com/jackc/pgtype/timestamp.go @@ -141,8 +141,10 @@ func (dst *Timestamp) DecodeBinary(ci *ConnInfo, src []byte) error { case negativeInfinityMicrosecondOffset: *dst = Timestamp{Status: Present, InfinityModifier: -Infinity} default: - microsecSinceUnixEpoch := microsecFromUnixEpochToY2K + microsecSinceY2K - tim := time.Unix(microsecSinceUnixEpoch/1000000, (microsecSinceUnixEpoch%1000000)*1000).UTC() + tim := time.Unix( + microsecFromUnixEpochToY2K/1000000+microsecSinceY2K/1000000, + (microsecFromUnixEpochToY2K%1000000*1000)+(microsecSinceY2K%1000000*1000), + ) *dst = Timestamp{Time: tim, Status: Present} } diff --git a/vendor/github.com/jackc/pgtype/timestamptz.go b/vendor/github.com/jackc/pgtype/timestamptz.go index e0743060b..299a8668a 100644 --- a/vendor/github.com/jackc/pgtype/timestamptz.go +++ b/vendor/github.com/jackc/pgtype/timestamptz.go @@ -148,8 +148,10 @@ func (dst *Timestamptz) DecodeBinary(ci *ConnInfo, src []byte) error { case negativeInfinityMicrosecondOffset: *dst = Timestamptz{Status: Present, InfinityModifier: -Infinity} default: - microsecSinceUnixEpoch := microsecFromUnixEpochToY2K + microsecSinceY2K - tim := time.Unix(microsecSinceUnixEpoch/1000000, (microsecSinceUnixEpoch%1000000)*1000) + tim := time.Unix( + microsecFromUnixEpochToY2K/1000000+microsecSinceY2K/1000000, + (microsecFromUnixEpochToY2K%1000000*1000)+(microsecSinceY2K%1000000*1000), + ) *dst = Timestamptz{Time: tim, Status: Present} } diff --git a/vendor/github.com/jackc/pgx/v4/CHANGELOG.md b/vendor/github.com/jackc/pgx/v4/CHANGELOG.md index ef4a2029a..f74d2afb6 100644 --- a/vendor/github.com/jackc/pgx/v4/CHANGELOG.md +++ b/vendor/github.com/jackc/pgx/v4/CHANGELOG.md @@ -1,3 +1,15 @@ +# 4.14.0 (November 20, 2021) + +* Upgrade pgconn to v1.10.1 +* Upgrade pgproto3 to v2.2.0 +* Upgrade pgtype to v1.9.0 +* Upgrade puddle to v1.2.0 +* Add QueryFunc to BatchResults +* Add context options to zerologadapter (Thomas Frössman) +* Add zerologadapter.NewContextLogger (urso) +* Eager initialize minpoolsize on connect (Daniel) +* Unpin memory used by large queries immediately after use + # 4.13.0 (July 24, 2021) * Trimmed pseudo-dependencies in Go modules from other packages tests diff --git a/vendor/github.com/jackc/pgx/v4/README.md b/vendor/github.com/jackc/pgx/v4/README.md index 732320447..110d4f02e 100644 --- a/vendor/github.com/jackc/pgx/v4/README.md +++ b/vendor/github.com/jackc/pgx/v4/README.md @@ -73,7 +73,7 @@ pgx supports many features beyond what is available through `database/sql`: * Single-round trip query mode * Full TLS connection control * Binary format support for custom types (allows for much quicker encoding/decoding) -* Copy protocol support for faster bulk data loads +* COPY protocol support for faster bulk data loads * Extendable logging support including built-in support for `log15adapter`, [`logrus`](https://github.com/sirupsen/logrus), [`zap`](https://github.com/uber-go/zap), and [`zerolog`](https://github.com/rs/zerolog) * Connection pool with after-connect hook for arbitrary connection setup * Listen / notify @@ -149,7 +149,7 @@ In addition, there are tests specific for PgBouncer that will be executed if `PG ## Supported Go and PostgreSQL Versions -pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.15 and higher and PostgreSQL 9.6 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/). +pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.16 and higher and PostgreSQL 10 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/). ## Version Policy diff --git a/vendor/github.com/jackc/pgx/v4/batch.go b/vendor/github.com/jackc/pgx/v4/batch.go index 4b96ca194..f0479ea63 100644 --- a/vendor/github.com/jackc/pgx/v4/batch.go +++ b/vendor/github.com/jackc/pgx/v4/batch.go @@ -41,6 +41,9 @@ type BatchResults interface { // QueryRow reads the results from the next query in the batch as if the query has been sent with Conn.QueryRow. QueryRow() Row + // QueryFunc reads the results from the next query in the batch as if the query has been sent with Conn.QueryFunc. + QueryFunc(scans []interface{}, f func(QueryFuncRow) error) (pgconn.CommandTag, error) + // Close closes the batch operation. This must be called before the underlying connection can be used again. Any error // that occurred during a batch operation may have made it impossible to resyncronize the connection with the server. // In this case the underlying connection will have been closed. @@ -135,6 +138,33 @@ func (br *batchResults) Query() (Rows, error) { return rows, nil } +// QueryFunc reads the results from the next query in the batch as if the query has been sent with Conn.QueryFunc. +func (br *batchResults) QueryFunc(scans []interface{}, f func(QueryFuncRow) error) (pgconn.CommandTag, error) { + rows, err := br.Query() + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + err = rows.Scan(scans...) + if err != nil { + return nil, err + } + + err = f(rows) + if err != nil { + return nil, err + } + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return rows.CommandTag(), nil +} + // QueryRow reads the results from the next query in the batch as if the query has been sent with QueryRow. func (br *batchResults) QueryRow() Row { rows, _ := br.Query() diff --git a/vendor/github.com/jackc/pgx/v4/conn.go b/vendor/github.com/jackc/pgx/v4/conn.go index 9636f2fd6..102158ab5 100644 --- a/vendor/github.com/jackc/pgx/v4/conn.go +++ b/vendor/github.com/jackc/pgx/v4/conn.go @@ -50,6 +50,7 @@ func (cc *ConnConfig) Copy() *ConnConfig { return newConfig } +// ConnString returns the connection string as parsed by pgx.ParseConfig into pgx.ConnConfig. func (cc *ConnConfig) ConnString() string { return cc.connString } // BuildStatementCacheFunc is a function that can be used to create a stmtcache.Cache implementation for connection. @@ -107,8 +108,8 @@ func Connect(ctx context.Context, connString string) (*Conn, error) { return connect(ctx, connConfig) } -// Connect establishes a connection with a PostgreSQL server with a configuration struct. connConfig must have been -// created by ParseConfig. +// ConnectConfig establishes a connection with a PostgreSQL server with a configuration struct. +// connConfig must have been created by ParseConfig. func ConnectConfig(ctx context.Context, connConfig *ConnConfig) (*Conn, error) { return connect(ctx, connConfig) } @@ -324,6 +325,7 @@ func (c *Conn) WaitForNotification(ctx context.Context) (*pgconn.Notification, e return n, err } +// IsClosed reports if the connection has been closed. func (c *Conn) IsClosed() bool { return c.pgConn.IsClosed() } @@ -357,6 +359,8 @@ func quoteIdentifier(s string) string { return `"` + strings.ReplaceAll(s, `"`, `""`) + `"` } +// Ping executes an empty sql statement against the *Conn +// If the sql returns without error, the database Ping is considered successful, otherwise, the error is returned. func (c *Conn) Ping(ctx context.Context) error { _, err := c.Exec(ctx, ";") return err @@ -517,6 +521,7 @@ func (c *Conn) execParams(ctx context.Context, sd *pgconn.StatementDescription, } result := c.pgConn.ExecParams(ctx, sd.SQL, c.eqb.paramValues, sd.ParamOIDs, c.eqb.paramFormats, c.eqb.resultFormats).Read() + c.eqb.Reset() // Allow c.eqb internal memory to be GC'ed as soon as possible. return result.CommandTag, result.Err } @@ -527,6 +532,7 @@ func (c *Conn) execPrepared(ctx context.Context, sd *pgconn.StatementDescription } result := c.pgConn.ExecPrepared(ctx, sd.Name, c.eqb.paramValues, c.eqb.paramFormats, c.eqb.resultFormats).Read() + c.eqb.Reset() // Allow c.eqb internal memory to be GC'ed as soon as possible. return result.CommandTag, result.Err } @@ -558,8 +564,12 @@ type QueryResultFormats []int16 // QueryResultFormatsByOID controls the result format (text=0, binary=1) of a query by the result column OID. type QueryResultFormatsByOID map[uint32]int16 -// Query executes sql with args. If there is an error the returned Rows will be returned in an error state. So it is -// allowed to ignore the error returned from Query and handle it in Rows. +// Query executes sql with args. It is safe to attempt to read from the returned Rows even if an error is returned. The +// error will be the available in rows.Err() after rows are closed. So it is allowed to ignore the error returned from +// Query and handle it in Rows. +// +// Err() on the returned Rows must be checked after the Rows is closed to determine if the query executed successfully +// as some errors can only be detected by reading the entire response. e.g. A divide by zero error on the last row. // // For extra control over how the query is executed, the types QuerySimpleProtocol, QueryResultFormats, and // QueryResultFormatsByOID may be used as the first args to control exactly how the query is executed. This is rarely @@ -670,6 +680,8 @@ optionLoop: rows.resultReader = c.pgConn.ExecPrepared(ctx, sd.Name, c.eqb.paramValues, c.eqb.paramFormats, resultFormats) } + c.eqb.Reset() // Allow c.eqb internal memory to be GC'ed as soon as possible. + return rows, rows.err } @@ -817,6 +829,8 @@ func (c *Conn) SendBatch(ctx context.Context, b *Batch) BatchResults { } } + c.eqb.Reset() // Allow c.eqb internal memory to be GC'ed as soon as possible. + mrr := c.pgConn.ExecBatch(ctx, batch) return &batchResults{ diff --git a/vendor/github.com/jackc/pgx/v4/doc.go b/vendor/github.com/jackc/pgx/v4/doc.go index 51b0d9f44..222f90479 100644 --- a/vendor/github.com/jackc/pgx/v4/doc.go +++ b/vendor/github.com/jackc/pgx/v4/doc.go @@ -309,7 +309,7 @@ CopyFrom can be faster than an insert with as few as 5 rows. Listen and Notify pgx can listen to the PostgreSQL notification system with the `Conn.WaitForNotification` method. It blocks until a -context is received or the context is canceled. +notification is received or the context is canceled. _, err := conn.Exec(context.Background(), "listen channelname") if err != nil { diff --git a/vendor/github.com/jackc/pgx/v4/extended_query_builder.go b/vendor/github.com/jackc/pgx/v4/extended_query_builder.go index 09419f0d0..d06f63fd1 100644 --- a/vendor/github.com/jackc/pgx/v4/extended_query_builder.go +++ b/vendor/github.com/jackc/pgx/v4/extended_query_builder.go @@ -13,8 +13,6 @@ type extendedQueryBuilder struct { paramValueBytes []byte paramFormats []int16 resultFormats []int16 - - resetCount int } func (eqb *extendedQueryBuilder) AppendParam(ci *pgtype.ConnInfo, oid uint32, arg interface{}) error { @@ -34,32 +32,27 @@ func (eqb *extendedQueryBuilder) AppendResultFormat(f int16) { eqb.resultFormats = append(eqb.resultFormats, f) } +// Reset readies eqb to build another query. func (eqb *extendedQueryBuilder) Reset() { eqb.paramValues = eqb.paramValues[0:0] eqb.paramValueBytes = eqb.paramValueBytes[0:0] eqb.paramFormats = eqb.paramFormats[0:0] eqb.resultFormats = eqb.resultFormats[0:0] - eqb.resetCount++ - - // Every so often shrink our reserved memory if it is abnormally high - if eqb.resetCount%128 == 0 { - if cap(eqb.paramValues) > 64 { - eqb.paramValues = make([][]byte, 0, cap(eqb.paramValues)/2) - } - - if cap(eqb.paramValueBytes) > 256 { - eqb.paramValueBytes = make([]byte, 0, cap(eqb.paramValueBytes)/2) - } + if cap(eqb.paramValues) > 64 { + eqb.paramValues = make([][]byte, 0, 64) + } - if cap(eqb.paramFormats) > 64 { - eqb.paramFormats = make([]int16, 0, cap(eqb.paramFormats)/2) - } - if cap(eqb.resultFormats) > 64 { - eqb.resultFormats = make([]int16, 0, cap(eqb.resultFormats)/2) - } + if cap(eqb.paramValueBytes) > 256 { + eqb.paramValueBytes = make([]byte, 0, 256) } + if cap(eqb.paramFormats) > 64 { + eqb.paramFormats = make([]int16, 0, 64) + } + if cap(eqb.resultFormats) > 64 { + eqb.resultFormats = make([]int16, 0, 64) + } } func (eqb *extendedQueryBuilder) encodeExtendedParamValue(ci *pgtype.ConnInfo, oid uint32, formatCode int16, arg interface{}) ([]byte, error) { diff --git a/vendor/github.com/jackc/pgx/v4/tx.go b/vendor/github.com/jackc/pgx/v4/tx.go index 7a296f4fe..ad399679b 100644 --- a/vendor/github.com/jackc/pgx/v4/tx.go +++ b/vendor/github.com/jackc/pgx/v4/tx.go @@ -10,6 +10,7 @@ import ( "github.com/jackc/pgconn" ) +// TxIsoLevel is the transaction isolation level (serializable, repeatable read, read committed or read uncommitted) type TxIsoLevel string // Transaction isolation levels @@ -20,6 +21,7 @@ const ( ReadUncommitted = TxIsoLevel("read uncommitted") ) +// TxAccessMode is the transaction access mode (read write or read only) type TxAccessMode string // Transaction access modes @@ -28,6 +30,7 @@ const ( ReadOnly = TxAccessMode("read only") ) +// TxDeferrableMode is the transaction deferrable mode (deferrable or not deferrable) type TxDeferrableMode string // Transaction deferrable modes @@ -36,6 +39,7 @@ const ( NotDeferrable = TxDeferrableMode("not deferrable") ) +// TxOptions are transaction modes within a transaction block type TxOptions struct { IsoLevel TxIsoLevel AccessMode TxAccessMode @@ -109,7 +113,7 @@ func (c *Conn) BeginTxFunc(ctx context.Context, txOptions TxOptions, f func(Tx) } defer func() { rollbackErr := tx.Rollback(ctx) - if !(rollbackErr == nil || errors.Is(rollbackErr, ErrTxClosed)) { + if rollbackErr != nil && !errors.Is(rollbackErr, ErrTxClosed) { err = rollbackErr } }() @@ -203,7 +207,7 @@ func (tx *dbTx) BeginFunc(ctx context.Context, f func(Tx) error) (err error) { } defer func() { rollbackErr := savepoint.Rollback(ctx) - if !(rollbackErr == nil || errors.Is(rollbackErr, ErrTxClosed)) { + if rollbackErr != nil && !errors.Is(rollbackErr, ErrTxClosed) { err = rollbackErr } }() |