mirror of https://github.com/jackc/pgx.git
pgtype.Numeric implements Float64Valuer
parent
a280f4db8a
commit
a74ebc9e51
|
@ -80,6 +80,35 @@ func (n Numeric) NumericValue() (Numeric, error) {
|
|||
return n, nil
|
||||
}
|
||||
|
||||
func (n Numeric) Float64Value() (Float8, error) {
|
||||
if !n.Valid {
|
||||
return Float8{}, nil
|
||||
} else if n.NaN {
|
||||
return Float8{Float: math.NaN(), Valid: true}, nil
|
||||
} else if n.InfinityModifier == Infinity {
|
||||
return Float8{Float: math.Inf(1), Valid: true}, nil
|
||||
} else if n.InfinityModifier == NegativeInfinity {
|
||||
return Float8{Float: math.Inf(-1), Valid: true}, nil
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, 32)
|
||||
|
||||
if n.Int == nil {
|
||||
buf = append(buf, '0')
|
||||
} else {
|
||||
buf = append(buf, n.Int.String()...)
|
||||
}
|
||||
buf = append(buf, 'e')
|
||||
buf = append(buf, strconv.FormatInt(int64(n.Exp), 10)...)
|
||||
|
||||
f, err := strconv.ParseFloat(string(buf), 64)
|
||||
if err != nil {
|
||||
return Float8{}, err
|
||||
}
|
||||
|
||||
return Float8{Float: f, Valid: true}, nil
|
||||
}
|
||||
|
||||
func (n *Numeric) toBigInt() (*big.Int, error) {
|
||||
if n.Exp == 0 {
|
||||
return n.Int, nil
|
||||
|
@ -104,28 +133,6 @@ func (n *Numeric) toBigInt() (*big.Int, error) {
|
|||
return num, nil
|
||||
}
|
||||
|
||||
func (n *Numeric) toFloat64() (float64, error) {
|
||||
if n.NaN {
|
||||
return math.NaN(), nil
|
||||
} else if n.InfinityModifier == Infinity {
|
||||
return math.Inf(1), nil
|
||||
} else if n.InfinityModifier == NegativeInfinity {
|
||||
return math.Inf(-1), nil
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, 32)
|
||||
|
||||
buf = append(buf, n.Int.String()...)
|
||||
buf = append(buf, 'e')
|
||||
buf = append(buf, strconv.FormatInt(int64(n.Exp), 10)...)
|
||||
|
||||
f, err := strconv.ParseFloat(string(buf), 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func parseNumericString(str string) (n *big.Int, exp int32, err error) {
|
||||
parts := strings.SplitN(str, ".", 2)
|
||||
digits := strings.Join(parts, "")
|
||||
|
@ -642,12 +649,12 @@ func (scanPlanBinaryNumericToFloat64Scanner) Scan(src []byte, dst interface{}) e
|
|||
return err
|
||||
}
|
||||
|
||||
f64, err := n.toFloat64()
|
||||
f8, err := n.Float64Value()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return scanner.ScanFloat64(Float8{Float: f64, Valid: true})
|
||||
return scanner.ScanFloat64(f8)
|
||||
}
|
||||
|
||||
type scanPlanBinaryNumericToInt64Scanner struct{}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -117,6 +118,30 @@ func TestNumericCodec(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestNumericFloat64Valuer(t *testing.T) {
|
||||
for i, tt := range []struct {
|
||||
n pgtype.Numeric
|
||||
f pgtype.Float8
|
||||
}{
|
||||
{mustParseNumeric(t, "1"), pgtype.Float8{Float: 1, Valid: true}},
|
||||
{mustParseNumeric(t, "0.0000000000000000001"), pgtype.Float8{Float: 0.0000000000000000001, Valid: true}},
|
||||
{mustParseNumeric(t, "-99999999999"), pgtype.Float8{Float: -99999999999, Valid: true}},
|
||||
{pgtype.Numeric{InfinityModifier: pgtype.Infinity, Valid: true}, pgtype.Float8{Float: math.Inf(1), Valid: true}},
|
||||
{pgtype.Numeric{InfinityModifier: pgtype.NegativeInfinity, Valid: true}, pgtype.Float8{Float: math.Inf(-1), Valid: true}},
|
||||
{pgtype.Numeric{Valid: true}, pgtype.Float8{Valid: true}},
|
||||
{pgtype.Numeric{}, pgtype.Float8{}},
|
||||
} {
|
||||
f, err := tt.n.Float64Value()
|
||||
assert.NoErrorf(t, err, "%d", i)
|
||||
assert.Equalf(t, tt.f, f, "%d", i)
|
||||
}
|
||||
|
||||
f, err := pgtype.Numeric{NaN: true, Valid: true}.Float64Value()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, math.IsNaN(f.Float))
|
||||
assert.True(t, f.Valid)
|
||||
}
|
||||
|
||||
func TestNumericCodecFuzz(t *testing.T) {
|
||||
r := rand.New(rand.NewSource(0))
|
||||
max := &big.Int{}
|
||||
|
|
Loading…
Reference in New Issue