From 942711e3300e7b9600aaacdce947387b4c49c07a Mon Sep 17 00:00:00 2001 From: Peter Kieltyka Date: Fri, 23 Jul 2021 17:45:55 -0400 Subject: [PATCH 1/3] test case for pgx scan issue of *BigInt --- dbtype/bigint.go | 39 ++++++++++++++++++++++++++ go.mod | 1 + pgkit.go | 9 ++++++ tests/pgkit_test.go | 48 ++++++++++++++++++++++++++------ tests/schema_test.go | 7 +++-- tests/testdata/pgkit_test_db.sql | 3 +- 6 files changed, 94 insertions(+), 13 deletions(-) diff --git a/dbtype/bigint.go b/dbtype/bigint.go index 45a2d3b..3a269d7 100644 --- a/dbtype/bigint.go +++ b/dbtype/bigint.go @@ -5,6 +5,9 @@ import ( "fmt" "math/big" "strings" + + "github.com/jackc/pgtype" + "github.com/kr/pretty" ) // BigInt is a type alias for big.Int used for JSON/Database marshalling. @@ -175,3 +178,39 @@ func (b *BigInt) Scan(src interface{}) error { return nil } + +// func (src *Point) AssignTo(dst interface{}) error { +// return fmt.Errorf("cannot assign %v to %T", src, dst) +// } + +func (b BigInt) DecodeText(ci *pgtype.ConnInfo, src []byte) error { + pretty.Println(src) + // panic("geez") + err := b.Scan(src) + if err != nil { + panic(err) + } + return nil +} + +func (dst *BigInt) Set(src interface{}) error { + panic("common") + // return fmt.Errorf("cannot convert %v to Point", src) +} + +func (dst *BigInt) Get() interface{} { + panic("ahh") + // switch dst.Status { + // case pgtype.Present: + // return dst + // case pgtype.Null: + // return nil + // default: + // return dst.Status + // } +} + +// BigInt pgx custom type assignment +func (src *BigInt) AssignTo(dst interface{}) error { + panic("wee") +} diff --git a/go.mod b/go.mod index cbdc627..ae919fd 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/jackc/pgconn v1.9.0 github.com/jackc/pgtype v1.8.0 github.com/jackc/pgx/v4 v4.12.0 + github.com/kr/pretty v0.1.0 github.com/stretchr/objx v0.3.0 // indirect github.com/stretchr/testify v1.7.0 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect diff --git a/pgkit.go b/pgkit.go index 321a749..8b8733e 100644 --- a/pgkit.go +++ b/pgkit.go @@ -60,6 +60,15 @@ func Connect(appName string, cfg Config) (*DB, error) { } func ConnectWithPGX(appName string, pgxConfig *pgxpool.Config) (*DB, error) { + // pgxConfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error { + // conn.ConnInfo().RegisterDataType(pgtype.DataType{ + // Value: &dbtype.BigInt{}, + // Name: "numeric", + // OID: pgtype.NumericOID, + // }) + // return nil + // } + pool, err := pgxpool.ConnectConfig(context.Background(), pgxConfig) if err != nil { return nil, fmt.Errorf("pgkit: failed to connect to db: %w", err) diff --git a/tests/pgkit_test.go b/tests/pgkit_test.go index 475482f..7f50c3f 100644 --- a/tests/pgkit_test.go +++ b/tests/pgkit_test.go @@ -15,6 +15,7 @@ import ( "github.com/goware/pgkit" "github.com/goware/pgkit/dbtype" "github.com/jackc/pgx/v4" + "github.com/kr/pretty" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -316,8 +317,27 @@ func TestRecordsWithJSONStruct(t *testing.T) { func TestRowsWithBigInt(t *testing.T) { truncateTable(t, "stats") + // { + // stat := &Stat{Key: "count", Num: dbtype.NewBigInt(2)} + + // // Insert + // q1 := DB.SQL.InsertRecord(stat, "stats") + // _, err := DB.Query.Exec(context.Background(), q1) + // assert.NoError(t, err) + + // // Select + // var sout Stat + // q2 := DB.SQL.Select("*").From("stats").Where(sq.Eq{"key": "count"}) + // err = DB.Query.GetOne(context.Background(), q2, &sout) + // assert.NoError(t, err) + // assert.Equal(t, "count", sout.Key) + // assert.True(t, sout.Num.Int64() == 2) + // assert.Nil(t, sout.Rating) + // } + + // another one, big number this time { - stat := &Stat{Key: "count", Num: dbtype.NewBigInt(2)} + stat := &Stat{Key: "count2", Num: dbtype.NewBigIntFromString("12323942398472837489234", 0)} // Insert q1 := DB.SQL.InsertRecord(stat, "stats") @@ -326,16 +346,25 @@ func TestRowsWithBigInt(t *testing.T) { // Select var sout Stat - q2 := DB.SQL.Select("*").From("stats").Where(sq.Eq{"key": "count"}) + q2 := DB.SQL.Select("*").From("stats").Where(sq.Eq{"key": "count2"}) err = DB.Query.GetOne(context.Background(), q2, &sout) assert.NoError(t, err) - assert.Equal(t, "count", sout.Key) - assert.True(t, sout.Num.Int64() == 2) + assert.Equal(t, "count2", sout.Key) + assert.True(t, sout.Num.String() == "12323942398472837489234") + + pretty.Println(sout.Rating) + + assert.Nil(t, sout.Rating) } - // another one, big number this time + // last, with opt rating { - stat := &Stat{Key: "count2", Num: dbtype.NewBigIntFromString("12323942398472837489234", 0)} + v := dbtype.NewBigInt(5) + stat := &Stat{ + Key: "count3", + Num: dbtype.NewBigIntFromString("44", 0), + Rating: v, + } // Insert q1 := DB.SQL.InsertRecord(stat, "stats") @@ -344,11 +373,12 @@ func TestRowsWithBigInt(t *testing.T) { // Select var sout Stat - q2 := DB.SQL.Select("*").From("stats").Where(sq.Eq{"key": "count2"}) + q2 := DB.SQL.Select("*").From("stats").Where(sq.Eq{"key": "count3"}) err = DB.Query.GetOne(context.Background(), q2, &sout) assert.NoError(t, err) - assert.Equal(t, "count2", sout.Key) - assert.True(t, sout.Num.String() == "12323942398472837489234") + assert.Equal(t, "count3", sout.Key) + assert.True(t, sout.Num.String() == "44") + assert.True(t, sout.Rating.String() == "5") } } diff --git a/tests/schema_test.go b/tests/schema_test.go index 69cb7ef..9bb52f3 100644 --- a/tests/schema_test.go +++ b/tests/schema_test.go @@ -32,9 +32,10 @@ type Log struct { } type Stat struct { - ID int64 `db:"id,omitempty"` - Key string `db:"key"` - Num dbtype.BigInt `db:"big_num"` // using NUMERIC(78,0) postgres datatype + ID int64 `db:"id,omitempty"` + Key string `db:"key"` + Num dbtype.BigInt `db:"big_num"` // using NUMERIC(78,0) postgres datatype + Rating dbtype.BigInt `db:"rating"` // using NUMERIC(78,0) postgres datatype } type Article struct { diff --git a/tests/testdata/pgkit_test_db.sql b/tests/testdata/pgkit_test_db.sql index 0830673..9f819bd 100644 --- a/tests/testdata/pgkit_test_db.sql +++ b/tests/testdata/pgkit_test_db.sql @@ -22,7 +22,8 @@ CREATE TABLE logs ( CREATE TABLE stats ( id SERIAL PRIMARY KEY, key VARCHAR(80), - big_num NUMERIC(78,0) -- representing a *big.Int runtime type + big_num NUMERIC(78,0) NOT NULL, -- representing a big.Int runtime type + rating NUMERIC(78,0) -- representing a *big.Int runtime type ); CREATE TABLE articles ( From 4a454dfecd4f5671b521b0851f12bceab086ca7e Mon Sep 17 00:00:00 2001 From: Peter Kieltyka Date: Sat, 24 Jul 2021 03:14:17 -0400 Subject: [PATCH 2/3] rebase, and update test --- tests/pgkit_test.go | 5 +++-- tests/schema_test.go | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/pgkit_test.go b/tests/pgkit_test.go index 7f50c3f..e03892d 100644 --- a/tests/pgkit_test.go +++ b/tests/pgkit_test.go @@ -359,11 +359,12 @@ func TestRowsWithBigInt(t *testing.T) { // last, with opt rating { - v := dbtype.NewBigInt(5) + bv := dbtype.NewBigInt(5) + stat := &Stat{ Key: "count3", Num: dbtype.NewBigIntFromString("44", 0), - Rating: v, + Rating: &bv, } // Insert diff --git a/tests/schema_test.go b/tests/schema_test.go index 9bb52f3..abc413e 100644 --- a/tests/schema_test.go +++ b/tests/schema_test.go @@ -32,10 +32,10 @@ type Log struct { } type Stat struct { - ID int64 `db:"id,omitempty"` - Key string `db:"key"` - Num dbtype.BigInt `db:"big_num"` // using NUMERIC(78,0) postgres datatype - Rating dbtype.BigInt `db:"rating"` // using NUMERIC(78,0) postgres datatype + ID int64 `db:"id,omitempty"` + Key string `db:"key"` + Num dbtype.BigInt `db:"big_num"` // using NUMERIC(78,0) postgres datatype + Rating *dbtype.BigInt `db:"rating"` // using NUMERIC(78,0) postgres datatype } type Article struct { From 0045d1aacce15fd0a7ad923ce1abcdec912db8c0 Mon Sep 17 00:00:00 2001 From: Peter Kieltyka Date: Sat, 24 Jul 2021 03:15:07 -0400 Subject: [PATCH 3/3] update test --- tests/pgkit_test.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/pgkit_test.go b/tests/pgkit_test.go index e03892d..8a248cb 100644 --- a/tests/pgkit_test.go +++ b/tests/pgkit_test.go @@ -317,23 +317,23 @@ func TestRecordsWithJSONStruct(t *testing.T) { func TestRowsWithBigInt(t *testing.T) { truncateTable(t, "stats") - // { - // stat := &Stat{Key: "count", Num: dbtype.NewBigInt(2)} - - // // Insert - // q1 := DB.SQL.InsertRecord(stat, "stats") - // _, err := DB.Query.Exec(context.Background(), q1) - // assert.NoError(t, err) - - // // Select - // var sout Stat - // q2 := DB.SQL.Select("*").From("stats").Where(sq.Eq{"key": "count"}) - // err = DB.Query.GetOne(context.Background(), q2, &sout) - // assert.NoError(t, err) - // assert.Equal(t, "count", sout.Key) - // assert.True(t, sout.Num.Int64() == 2) - // assert.Nil(t, sout.Rating) - // } + { + stat := &Stat{Key: "count", Num: dbtype.NewBigInt(2)} + + // Insert + q1 := DB.SQL.InsertRecord(stat, "stats") + _, err := DB.Query.Exec(context.Background(), q1) + assert.NoError(t, err) + + // Select + var sout Stat + q2 := DB.SQL.Select("*").From("stats").Where(sq.Eq{"key": "count"}) + err = DB.Query.GetOne(context.Background(), q2, &sout) + assert.NoError(t, err) + assert.Equal(t, "count", sout.Key) + assert.True(t, sout.Num.Int64() == 2) + assert.Nil(t, sout.Rating) + } // another one, big number this time {