pgtype
pgtype copied to clipboard
Missing conversion from Numeric AssignTo string/big.Int
Hi, first of all thank you for providing suite of libraries and drivers for the Postgres in Golang.
I am working on a very big integer field that could not fits in Golang int64 nor Postgres bigint. So I use the Postgres numeric field. I noticed the Set method on pgtype.Numeric can accepts a string so I have made the insertion operation works by using
value := big.NewInt(int64(1))
new(pgtype.Numeric).Set(value.String())
However, I realize in the implementation of AssignTo there is no way back to string but only existing Golang primitive numeric types only. I notice the Numeric struct does declare the Int (big.Int) as public, but it doesn't seem right to use it directly, I assume this is implementation details and I should rely on public methods to do it.
Maybe I have missed something in this process. Is this design on purpose or do I missed the way to convert it back to string or big.Int? Thank you.
It's on purpose in the general case for pgtype. That is, types only can assign to string if they are a string-like type. It may be worth revisiting that decision though...
However, for this particular case you probably want to use the package github.com/jackc/pgtype/ext/shopspring-numeric to integrate with github.com/shopspring/decimal.
I faced this problem too.
Using package github.com/jackc/pgtype/ext/shopspring-numeric works.
Thanks.
It's on purpose in the general case for pgtype. That is, types only can assign to string if they are a string-like type. It may be worth revisiting that decision though...
However, for this particular case you probably want to use the package
github.com/jackc/pgtype/ext/shopspring-numericto integrate withgithub.com/shopspring/decimal.
Why can't we add something like this to code to get bigints directly?

A simple approach is:
type Numeric struct {
pgtype.Numeric
}
func NewNumeric(i *big.Int) *Numeric {
n := new(Numeric)
n.Int = i
n.Status = pgtype.Present
return n
}
func (n *Numeric) MustBigInt() *big.Int {
if n == nil {
return nil
}
var r *big.Rat
err := n.AssignTo(r)
if err != nil {
panic(err)
}
if r.Denom().Cmp(big1) != 0 {
panic("Numeric contains decimal part: " + r.String())
}
return r.Num()
}