mirror of
https://github.com/jackc/pgx.git
synced 2025-05-31 11:42:24 +00:00
Assign Numeric to *big.Rat
This commit is contained in:
parent
75446032b9
commit
ccc7cc2931
26
numeric.go
26
numeric.go
@ -369,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)
|
||||
@ -406,6 +412,26 @@ 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
|
||||
|
@ -263,6 +263,7 @@ func TestNumericAssignTo(t *testing.T) {
|
||||
var f64 float64
|
||||
var pf32 *float32
|
||||
var pf64 *float64
|
||||
var br = new(big.Rat)
|
||||
|
||||
simpleTests := []struct {
|
||||
src *pgtype.Numeric
|
||||
@ -293,6 +294,9 @@ func TestNumericAssignTo(t *testing.T) {
|
||||
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: &f32, expected: float32(math.Inf(1))},
|
||||
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f64, expected: math.Inf(-1)},
|
||||
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f32, expected: float32(math.Inf(-1))},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(-1023), Exp: -2, Status: pgtype.Present}, dst: br, expected: big.NewRat(-1023, 100)},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(-1023), Exp: 2, Status: pgtype.Present}, dst: br, expected: big.NewRat(-102300, 1)},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(23), Exp: 0, Status: pgtype.Present}, dst: br, expected: big.NewRat(23, 1)},
|
||||
}
|
||||
|
||||
for i, tt := range simpleTests {
|
||||
@ -317,6 +321,11 @@ func TestNumericAssignTo(t *testing.T) {
|
||||
} else if !nanExpected && dst != tt.expected {
|
||||
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
||||
}
|
||||
case big.Rat:
|
||||
if (&dstTyped).Cmp(tt.expected.(*big.Rat)) != 0 {
|
||||
t.Errorf("%d: expected %v to assign %v, but result was %v",
|
||||
i, tt.src, tt.expected, dst)
|
||||
}
|
||||
default:
|
||||
if dst != tt.expected {
|
||||
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
||||
@ -356,6 +365,10 @@ func TestNumericAssignTo(t *testing.T) {
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui64},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: &i32},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: br},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, NaN: true}, dst: br},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: br},
|
||||
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: br},
|
||||
}
|
||||
|
||||
for i, tt := range errorTests {
|
||||
|
Loading…
x
Reference in New Issue
Block a user