From d678216f468d1fe4dc28649feacd4b30a176769e Mon Sep 17 00:00:00 2001 From: David Hudson Date: Fri, 7 Jun 2019 15:08:36 +0100 Subject: [PATCH] pgtype: Fix -0 for numeric types Due to the special case of when the digits string was longer than 1 but only contained the negative sign and a 0, it was incorrectly stripping the 0 and attempting to parse "-" as a number. The solution is to check an extra position along to make sure a trailing 0 is not immediately preceeded by a negetive sign. Fixes #543 --- pgtype/numeric.go | 2 +- pgtype/numeric_array_test.go | 15 +++++++++++++++ pgtype/numeric_test.go | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pgtype/numeric.go b/pgtype/numeric.go index fb63df75..e14d02e4 100644 --- a/pgtype/numeric.go +++ b/pgtype/numeric.go @@ -321,7 +321,7 @@ func parseNumericString(str string) (n *big.Int, exp int32, err error) { if len(parts) > 1 { exp = int32(-len(parts[1])) } else { - for len(digits) > 1 && digits[len(digits)-1] == '0' { + for len(digits) > 1 && digits[len(digits)-1] == '0' && digits[len(digits)-2] != '-' { digits = digits[:len(digits)-1] exp++ } diff --git a/pgtype/numeric_array_test.go b/pgtype/numeric_array_test.go index 22ee1bc4..28aa67d9 100644 --- a/pgtype/numeric_array_test.go +++ b/pgtype/numeric_array_test.go @@ -1,6 +1,7 @@ package pgtype_test import ( + "math" "math/big" "reflect" "testing" @@ -65,6 +66,13 @@ func TestNumericArraySet(t *testing.T) { Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, Status: pgtype.Present}, }, + { + source: []float32{float32(math.Copysign(0, -1))}, + result: pgtype.NumericArray{ + Elements: []pgtype.Numeric{{Int: big.NewInt(0), Status: pgtype.Present}}, + Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, + Status: pgtype.Present}, + }, { source: []float64{1}, result: pgtype.NumericArray{ @@ -72,6 +80,13 @@ func TestNumericArraySet(t *testing.T) { Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, Status: pgtype.Present}, }, + { + source: []float64{math.Copysign(0, -1)}, + result: pgtype.NumericArray{ + Elements: []pgtype.Numeric{{Int: big.NewInt(0), Status: pgtype.Present}}, + Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, + Status: pgtype.Present}, + }, { source: (([]float32)(nil)), result: pgtype.NumericArray{Status: pgtype.Null}, diff --git a/pgtype/numeric_test.go b/pgtype/numeric_test.go index 9d7d83d6..a5f70c9e 100644 --- a/pgtype/numeric_test.go +++ b/pgtype/numeric_test.go @@ -1,6 +1,7 @@ package pgtype_test import ( + "math" "math/big" "math/rand" "reflect" @@ -188,7 +189,9 @@ func TestNumericSet(t *testing.T) { result *pgtype.Numeric }{ {source: float32(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}}, + {source: float32(math.Copysign(0, -1)), result: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present}}, {source: float64(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}}, + {source: float64(math.Copysign(0, -1)), result: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present}}, {source: int8(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}}, {source: int16(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}}, {source: int32(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},