pgtype icon indicating copy to clipboard operation
pgtype copied to clipboard

Missing conversion from Numeric AssignTo string/big.Int

Open calvinlauyh opened this issue 5 years ago • 4 comments

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.

calvinlauyh avatar May 04 '20 21:05 calvinlauyh

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.

jackc avatar May 13 '20 13:05 jackc

I faced this problem too.

Using package github.com/jackc/pgtype/ext/shopspring-numeric works.

Thanks.

memochou1993 avatar Jul 06 '22 18:07 memochou1993

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.

Why can't we add something like this to code to get bigints directly? image

abonec avatar Aug 19 '22 07:08 abonec

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()
}

injeniero avatar Nov 15 '22 22:11 injeniero