build(deps): bump github.com/jackc/pgtype from 1.8.1 to 1.10.0

Bumps [github.com/jackc/pgtype](https://github.com/jackc/pgtype) from 1.8.1 to 1.10.0.
- [Release notes](https://github.com/jackc/pgtype/releases)
- [Changelog](https://github.com/jackc/pgtype/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgtype/compare/v1.8.1...v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgtype
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2022-04-07 04:29:20 +00:00 committed by Ondřej Budai
parent 98dc97e947
commit df0db98bf0
16 changed files with 235 additions and 57 deletions

2
go.mod
View file

@ -30,7 +30,7 @@ require (
github.com/google/uuid v1.3.0
github.com/gophercloud/gophercloud v0.22.0
github.com/hashicorp/go-retryablehttp v0.7.0
github.com/jackc/pgtype v1.8.1
github.com/jackc/pgtype v1.10.0
github.com/jackc/pgx/v4 v4.13.0
github.com/julienschmidt/httprouter v1.3.0
github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b

3
go.sum
View file

@ -414,8 +414,9 @@ github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/V
github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE=
github.com/jackc/pgtype v1.8.0/go.mod h1:PqDKcEBtllAtk/2p6z6SHdXW5UB+MhE75tUol2OKexE=
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.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38=
github.com/jackc/pgtype v1.10.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=

View file

@ -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

View file

@ -1,3 +1,28 @@
# 1.10.0 (February 7, 2022)
* Normalize UTC timestamps to comply with stdlib (Torkel Rogstad)
* Assign Numeric to *big.Rat (Oleg Lomaka)
* Fix typo in float8 error message (Pinank Solanki)
* Scan type aliases for floating point types (Collin Forsyth)
# 1.9.1 (November 28, 2021)
* Fix: binary timestamp is assumed to be in UTC (restored behavior changed in v1.9.0)
# 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

View file

@ -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()

View file

@ -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 {

View file

@ -337,6 +337,10 @@ func float64AssignTo(srcVal float64, srcStatus Status, dst interface{}) error {
if v := reflect.ValueOf(dst); v.Kind() == reflect.Ptr {
el := v.Elem()
switch el.Kind() {
// if dst is a type alias of a float32 or 64, set dst val
case reflect.Float32, reflect.Float64:
el.SetFloat(srcVal)
return nil
// if dst is a pointer to pointer, strip the pointer and try again
case reflect.Ptr:
if el.IsNil() {

View file

@ -204,7 +204,7 @@ func (dst *Float8) DecodeBinary(ci *ConnInfo, src []byte) error {
}
if len(src) != 8 {
return fmt.Errorf("invalid length for float4: %v", len(src))
return fmt.Errorf("invalid length for float8: %v", len(src))
}
n := int64(binary.BigEndian.Uint64(src))

View file

@ -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)

View file

@ -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}

View file

@ -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
@ -345,6 +369,12 @@ func (src *Numeric) AssignTo(dst interface{}) error {
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
}
*v = normalizedInt.Uint64()
case *big.Rat:
rat, err := src.toBigRat()
if err != nil {
return err
}
v.Set(rat)
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
@ -382,9 +412,33 @@ func (dst *Numeric) toBigInt() (*big.Int, error) {
return num, nil
}
func (dst *Numeric) toBigRat() (*big.Rat, error) {
if dst.NaN {
return nil, fmt.Errorf("%v is not a number", dst)
} else if dst.InfinityModifier == Infinity {
return nil, fmt.Errorf("%v is infinity", dst)
} else if dst.InfinityModifier == NegativeInfinity {
return nil, fmt.Errorf("%v is -infinity", dst)
}
num := new(big.Rat).SetInt(dst.Int)
if dst.Exp > 0 {
mul := new(big.Int).Exp(big10, big.NewInt(int64(dst.Exp)), nil)
num.Mul(num, new(big.Rat).SetInt(mul))
} else if dst.Exp < 0 {
mul := new(big.Int).Exp(big10, big.NewInt(int64(-dst.Exp)), nil)
num.Quo(num, new(big.Rat).SetInt(mul))
}
return num, nil
}
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 +463,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 +512,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 +524,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 +570,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 +641,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 +666,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

View file

@ -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))

View file

@ -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)
}

View file

@ -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),
).UTC()
*dst = Timestamp{Time: tim, Status: Present}
}

View file

@ -124,7 +124,7 @@ func (dst *Timestamptz) DecodeText(ci *ConnInfo, src []byte) error {
return err
}
*dst = Timestamptz{Time: tim, Status: Present}
*dst = Timestamptz{Time: normalizePotentialUTC(tim), Status: Present}
}
return nil
@ -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}
}
@ -229,6 +231,9 @@ func (src Timestamptz) Value() (driver.Value, error) {
if src.InfinityModifier != None {
return src.InfinityModifier.String(), nil
}
if src.Time.Location().String() == time.UTC.String() {
return src.Time.UTC(), nil
}
return src.Time, nil
case Null:
return nil, nil
@ -287,8 +292,23 @@ func (dst *Timestamptz) UnmarshalJSON(b []byte) error {
return err
}
*dst = Timestamptz{Time: tim, Status: Present}
*dst = Timestamptz{Time: normalizePotentialUTC(tim), Status: Present}
}
return nil
}
// Normalize timestamps in UTC location to behave similarly to how the Golang
// standard library does it: UTC timestamps lack a .loc value.
//
// Reason for this: when comparing two timestamps with reflect.DeepEqual (generally
// speaking not a good idea, but several testing libraries (for example testify)
// does this), their location data needs to be equal for them to be considered
// equal.
func normalizePotentialUTC(timestamp time.Time) time.Time {
if timestamp.Location().String() != time.UTC.String() {
return timestamp
}
return timestamp.UTC()
}

2
vendor/modules.txt vendored
View file

@ -297,7 +297,7 @@ github.com/jackc/pgpassfile
github.com/jackc/pgproto3/v2
# github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b
github.com/jackc/pgservicefile
# github.com/jackc/pgtype v1.8.1
# github.com/jackc/pgtype v1.10.0
## explicit
github.com/jackc/pgtype
# github.com/jackc/pgx/v4 v4.13.0