Use Numeric in JSON output

This commit is contained in:
2022-02-06 22:12:48 +00:00
parent 5763409aa8
commit 487aa89f18
11 changed files with 258 additions and 118 deletions

View File

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