Use Numeric in JSON output
This commit is contained in:
@ -1,11 +1,20 @@
|
||||
package postgres
|
||||
|
||||
import "github.com/jackc/pgtype"
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/jackc/pgtype"
|
||||
)
|
||||
|
||||
type Numeric struct {
|
||||
pgtype.Numeric
|
||||
}
|
||||
|
||||
func NewZeroNumeric() Numeric {
|
||||
return Numeric{pgtype.Numeric{Exp: 0, Int: big.NewInt(0), Status: pgtype.Present, NaN: false}}
|
||||
}
|
||||
|
||||
func (n Numeric) GetFloat64() float64 {
|
||||
if n.Status != pgtype.Present {
|
||||
return 0
|
||||
@ -33,3 +42,83 @@ func (n Numeric) IsZero() bool {
|
||||
float := n.GetFloat64()
|
||||
return float == 0
|
||||
}
|
||||
|
||||
func (n Numeric) MatchExp(exp int32) Numeric {
|
||||
diffExp := exp - n.Exp
|
||||
factor := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(diffExp)), nil)
|
||||
return Numeric{pgtype.Numeric{
|
||||
Exp: exp,
|
||||
Int: big.NewInt(0).Mul(n.Int, factor),
|
||||
Status: n.Status,
|
||||
NaN: n.NaN,
|
||||
}}
|
||||
}
|
||||
|
||||
func (n Numeric) Sub(o Numeric) Numeric {
|
||||
if n.Exp > o.Exp {
|
||||
o = o.MatchExp(n.Exp)
|
||||
} else if n.Exp < o.Exp {
|
||||
n = n.MatchExp(o.Exp)
|
||||
}
|
||||
|
||||
if o.Exp == n.Exp {
|
||||
return Numeric{pgtype.Numeric{
|
||||
Exp: n.Exp,
|
||||
Int: big.NewInt(0).Sub(o.Int, n.Int),
|
||||
}}
|
||||
}
|
||||
|
||||
panic("Cannot subtract with different exponents")
|
||||
}
|
||||
func (n Numeric) Add(o Numeric) Numeric {
|
||||
fmt.Println("N", n, "O", o)
|
||||
if n.Exp > o.Exp {
|
||||
o = o.MatchExp(n.Exp)
|
||||
} else if n.Exp < o.Exp {
|
||||
n = n.MatchExp(o.Exp)
|
||||
}
|
||||
|
||||
fmt.Println("NM", n, "OM", o)
|
||||
if o.Exp == n.Exp {
|
||||
return Numeric{pgtype.Numeric{
|
||||
Exp: n.Exp,
|
||||
Int: big.NewInt(0).Add(o.Int, n.Int),
|
||||
}}
|
||||
}
|
||||
|
||||
panic("Cannot add with different exponents")
|
||||
}
|
||||
|
||||
func (n Numeric) MarshalJSON() ([]byte, error) {
|
||||
if n.Int.Int64() == 0 {
|
||||
return []byte("\"0\""), nil
|
||||
}
|
||||
|
||||
s := fmt.Sprintf("%d", n.Int)
|
||||
bytes := []byte(s)
|
||||
|
||||
exp := n.Exp
|
||||
for exp > 0 {
|
||||
bytes = append(bytes, byte('0'))
|
||||
exp--
|
||||
}
|
||||
|
||||
if exp == 0 {
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
length := int32(len(bytes))
|
||||
var bytesWithSeparator []byte
|
||||
|
||||
exp = -exp
|
||||
for length <= exp {
|
||||
bytes = append(bytes, byte('0'))
|
||||
length++
|
||||
}
|
||||
|
||||
split := length - exp
|
||||
bytesWithSeparator = append(bytesWithSeparator, bytes[:split]...)
|
||||
bytesWithSeparator = append(bytesWithSeparator, byte('.'))
|
||||
bytesWithSeparator = append(bytesWithSeparator, bytes[split:]...)
|
||||
return bytesWithSeparator, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user