From ee93440ac15326a4dbfedd6b56de685726392de6 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sat, 2 Apr 2022 14:34:19 -0500 Subject: [PATCH] pgtype uses pgxtest Added ValueRoundTripTest to pgxtest Removed pgtype/testutil pgtype tests now run with all (applicable) query modes. This gives better coverage than before and revealed several bugs which are also fixed in this commit. --- conn.go | 35 +- pgtype/array_codec_test.go | 269 ++- pgtype/bits_test.go | 7 +- pgtype/bool_test.go | 5 +- pgtype/box_test.go | 5 +- pgtype/bytea_test.go | 127 +- pgtype/circle_test.go | 5 +- pgtype/composite_test.go | 201 +- pgtype/date_test.go | 5 +- pgtype/enum_codec_test.go | 78 +- pgtype/float4_test.go | 5 +- pgtype/float8_test.go | 5 +- pgtype/hstore_test.go | 48 +- pgtype/inet_test.go | 7 +- pgtype/int_test.go | 9 +- pgtype/int_test.go.erb | 2 +- pgtype/integration_benchmark_test.go | 2171 +++++++++++----------- pgtype/integration_benchmark_test.go.erb | 66 +- pgtype/interval_test.go | 5 +- pgtype/json_test.go | 18 +- pgtype/jsonb_test.go | 18 +- pgtype/line_test.go | 36 +- pgtype/lseg_test.go | 5 +- pgtype/macaddr_test.go | 6 +- pgtype/numeric_test.go | 67 +- pgtype/path_test.go | 5 +- pgtype/pgtype.go | 2 +- pgtype/pgtype_test.go | 29 +- pgtype/point_test.go | 5 +- pgtype/polygon_test.go | 5 +- pgtype/qchar_test.go | 16 +- pgtype/range_codec_test.go | 152 +- pgtype/record_codec_test.go | 108 +- pgtype/testutil/testutil.go | 85 - pgtype/text_test.go | 51 +- pgtype/tid_test.go | 5 +- pgtype/time_test.go | 5 +- pgtype/timestamp.go | 28 + pgtype/timestamp_test.go | 31 +- pgtype/timestamptz.go | 33 +- pgtype/timestamptz_test.go | 31 +- pgtype/uint32_test.go | 5 +- pgtype/uuid_test.go | 28 +- pgtype/zeronull/float8_test.go | 5 +- pgtype/zeronull/int_test.go | 9 +- pgtype/zeronull/int_test.go.erb | 2 +- pgtype/zeronull/text_test.go | 5 +- pgtype/zeronull/timestamp_test.go | 5 +- pgtype/zeronull/timestamptz_test.go | 5 +- pgtype/zeronull/uuid_test.go | 5 +- pgtype/zeronull/zeronull.go | 17 + pgtype/zeronull/zeronull_test.go | 26 + pgxtest/pgxtest.go | 72 +- values.go | 2 +- 54 files changed, 2028 insertions(+), 1954 deletions(-) delete mode 100644 pgtype/testutil/testutil.go create mode 100644 pgtype/zeronull/zeronull.go create mode 100644 pgtype/zeronull/zeronull_test.go diff --git a/conn.go b/conn.go index 8ccf5043..e6396cd3 100644 --- a/conn.go +++ b/conn.go @@ -558,18 +558,41 @@ func (c *Conn) execSQLParams(ctx context.Context, sql string, args []interface{} // Given that the whole point of QueryExecModeExec is to operate without having to know the PostgreSQL types there is // no way to safely use binary or to specify the parameter OIDs. func (c *Conn) appendParamsForQueryExecModeExec(args []interface{}) error { - for i := range args { - if args[i] == nil { - err := c.eqb.AppendParamFormat(c.typeMap, 0, TextFormatCode, args[i]) + for _, arg := range args { + if arg == nil { + err := c.eqb.AppendParamFormat(c.typeMap, 0, TextFormatCode, arg) if err != nil { return err } } else { - dt, ok := c.TypeMap().TypeForValue(args[i]) + dt, ok := c.TypeMap().TypeForValue(arg) if !ok { - return &unknownArgumentTypeQueryExecModeExecError{arg: args[i]} + var tv pgtype.TextValuer + if tv, ok = arg.(pgtype.TextValuer); ok { + t, err := tv.TextValue() + if err != nil { + return err + } + + dt, ok = c.TypeMap().TypeForOID(pgtype.TextOID) + if ok { + arg = t + } + } } - err := c.eqb.AppendParamFormat(c.typeMap, dt.OID, TextFormatCode, args[i]) + if !ok { + var str fmt.Stringer + if str, ok = arg.(fmt.Stringer); ok { + dt, ok = c.TypeMap().TypeForOID(pgtype.TextOID) + if ok { + arg = str.String() + } + } + } + if !ok { + return &unknownArgumentTypeQueryExecModeExecError{arg: arg} + } + err := c.eqb.AppendParamFormat(c.typeMap, dt.OID, TextFormatCode, arg) if err != nil { return err } diff --git a/pgtype/array_codec_test.go b/pgtype/array_codec_test.go index 0cc6d7cb..55ab814e 100644 --- a/pgtype/array_codec_test.go +++ b/pgtype/array_codec_test.go @@ -4,191 +4,184 @@ import ( "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" + pgx "github.com/jackc/pgx/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestArrayCodec(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + for i, tt := range []struct { + expected interface{} + }{ + {[]int16(nil)}, + {[]int16{}}, + {[]int16{1, 2, 3}}, + } { + var actual []int16 + err := conn.QueryRow( + ctx, + "select $1::smallint[]", + tt.expected, + ).Scan(&actual) + assert.NoErrorf(t, err, "%d", i) + assert.Equalf(t, tt.expected, actual, "%d", i) + } - for i, tt := range []struct { - expected interface{} - }{ - {[]int16(nil)}, - {[]int16{}}, - {[]int16{1, 2, 3}}, - } { - var actual []int16 - err := conn.QueryRow( - context.Background(), - "select $1::smallint[]", - tt.expected, - ).Scan(&actual) - assert.NoErrorf(t, err, "%d", i) - assert.Equalf(t, tt.expected, actual, "%d", i) - } + newInt16 := func(n int16) *int16 { return &n } - newInt16 := func(n int16) *int16 { return &n } - - for i, tt := range []struct { - expected interface{} - }{ - {[]*int16{newInt16(1), nil, newInt16(3), nil, newInt16(5)}}, - } { - var actual []*int16 - err := conn.QueryRow( - context.Background(), - "select $1::smallint[]", - tt.expected, - ).Scan(&actual) - assert.NoErrorf(t, err, "%d", i) - assert.Equalf(t, tt.expected, actual, "%d", i) - } + for i, tt := range []struct { + expected interface{} + }{ + {[]*int16{newInt16(1), nil, newInt16(3), nil, newInt16(5)}}, + } { + var actual []*int16 + err := conn.QueryRow( + ctx, + "select $1::smallint[]", + tt.expected, + ).Scan(&actual) + assert.NoErrorf(t, err, "%d", i) + assert.Equalf(t, tt.expected, actual, "%d", i) + } + }) } func TestArrayCodecAnySlice(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + type _int16Slice []int16 - type _int16Slice []int16 - - for i, tt := range []struct { - expected interface{} - }{ - {_int16Slice(nil)}, - {_int16Slice{}}, - {_int16Slice{1, 2, 3}}, - } { - var actual _int16Slice - err := conn.QueryRow( - context.Background(), - "select $1::smallint[]", - tt.expected, - ).Scan(&actual) - assert.NoErrorf(t, err, "%d", i) - assert.Equalf(t, tt.expected, actual, "%d", i) - } + for i, tt := range []struct { + expected interface{} + }{ + {_int16Slice(nil)}, + {_int16Slice{}}, + {_int16Slice{1, 2, 3}}, + } { + var actual _int16Slice + err := conn.QueryRow( + ctx, + "select $1::smallint[]", + tt.expected, + ).Scan(&actual) + assert.NoErrorf(t, err, "%d", i) + assert.Equalf(t, tt.expected, actual, "%d", i) + } + }) } func TestArrayCodecDecodeValue(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - for _, tt := range []struct { - sql string - expected interface{} - }{ - { - sql: `select '{}'::int4[]`, - expected: []interface{}{}, - }, - { - sql: `select '{1,2}'::int8[]`, - expected: []interface{}{int64(1), int64(2)}, - }, - { - sql: `select '{foo,bar}'::text[]`, - expected: []interface{}{"foo", "bar"}, - }, - } { - t.Run(tt.sql, func(t *testing.T) { - rows, err := conn.Query(context.Background(), tt.sql) - require.NoError(t, err) - - for rows.Next() { - values, err := rows.Values() + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + for _, tt := range []struct { + sql string + expected interface{} + }{ + { + sql: `select '{}'::int4[]`, + expected: []interface{}{}, + }, + { + sql: `select '{1,2}'::int8[]`, + expected: []interface{}{int64(1), int64(2)}, + }, + { + sql: `select '{foo,bar}'::text[]`, + expected: []interface{}{"foo", "bar"}, + }, + } { + t.Run(tt.sql, func(t *testing.T) { + rows, err := conn.Query(ctx, tt.sql) require.NoError(t, err) - require.Len(t, values, 1) - require.Equal(t, tt.expected, values[0]) - } - require.NoError(t, rows.Err()) - }) - } + for rows.Next() { + values, err := rows.Values() + require.NoError(t, err) + require.Len(t, values, 1) + require.Equal(t, tt.expected, values[0]) + } + + require.NoError(t, rows.Err()) + }) + } + }) } func TestArrayCodecScanMultipleDimensions(t *testing.T) { skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - rows, err := conn.Query(context.Background(), `select '{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}'::int4[]`) - require.NoError(t, err) - - for rows.Next() { - var ss [][]int32 - err := rows.Scan(&ss) + rows, err := conn.Query(ctx, `select '{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}'::int4[]`) require.NoError(t, err) - require.Equal(t, [][]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, ss) - } - require.NoError(t, rows.Err()) + for rows.Next() { + var ss [][]int32 + err := rows.Scan(&ss) + require.NoError(t, err) + require.Equal(t, [][]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, ss) + } + + require.NoError(t, rows.Err()) + }) } func TestArrayCodecScanMultipleDimensionsEmpty(t *testing.T) { skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - rows, err := conn.Query(context.Background(), `select '{}'::int4[]`) - require.NoError(t, err) - - for rows.Next() { - var ss [][]int32 - err := rows.Scan(&ss) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + rows, err := conn.Query(ctx, `select '{}'::int4[]`) require.NoError(t, err) - require.Equal(t, [][]int32{}, ss) - } - require.NoError(t, rows.Err()) + for rows.Next() { + var ss [][]int32 + err := rows.Scan(&ss) + require.NoError(t, err) + require.Equal(t, [][]int32{}, ss) + } + + require.NoError(t, rows.Err()) + }) } func TestArrayCodecScanWrongMultipleDimensions(t *testing.T) { skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + rows, err := conn.Query(ctx, `select '{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}'::int4[]`) + require.NoError(t, err) - rows, err := conn.Query(context.Background(), `select '{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}'::int4[]`) - require.NoError(t, err) - - for rows.Next() { - var ss [][][]int32 - err := rows.Scan(&ss) - require.Error(t, err, "can't scan into dest[0]: PostgreSQL array has 2 dimensions but slice has 3 dimensions") - } + for rows.Next() { + var ss [][][]int32 + err := rows.Scan(&ss) + require.Error(t, err, "can't scan into dest[0]: PostgreSQL array has 2 dimensions but slice has 3 dimensions") + } + }) } func TestArrayCodecEncodeMultipleDimensions(t *testing.T) { skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - rows, err := conn.Query(context.Background(), `select $1::int4[]`, [][]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}) - require.NoError(t, err) - - for rows.Next() { - var ss [][]int32 - err := rows.Scan(&ss) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + rows, err := conn.Query(ctx, `select $1::int4[]`, [][]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}) require.NoError(t, err) - require.Equal(t, [][]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, ss) - } - require.NoError(t, rows.Err()) + for rows.Next() { + var ss [][]int32 + err := rows.Scan(&ss) + require.NoError(t, err) + require.Equal(t, [][]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, ss) + } + + require.NoError(t, rows.Err()) + }) } func TestArrayCodecEncodeMultipleDimensionsRagged(t *testing.T) { skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - rows, err := conn.Query(context.Background(), `select $1::int4[]`, [][]int32{{1, 2, 3, 4}, {5}, {9, 10, 11, 12}}) - require.Error(t, err, "cannot convert [][]int32 to ArrayGetter because it is a ragged multi-dimensional") - defer rows.Close() + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + rows, err := conn.Query(ctx, `select $1::int4[]`, [][]int32{{1, 2, 3, 4}, {5}, {9, 10, 11, 12}}) + require.Error(t, err, "cannot convert [][]int32 to ArrayGetter because it is a ragged multi-dimensional") + defer rows.Close() + }) } diff --git a/pgtype/bits_test.go b/pgtype/bits_test.go index 5a82743c..3ca3b0c0 100644 --- a/pgtype/bits_test.go +++ b/pgtype/bits_test.go @@ -2,10 +2,11 @@ package pgtype_test import ( "bytes" + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqBits(a interface{}) func(interface{}) bool { @@ -17,7 +18,7 @@ func isExpectedEqBits(a interface{}) func(interface{}) bool { } func TestBitsCodecBit(t *testing.T) { - testutil.RunTranscodeTests(t, "bit(40)", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "bit(40)", []pgxtest.ValueRoundTripTest{ { pgtype.Bits{Bytes: []byte{0, 0, 0, 0, 0}, Len: 40, Valid: true}, new(pgtype.Bits), @@ -34,7 +35,7 @@ func TestBitsCodecBit(t *testing.T) { } func TestBitsCodecVarbit(t *testing.T) { - testutil.RunTranscodeTests(t, "varbit", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "varbit", []pgxtest.ValueRoundTripTest{ { pgtype.Bits{Bytes: []byte{}, Len: 0, Valid: true}, new(pgtype.Bits), diff --git a/pgtype/bool_test.go b/pgtype/bool_test.go index 57094144..7480471b 100644 --- a/pgtype/bool_test.go +++ b/pgtype/bool_test.go @@ -1,14 +1,15 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestBoolCodec(t *testing.T) { - testutil.RunTranscodeTests(t, "bool", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "bool", []pgxtest.ValueRoundTripTest{ {true, new(bool), isExpectedEq(true)}, {false, new(bool), isExpectedEq(false)}, {true, new(pgtype.Bool), isExpectedEq(pgtype.Bool{Bool: true, Valid: true})}, diff --git a/pgtype/box_test.go b/pgtype/box_test.go index 173fb1f5..3b54c1f8 100644 --- a/pgtype/box_test.go +++ b/pgtype/box_test.go @@ -1,16 +1,17 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestBoxCodec(t *testing.T) { skipCockroachDB(t, "Server does not support box type") - testutil.RunTranscodeTests(t, "box", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "box", []pgxtest.ValueRoundTripTest{ { pgtype.Box{ P: [2]pgtype.Vec2{{7.1, 5.2345678}, {3.14, 1.678}}, diff --git a/pgtype/bytea_test.go b/pgtype/bytea_test.go index 443b73ce..7a348ebb 100644 --- a/pgtype/bytea_test.go +++ b/pgtype/bytea_test.go @@ -5,8 +5,9 @@ import ( "context" "testing" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/require" ) @@ -28,7 +29,7 @@ func isExpectedEqBytes(a interface{}) func(interface{}) bool { } func TestByteaCodec(t *testing.T) { - testutil.RunTranscodeTests(t, "bytea", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "bytea", []pgxtest.ValueRoundTripTest{ {[]byte{1, 2, 3}, new([]byte), isExpectedEqBytes([]byte{1, 2, 3})}, {[]byte{}, new([]byte), isExpectedEqBytes([]byte{})}, {[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, @@ -37,91 +38,79 @@ func TestByteaCodec(t *testing.T) { } func TestDriverBytesQueryRow(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - ctx := context.Background() - - var buf []byte - err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.DriverBytes)(&buf)) - require.EqualError(t, err, "cannot scan into *pgtype.DriverBytes from QueryRow") + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + var buf []byte + err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.DriverBytes)(&buf)) + require.EqualError(t, err, "cannot scan into *pgtype.DriverBytes from QueryRow") + }) } func TestDriverBytes(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - ctx := context.Background() - - argBuf := make([]byte, 128) - for i := range argBuf { - argBuf[i] = byte(i) - } - - rows, err := conn.Query(ctx, `select $1::bytea from generate_series(1, 1000)`, argBuf) - require.NoError(t, err) - defer rows.Close() - - rowCount := 0 - resultBuf := argBuf - detectedResultMutation := false - for rows.Next() { - rowCount++ - - // At some point the buffer should be reused and change. - if bytes.Compare(argBuf, resultBuf) != 0 { - detectedResultMutation = true + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + argBuf := make([]byte, 128) + for i := range argBuf { + argBuf[i] = byte(i) } - err = rows.Scan((*pgtype.DriverBytes)(&resultBuf)) + rows, err := conn.Query(ctx, `select $1::bytea from generate_series(1, 1000)`, argBuf) require.NoError(t, err) + defer rows.Close() - require.Len(t, resultBuf, len(argBuf)) - require.Equal(t, resultBuf, argBuf) - require.Equalf(t, cap(resultBuf), len(resultBuf), "cap(resultBuf) is larger than len(resultBuf)") - } + rowCount := 0 + resultBuf := argBuf + detectedResultMutation := false + for rows.Next() { + rowCount++ - require.True(t, detectedResultMutation) + // At some point the buffer should be reused and change. + if bytes.Compare(argBuf, resultBuf) != 0 { + detectedResultMutation = true + } - err = rows.Err() - require.NoError(t, err) + err = rows.Scan((*pgtype.DriverBytes)(&resultBuf)) + require.NoError(t, err) + + require.Len(t, resultBuf, len(argBuf)) + require.Equal(t, resultBuf, argBuf) + require.Equalf(t, cap(resultBuf), len(resultBuf), "cap(resultBuf) is larger than len(resultBuf)") + } + + require.True(t, detectedResultMutation) + + err = rows.Err() + require.NoError(t, err) + }) } func TestPreallocBytes(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + origBuf := []byte{5, 6, 7, 8} + buf := origBuf + err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.PreallocBytes)(&buf)) + require.NoError(t, err) - ctx := context.Background() + require.Len(t, buf, 2) + require.Equal(t, 4, cap(buf)) + require.Equal(t, buf, []byte{1, 2}) - origBuf := []byte{5, 6, 7, 8} - buf := origBuf - err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.PreallocBytes)(&buf)) - require.NoError(t, err) + require.Equal(t, []byte{1, 2, 7, 8}, origBuf) - require.Len(t, buf, 2) - require.Equal(t, 4, cap(buf)) - require.Equal(t, buf, []byte{1, 2}) + err = conn.QueryRow(ctx, `select $1::bytea`, []byte{3, 4, 5, 6, 7}).Scan((*pgtype.PreallocBytes)(&buf)) + require.NoError(t, err) + require.Len(t, buf, 5) + require.Equal(t, 5, cap(buf)) - require.Equal(t, []byte{1, 2, 7, 8}, origBuf) - - err = conn.QueryRow(ctx, `select $1::bytea`, []byte{3, 4, 5, 6, 7}).Scan((*pgtype.PreallocBytes)(&buf)) - require.NoError(t, err) - require.Len(t, buf, 5) - require.Equal(t, 5, cap(buf)) - - require.Equal(t, []byte{1, 2, 7, 8}, origBuf) + require.Equal(t, []byte{1, 2, 7, 8}, origBuf) + }) } func TestUndecodedBytes(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + var buf []byte + err := conn.QueryRow(ctx, `select 1::int4`).Scan((*pgtype.UndecodedBytes)(&buf)) + require.NoError(t, err) - ctx := context.Background() - - var buf []byte - err := conn.QueryRow(ctx, `select 1::int4`).Scan((*pgtype.UndecodedBytes)(&buf)) - require.NoError(t, err) - - require.Len(t, buf, 4) - require.Equal(t, buf, []byte{0, 0, 0, 1}) + require.Len(t, buf, 4) + require.Equal(t, buf, []byte{0, 0, 0, 1}) + }) } diff --git a/pgtype/circle_test.go b/pgtype/circle_test.go index b78d35ba..7b6db777 100644 --- a/pgtype/circle_test.go +++ b/pgtype/circle_test.go @@ -1,16 +1,17 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestCircleTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support box type") - testutil.RunTranscodeTests(t, "circle", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "circle", []pgxtest.ValueRoundTripTest{ { pgtype.Circle{P: pgtype.Vec2{1.234, 5.67890123}, R: 3.5, Valid: true}, new(pgtype.Circle), diff --git a/pgtype/composite_test.go b/pgtype/composite_test.go index 0f112ebd..559403d8 100644 --- a/pgtype/composite_test.go +++ b/pgtype/composite_test.go @@ -7,50 +7,49 @@ import ( pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/stretchr/testify/require" ) func TestCompositeCodecTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - _, err := conn.Exec(context.Background(), `drop type if exists ct_test; + _, err := conn.Exec(ctx, `drop type if exists ct_test; create type ct_test as ( a text, b int4 );`) - require.NoError(t, err) - defer conn.Exec(context.Background(), "drop type ct_test") + require.NoError(t, err) + defer conn.Exec(ctx, "drop type ct_test") - dt, err := conn.LoadType(context.Background(), "ct_test") - require.NoError(t, err) - conn.TypeMap().RegisterType(dt) + dt, err := conn.LoadType(ctx, "ct_test") + require.NoError(t, err) + conn.TypeMap().RegisterType(dt) - formats := []struct { - name string - code int16 - }{ - {name: "TextFormat", code: pgx.TextFormatCode}, - {name: "BinaryFormat", code: pgx.BinaryFormatCode}, - } + formats := []struct { + name string + code int16 + }{ + {name: "TextFormat", code: pgx.TextFormatCode}, + {name: "BinaryFormat", code: pgx.BinaryFormatCode}, + } - for _, format := range formats { - var a string - var b int32 + for _, format := range formats { + var a string + var b int32 - err := conn.QueryRow(context.Background(), "select $1::ct_test", pgx.QueryResultFormats{format.code}, - pgtype.CompositeFields{"hi", int32(42)}, - ).Scan( - pgtype.CompositeFields{&a, &b}, - ) - require.NoErrorf(t, err, "%v", format.name) - require.EqualValuesf(t, "hi", a, "%v", format.name) - require.EqualValuesf(t, 42, b, "%v", format.name) - } + err := conn.QueryRow(ctx, "select $1::ct_test", pgx.QueryResultFormats{format.code}, + pgtype.CompositeFields{"hi", int32(42)}, + ).Scan( + pgtype.CompositeFields{&a, &b}, + ) + require.NoErrorf(t, err, "%v", format.name) + require.EqualValuesf(t, "hi", a, "%v", format.name) + require.EqualValuesf(t, 42, b, "%v", format.name) + } + }) } type point3d struct { @@ -94,118 +93,118 @@ func (p *point3d) ScanIndex(i int) interface{} { func TestCompositeCodecTranscodeStruct(t *testing.T) { skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - _, err := conn.Exec(context.Background(), `drop type if exists point3d; + _, err := conn.Exec(ctx, `drop type if exists point3d; create type point3d as ( x float8, y float8, z float8 );`) - require.NoError(t, err) - defer conn.Exec(context.Background(), "drop type point3d") + require.NoError(t, err) + defer conn.Exec(ctx, "drop type point3d") - dt, err := conn.LoadType(context.Background(), "point3d") - require.NoError(t, err) - conn.TypeMap().RegisterType(dt) + dt, err := conn.LoadType(ctx, "point3d") + require.NoError(t, err) + conn.TypeMap().RegisterType(dt) - formats := []struct { - name string - code int16 - }{ - {name: "TextFormat", code: pgx.TextFormatCode}, - {name: "BinaryFormat", code: pgx.BinaryFormatCode}, - } + formats := []struct { + name string + code int16 + }{ + {name: "TextFormat", code: pgx.TextFormatCode}, + {name: "BinaryFormat", code: pgx.BinaryFormatCode}, + } - for _, format := range formats { - input := point3d{X: 1, Y: 2, Z: 3} - var output point3d - err := conn.QueryRow(context.Background(), "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) - require.NoErrorf(t, err, "%v", format.name) - require.Equalf(t, input, output, "%v", format.name) - } + for _, format := range formats { + input := point3d{X: 1, Y: 2, Z: 3} + var output point3d + err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) + require.NoErrorf(t, err, "%v", format.name) + require.Equalf(t, input, output, "%v", format.name) + } + }) } func TestCompositeCodecTranscodeStructWrapper(t *testing.T) { skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - _, err := conn.Exec(context.Background(), `drop type if exists point3d; + _, err := conn.Exec(ctx, `drop type if exists point3d; create type point3d as ( x float8, y float8, z float8 );`) - require.NoError(t, err) - defer conn.Exec(context.Background(), "drop type point3d") + require.NoError(t, err) + defer conn.Exec(ctx, "drop type point3d") - dt, err := conn.LoadType(context.Background(), "point3d") - require.NoError(t, err) - conn.TypeMap().RegisterType(dt) + dt, err := conn.LoadType(ctx, "point3d") + require.NoError(t, err) + conn.TypeMap().RegisterType(dt) - formats := []struct { - name string - code int16 - }{ - {name: "TextFormat", code: pgx.TextFormatCode}, - {name: "BinaryFormat", code: pgx.BinaryFormatCode}, - } + formats := []struct { + name string + code int16 + }{ + {name: "TextFormat", code: pgx.TextFormatCode}, + {name: "BinaryFormat", code: pgx.BinaryFormatCode}, + } - type anotherPoint struct { - X, Y, Z float64 - } + type anotherPoint struct { + X, Y, Z float64 + } - for _, format := range formats { - input := anotherPoint{X: 1, Y: 2, Z: 3} - var output anotherPoint - err := conn.QueryRow(context.Background(), "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) - require.NoErrorf(t, err, "%v", format.name) - require.Equalf(t, input, output, "%v", format.name) - } + for _, format := range formats { + input := anotherPoint{X: 1, Y: 2, Z: 3} + var output anotherPoint + err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) + require.NoErrorf(t, err, "%v", format.name) + require.Equalf(t, input, output, "%v", format.name) + } + }) } func TestCompositeCodecDecodeValue(t *testing.T) { skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - _, err := conn.Exec(context.Background(), `drop type if exists point3d; + _, err := conn.Exec(ctx, `drop type if exists point3d; create type point3d as ( x float8, y float8, z float8 );`) - require.NoError(t, err) - defer conn.Exec(context.Background(), "drop type point3d") + require.NoError(t, err) + defer conn.Exec(ctx, "drop type point3d") - dt, err := conn.LoadType(context.Background(), "point3d") - require.NoError(t, err) - conn.TypeMap().RegisterType(dt) + dt, err := conn.LoadType(ctx, "point3d") + require.NoError(t, err) + conn.TypeMap().RegisterType(dt) - formats := []struct { - name string - code int16 - }{ - {name: "TextFormat", code: pgx.TextFormatCode}, - {name: "BinaryFormat", code: pgx.BinaryFormatCode}, - } + formats := []struct { + name string + code int16 + }{ + {name: "TextFormat", code: pgx.TextFormatCode}, + {name: "BinaryFormat", code: pgx.BinaryFormatCode}, + } - for _, format := range formats { - rows, err := conn.Query(context.Background(), "select '(1,2,3)'::point3d", pgx.QueryResultFormats{format.code}) - require.NoErrorf(t, err, "%v", format.name) - require.True(t, rows.Next()) - values, err := rows.Values() - require.NoErrorf(t, err, "%v", format.name) - require.Lenf(t, values, 1, "%v", format.name) - require.Equalf(t, map[string]interface{}{"x": 1.0, "y": 2.0, "z": 3.0}, values[0], "%v", format.name) - require.False(t, rows.Next()) - require.NoErrorf(t, rows.Err(), "%v", format.name) - } + for _, format := range formats { + rows, err := conn.Query(ctx, "select '(1,2,3)'::point3d", pgx.QueryResultFormats{format.code}) + require.NoErrorf(t, err, "%v", format.name) + require.True(t, rows.Next()) + values, err := rows.Values() + require.NoErrorf(t, err, "%v", format.name) + require.Lenf(t, values, 1, "%v", format.name) + require.Equalf(t, map[string]interface{}{"x": 1.0, "y": 2.0, "z": 3.0}, values[0], "%v", format.name) + require.False(t, rows.Next()) + require.NoErrorf(t, rows.Err(), "%v", format.name) + } + }) } diff --git a/pgtype/date_test.go b/pgtype/date_test.go index 06539822..25c6bfc2 100644 --- a/pgtype/date_test.go +++ b/pgtype/date_test.go @@ -1,11 +1,12 @@ package pgtype_test import ( + "context" "testing" "time" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqTime(a interface{}) func(interface{}) bool { @@ -18,7 +19,7 @@ func isExpectedEqTime(a interface{}) func(interface{}) bool { } func TestDateCodec(t *testing.T) { - testutil.RunTranscodeTests(t, "date", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "date", []pgxtest.ValueRoundTripTest{ {time.Date(-100, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(-100, 1, 1, 0, 0, 0, 0, time.UTC))}, {time.Date(-1, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(-1, 1, 1, 0, 0, 0, 0, time.UTC))}, {time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC))}, diff --git a/pgtype/enum_codec_test.go b/pgtype/enum_codec_test.go index afd062a2..633b610b 100644 --- a/pgtype/enum_codec_test.go +++ b/pgtype/enum_codec_test.go @@ -4,66 +4,66 @@ import ( "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" + pgx "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" ) func TestEnumCodec(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - _, err := conn.Exec(context.Background(), `drop type if exists enum_test; + _, err := conn.Exec(ctx, `drop type if exists enum_test; create type enum_test as enum ('foo', 'bar', 'baz');`) - require.NoError(t, err) - defer conn.Exec(context.Background(), "drop type enum_test") + require.NoError(t, err) + defer conn.Exec(ctx, "drop type enum_test") - dt, err := conn.LoadType(context.Background(), "enum_test") - require.NoError(t, err) + dt, err := conn.LoadType(ctx, "enum_test") + require.NoError(t, err) - conn.TypeMap().RegisterType(dt) + conn.TypeMap().RegisterType(dt) - var s string - err = conn.QueryRow(context.Background(), `select 'foo'::enum_test`).Scan(&s) - require.NoError(t, err) - require.Equal(t, "foo", s) + var s string + err = conn.QueryRow(ctx, `select 'foo'::enum_test`).Scan(&s) + require.NoError(t, err) + require.Equal(t, "foo", s) - err = conn.QueryRow(context.Background(), `select $1::enum_test`, "bar").Scan(&s) - require.NoError(t, err) - require.Equal(t, "bar", s) + err = conn.QueryRow(ctx, `select $1::enum_test`, "bar").Scan(&s) + require.NoError(t, err) + require.Equal(t, "bar", s) - err = conn.QueryRow(context.Background(), `select 'foo'::enum_test`).Scan(&s) - require.NoError(t, err) - require.Equal(t, "foo", s) + err = conn.QueryRow(ctx, `select 'foo'::enum_test`).Scan(&s) + require.NoError(t, err) + require.Equal(t, "foo", s) - err = conn.QueryRow(context.Background(), `select $1::enum_test`, "bar").Scan(&s) - require.NoError(t, err) - require.Equal(t, "bar", s) + err = conn.QueryRow(ctx, `select $1::enum_test`, "bar").Scan(&s) + require.NoError(t, err) + require.Equal(t, "bar", s) - err = conn.QueryRow(context.Background(), `select 'baz'::enum_test`).Scan(&s) - require.NoError(t, err) - require.Equal(t, "baz", s) + err = conn.QueryRow(ctx, `select 'baz'::enum_test`).Scan(&s) + require.NoError(t, err) + require.Equal(t, "baz", s) + }) } func TestEnumCodecValues(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - _, err := conn.Exec(context.Background(), `drop type if exists enum_test; + _, err := conn.Exec(ctx, `drop type if exists enum_test; create type enum_test as enum ('foo', 'bar', 'baz');`) - require.NoError(t, err) - defer conn.Exec(context.Background(), "drop type enum_test") + require.NoError(t, err) + defer conn.Exec(ctx, "drop type enum_test") - dt, err := conn.LoadType(context.Background(), "enum_test") - require.NoError(t, err) + dt, err := conn.LoadType(ctx, "enum_test") + require.NoError(t, err) - conn.TypeMap().RegisterType(dt) + conn.TypeMap().RegisterType(dt) - rows, err := conn.Query(context.Background(), `select 'foo'::enum_test`) - require.NoError(t, err) - require.True(t, rows.Next()) - values, err := rows.Values() - require.NoError(t, err) - require.Equal(t, values, []interface{}{"foo"}) + rows, err := conn.Query(ctx, `select 'foo'::enum_test`) + require.NoError(t, err) + require.True(t, rows.Next()) + values, err := rows.Values() + require.NoError(t, err) + require.Equal(t, values, []interface{}{"foo"}) + }) } diff --git a/pgtype/float4_test.go b/pgtype/float4_test.go index 39d7ee75..00b9addf 100644 --- a/pgtype/float4_test.go +++ b/pgtype/float4_test.go @@ -1,14 +1,15 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestFloat4Codec(t *testing.T) { - testutil.RunTranscodeTests(t, "float4", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "float4", []pgxtest.ValueRoundTripTest{ {pgtype.Float4{Float32: -1, Valid: true}, new(pgtype.Float4), isExpectedEq(pgtype.Float4{Float32: -1, Valid: true})}, {pgtype.Float4{Float32: 0, Valid: true}, new(pgtype.Float4), isExpectedEq(pgtype.Float4{Float32: 0, Valid: true})}, {pgtype.Float4{Float32: 1, Valid: true}, new(pgtype.Float4), isExpectedEq(pgtype.Float4{Float32: 1, Valid: true})}, diff --git a/pgtype/float8_test.go b/pgtype/float8_test.go index 29bd6f31..9c269072 100644 --- a/pgtype/float8_test.go +++ b/pgtype/float8_test.go @@ -1,14 +1,15 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestFloat8Codec(t *testing.T) { - testutil.RunTranscodeTests(t, "float8", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "float8", []pgxtest.ValueRoundTripTest{ {pgtype.Float8{Float64: -1, Valid: true}, new(pgtype.Float8), isExpectedEq(pgtype.Float8{Float64: -1, Valid: true})}, {pgtype.Float8{Float64: 0, Valid: true}, new(pgtype.Float8), isExpectedEq(pgtype.Float8{Float64: 0, Valid: true})}, {pgtype.Float8{Float64: 1, Valid: true}, new(pgtype.Float8), isExpectedEq(pgtype.Float8{Float64: 1, Valid: true})}, diff --git a/pgtype/hstore_test.go b/pgtype/hstore_test.go index 8141687a..fb0cc27b 100644 --- a/pgtype/hstore_test.go +++ b/pgtype/hstore_test.go @@ -6,7 +6,7 @@ import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqMapStringString(a interface{}) func(interface{}) bool { @@ -52,30 +52,22 @@ func isExpectedEqMapStringPointerString(a interface{}) func(interface{}) bool { } func TestHstoreCodec(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + ctr := defaultConnTestRunner + ctr.AfterConnect = func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + var hstoreOID uint32 + err := conn.QueryRow(context.Background(), `select oid from pg_type where typname = 'hstore'`).Scan(&hstoreOID) + if err != nil { + t.Skipf("Skipping: cannot find hstore OID") + } - var hstoreOID uint32 - err := conn.QueryRow(context.Background(), `select oid from pg_type where typname = 'hstore'`).Scan(&hstoreOID) - if err != nil { - t.Skipf("Skipping: cannot find hstore OID") - } - - conn.TypeMap().RegisterType(&pgtype.Type{Name: "hstore", OID: hstoreOID, Codec: pgtype.HstoreCodec{}}) - - formats := []struct { - name string - code int16 - }{ - {name: "TextFormat", code: pgx.TextFormatCode}, - {name: "BinaryFormat", code: pgx.BinaryFormatCode}, + conn.TypeMap().RegisterType(&pgtype.Type{Name: "hstore", OID: hstoreOID, Codec: pgtype.HstoreCodec{}}) } fs := func(s string) *string { return &s } - tests := []testutil.TranscodeTestCase{ + tests := []pgxtest.ValueRoundTripTest{ { map[string]string{}, new(map[string]string), @@ -134,25 +126,25 @@ func TestHstoreCodec(t *testing.T) { // Special key values // at beginning - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{s + "foo": "bar"}, new(map[string]string), isExpectedEqMapStringString(map[string]string{s + "foo": "bar"}), }) // in middle - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{"foo" + s + "bar": "bar"}, new(map[string]string), isExpectedEqMapStringString(map[string]string{"foo" + s + "bar": "bar"}), }) // at end - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{"foo" + s: "bar"}, new(map[string]string), isExpectedEqMapStringString(map[string]string{"foo" + s: "bar"}), }) // is key - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{s: "bar"}, new(map[string]string), isExpectedEqMapStringString(map[string]string{s: "bar"}), @@ -161,32 +153,30 @@ func TestHstoreCodec(t *testing.T) { // Special value values // at beginning - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{"foo": s + "bar"}, new(map[string]string), isExpectedEqMapStringString(map[string]string{"foo": s + "bar"}), }) // in middle - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{"foo": "foo" + s + "bar"}, new(map[string]string), isExpectedEqMapStringString(map[string]string{"foo": "foo" + s + "bar"}), }) // at end - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{"foo": "foo" + s}, new(map[string]string), isExpectedEqMapStringString(map[string]string{"foo": "foo" + s}), }) // is key - tests = append(tests, testutil.TranscodeTestCase{ + tests = append(tests, pgxtest.ValueRoundTripTest{ map[string]string{"foo": s}, new(map[string]string), isExpectedEqMapStringString(map[string]string{"foo": s}), }) } - for _, format := range formats { - testutil.RunTranscodeTestsFormat(t, "hstore", tests, conn, format.name, format.code) - } + pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, pgxtest.KnownOIDQueryExecModes, "hstore", tests) } diff --git a/pgtype/inet_test.go b/pgtype/inet_test.go index 249caf3f..8bf11a76 100644 --- a/pgtype/inet_test.go +++ b/pgtype/inet_test.go @@ -1,11 +1,12 @@ package pgtype_test import ( + "context" "net" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqIPNet(a interface{}) func(interface{}) bool { @@ -18,7 +19,7 @@ func isExpectedEqIPNet(a interface{}) func(interface{}) bool { } func TestInetTranscode(t *testing.T) { - testutil.RunTranscodeTests(t, "inet", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "inet", []pgxtest.ValueRoundTripTest{ {mustParseInet(t, "0.0.0.0/32"), new(net.IPNet), isExpectedEqIPNet(mustParseInet(t, "0.0.0.0/32"))}, {mustParseInet(t, "127.0.0.1/8"), new(net.IPNet), isExpectedEqIPNet(mustParseInet(t, "127.0.0.1/8"))}, {mustParseInet(t, "12.34.56.65/32"), new(net.IPNet), isExpectedEqIPNet(mustParseInet(t, "12.34.56.65/32"))}, @@ -37,7 +38,7 @@ func TestInetTranscode(t *testing.T) { func TestCidrTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support cidr type (see https://github.com/cockroachdb/cockroach/issues/18846)") - testutil.RunTranscodeTests(t, "cidr", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "cidr", []pgxtest.ValueRoundTripTest{ {mustParseInet(t, "0.0.0.0/32"), new(net.IPNet), isExpectedEqIPNet(mustParseInet(t, "0.0.0.0/32"))}, {mustParseInet(t, "127.0.0.1/32"), new(net.IPNet), isExpectedEqIPNet(mustParseInet(t, "127.0.0.1/32"))}, {mustParseInet(t, "12.34.56.0/32"), new(net.IPNet), isExpectedEqIPNet(mustParseInet(t, "12.34.56.0/32"))}, diff --git a/pgtype/int_test.go b/pgtype/int_test.go index 6dc65259..c779bdc9 100644 --- a/pgtype/int_test.go +++ b/pgtype/int_test.go @@ -2,15 +2,16 @@ package pgtype_test import ( + "context" "math" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestInt2Codec(t *testing.T) { - testutil.RunTranscodeTests(t, "int2", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int2", []pgxtest.ValueRoundTripTest{ {int8(1), new(int16), isExpectedEq(int16(1))}, {int16(1), new(int16), isExpectedEq(int16(1))}, {int32(1), new(int16), isExpectedEq(int16(1))}, @@ -91,7 +92,7 @@ func TestInt2UnmarshalJSON(t *testing.T) { } func TestInt4Codec(t *testing.T) { - testutil.RunTranscodeTests(t, "int4", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int4", []pgxtest.ValueRoundTripTest{ {int8(1), new(int32), isExpectedEq(int32(1))}, {int16(1), new(int32), isExpectedEq(int32(1))}, {int32(1), new(int32), isExpectedEq(int32(1))}, @@ -172,7 +173,7 @@ func TestInt4UnmarshalJSON(t *testing.T) { } func TestInt8Codec(t *testing.T) { - testutil.RunTranscodeTests(t, "int8", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int8", []pgxtest.ValueRoundTripTest{ {int8(1), new(int64), isExpectedEq(int64(1))}, {int16(1), new(int64), isExpectedEq(int64(1))}, {int32(1), new(int64), isExpectedEq(int64(1))}, diff --git a/pgtype/int_test.go.erb b/pgtype/int_test.go.erb index d55851c2..799d8c32 100644 --- a/pgtype/int_test.go.erb +++ b/pgtype/int_test.go.erb @@ -10,7 +10,7 @@ import ( <% [2, 4, 8].each do |pg_byte_size| %> <% pg_bit_size = pg_byte_size * 8 %> func TestInt<%= pg_byte_size %>Codec(t *testing.T) { - testutil.RunTranscodeTests(t, "int<%= pg_byte_size %>", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int<%= pg_byte_size %>", []pgxtest.ValueRoundTripTest{ {int8(1), new(int<%= pg_bit_size %>), isExpectedEq(int<%= pg_bit_size %>(1))}, {int16(1), new(int<%= pg_bit_size %>), isExpectedEq(int<%= pg_bit_size %>(1))}, {int32(1), new(int<%= pg_bit_size %>), isExpectedEq(int<%= pg_bit_size %>(1))}, diff --git a/pgtype/integration_benchmark_test.go b/pgtype/integration_benchmark_test.go index 58934ead..66758d07 100644 --- a/pgtype/integration_benchmark_test.go +++ b/pgtype/integration_benchmark_test.go @@ -7,1405 +7,1334 @@ import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" ) func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int16_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int16_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int16_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int16_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int16_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int16_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int16_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int16_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int16 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int16 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int32_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int32_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int32_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int32_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int32_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int32_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int32_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int32_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_int64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_int64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_uint64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_uint64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_uint64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_uint64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_uint64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_uint64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_uint64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_uint64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]uint64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]uint64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_pgtype_Int4_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_pgtype_Int4_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_pgtype_Int4_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_pgtype_Int4_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_pgtype_Int4_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_pgtype_Int4_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_int4_to_Go_pgtype_Int4_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_int4_to_Go_pgtype_Int4_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Int4 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Int4 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::int4 + 0, n::int4 + 1, n::int4 + 2, n::int4 + 3, n::int4 + 4, n::int4 + 5, n::int4 + 6, n::int4 + 7, n::int4 + 8, n::int4 + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_int64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_int64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_int64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_int64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_int64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_int64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_int64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_int64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]int64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]int64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_float64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_float64_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_float64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_float64_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_float64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_float64_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_float64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_float64_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]float64 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]float64 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_pgtype_Numeric_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_pgtype_Numeric_1_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_pgtype_Numeric_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_pgtype_Numeric_1_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 1) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_pgtype_Numeric_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_pgtype_Numeric_10_rows_1_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [1]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0 from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [1]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0 from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_numeric_to_Go_pgtype_Numeric_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_numeric_to_Go_pgtype_Numeric_100_rows_10_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [10]pgtype.Numeric - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [10]pgtype.Numeric + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select n::numeric + 0, n::numeric + 1, n::numeric + 2, n::numeric + 3, n::numeric + 4, n::numeric + 5, n::numeric + 6, n::numeric + 7, n::numeric + 8, n::numeric + 9 from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_Int4Array_With_Go_Int4Array_10(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v []int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select array_agg(n) from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v []int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select array_agg(n) from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_Int4Array_With_Go_Int4Array_10(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v []int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select array_agg(n) from generate_series(1, 10) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v []int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select array_agg(n) from generate_series(1, 10) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_Int4Array_With_Go_Int4Array_100(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v []int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select array_agg(n) from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v []int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select array_agg(n) from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_Int4Array_With_Go_Int4Array_100(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v []int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select array_agg(n) from generate_series(1, 100) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v []int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select array_agg(n) from generate_series(1, 100) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryTextFormatDecode_PG_Int4Array_With_Go_Int4Array_1000(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v []int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select array_agg(n) from generate_series(1, 1000) n`, - []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, - []interface{}{&v}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v []int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select array_agg(n) from generate_series(1, 1000) n`, + []interface{}{pgx.QueryResultFormats{pgx.TextFormatCode}}, + []interface{}{&v}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } func BenchmarkQueryBinaryFormatDecode_PG_Int4Array_With_Go_Int4Array_1000(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v []int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select array_agg(n) from generate_series(1, 1000) n`, - []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, - []interface{}{&v}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v []int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select array_agg(n) from generate_series(1, 1000) n`, + []interface{}{pgx.QueryResultFormats{pgx.BinaryFormatCode}}, + []interface{}{&v}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } } - } + }) } diff --git a/pgtype/integration_benchmark_test.go.erb b/pgtype/integration_benchmark_test.go.erb index de9cabc9..b122c606 100644 --- a/pgtype/integration_benchmark_test.go.erb +++ b/pgtype/integration_benchmark_test.go.erb @@ -18,23 +18,22 @@ import ( <% rows_columns.each do |rows, columns| %> <% [["Text", "pgx.TextFormatCode"], ["Binary", "pgx.BinaryFormatCode"]].each do |format_name, format_code| %> func BenchmarkQuery<%= format_name %>FormatDecode_PG_<%= pg_type %>_to_Go_<%= go_type.gsub(/\W/, "_") %>_<%= rows %>_rows_<%= columns %>_columns(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v [<%= columns %>]<%= go_type %> - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`, - []interface{}{pgx.QueryResultFormats{<%= format_code %>}}, - []interface{}{<% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>&v[<%= col_idx%>]<% end %>}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) - } - } + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v [<%= columns %>]<%= go_type %> + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`, + []interface{}{pgx.QueryResultFormats{<%= format_code %>}}, + []interface{}{<% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>&v[<%= col_idx%>]<% end %>}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } + } + }) } <% end %> <% end %> @@ -44,23 +43,22 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_<%= pg_type %>_to_Go_<%= go <% [10, 100, 1000].each do |array_size| %> <% [["Text", "pgx.TextFormatCode"], ["Binary", "pgx.BinaryFormatCode"]].each do |format_name, format_code| %> func BenchmarkQuery<%= format_name %>FormatDecode_PG_Int4Array_With_Go_Int4Array_<%= array_size %>(b *testing.B) { - conn := testutil.MustConnectPgx(b) - defer testutil.MustCloseContext(b, conn) - - b.ResetTimer() - var v []int32 - for i := 0; i < b.N; i++ { - _, err := conn.QueryFunc( - context.Background(), - `select array_agg(n) from generate_series(1, <%= array_size %>) n`, - []interface{}{pgx.QueryResultFormats{<%= format_code %>}}, - []interface{}{&v}, - func(pgx.QueryFuncRow) error { return nil }, - ) - if err != nil { - b.Fatal(err) - } - } + defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + b.ResetTimer() + var v []int32 + for i := 0; i < b.N; i++ { + _, err := conn.QueryFunc( + ctx, + `select array_agg(n) from generate_series(1, <%= array_size %>) n`, + []interface{}{pgx.QueryResultFormats{<%= format_code %>}}, + []interface{}{&v}, + func(pgx.QueryFuncRow) error { return nil }, + ) + if err != nil { + b.Fatal(err) + } + } + }) } <% end %> <% end %> diff --git a/pgtype/interval_test.go b/pgtype/interval_test.go index 310ea6bc..754c44e3 100644 --- a/pgtype/interval_test.go +++ b/pgtype/interval_test.go @@ -1,15 +1,16 @@ package pgtype_test import ( + "context" "testing" "time" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestIntervalCodec(t *testing.T) { - testutil.RunTranscodeTests(t, "interval", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "interval", []pgxtest.ValueRoundTripTest{ { pgtype.Interval{Microseconds: 1, Valid: true}, new(pgtype.Interval), diff --git a/pgtype/json_test.go b/pgtype/json_test.go index 39658bfa..0275b1e6 100644 --- a/pgtype/json_test.go +++ b/pgtype/json_test.go @@ -1,9 +1,10 @@ package pgtype_test import ( + "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqMap(a interface{}) func(interface{}) bool { @@ -39,7 +40,15 @@ func TestJSONCodec(t *testing.T) { Age int `json:"age"` } - testutil.RunTranscodeTests(t, "json", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "json", []pgxtest.ValueRoundTripTest{ + {nil, new(*jsonStruct), isExpectedEq((*jsonStruct)(nil))}, + {map[string]interface{}(nil), new(*string), isExpectedEq((*string)(nil))}, + {map[string]interface{}(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, + {[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, + {nil, new([]byte), isExpectedEqBytes([]byte(nil))}, + }) + + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, "json", []pgxtest.ValueRoundTripTest{ {[]byte("{}"), new([]byte), isExpectedEqBytes([]byte("{}"))}, {[]byte("null"), new([]byte), isExpectedEqBytes([]byte("null"))}, {[]byte("42"), new([]byte), isExpectedEqBytes([]byte("42"))}, @@ -47,10 +56,5 @@ func TestJSONCodec(t *testing.T) { {[]byte(`"hello"`), new(string), isExpectedEq(`"hello"`)}, {map[string]interface{}{"foo": "bar"}, new(map[string]interface{}), isExpectedEqMap(map[string]interface{}{"foo": "bar"})}, {jsonStruct{Name: "Adam", Age: 10}, new(jsonStruct), isExpectedEq(jsonStruct{Name: "Adam", Age: 10})}, - {nil, new(*jsonStruct), isExpectedEq((*jsonStruct)(nil))}, - {map[string]interface{}(nil), new(*string), isExpectedEq((*string)(nil))}, - {map[string]interface{}(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, - {[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, - {nil, new([]byte), isExpectedEqBytes([]byte(nil))}, }) } diff --git a/pgtype/jsonb_test.go b/pgtype/jsonb_test.go index c26499c6..4a9f7a35 100644 --- a/pgtype/jsonb_test.go +++ b/pgtype/jsonb_test.go @@ -1,9 +1,10 @@ package pgtype_test import ( + "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestJSONBTranscode(t *testing.T) { @@ -12,7 +13,15 @@ func TestJSONBTranscode(t *testing.T) { Age int `json:"age"` } - testutil.RunTranscodeTests(t, "jsonb", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "jsonb", []pgxtest.ValueRoundTripTest{ + {nil, new(*jsonStruct), isExpectedEq((*jsonStruct)(nil))}, + {map[string]interface{}(nil), new(*string), isExpectedEq((*string)(nil))}, + {map[string]interface{}(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, + {[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, + {nil, new([]byte), isExpectedEqBytes([]byte(nil))}, + }) + + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, "jsonb", []pgxtest.ValueRoundTripTest{ {[]byte("{}"), new([]byte), isExpectedEqBytes([]byte("{}"))}, {[]byte("null"), new([]byte), isExpectedEqBytes([]byte("null"))}, {[]byte("42"), new([]byte), isExpectedEqBytes([]byte("42"))}, @@ -20,10 +29,5 @@ func TestJSONBTranscode(t *testing.T) { {[]byte(`"hello"`), new(string), isExpectedEq(`"hello"`)}, {map[string]interface{}{"foo": "bar"}, new(map[string]interface{}), isExpectedEqMap(map[string]interface{}{"foo": "bar"})}, {jsonStruct{Name: "Adam", Age: 10}, new(jsonStruct), isExpectedEq(jsonStruct{Name: "Adam", Age: 10})}, - {nil, new(*jsonStruct), isExpectedEq((*jsonStruct)(nil))}, - {map[string]interface{}(nil), new(*string), isExpectedEq((*string)(nil))}, - {map[string]interface{}(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, - {[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, - {nil, new([]byte), isExpectedEqBytes([]byte(nil))}, }) } diff --git a/pgtype/line_test.go b/pgtype/line_test.go index 8e3d782c..dc980ce1 100644 --- a/pgtype/line_test.go +++ b/pgtype/line_test.go @@ -4,30 +4,32 @@ import ( "context" "testing" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestLineTranscode(t *testing.T) { - skipCockroachDB(t, "Server does not support type line") + ctr := defaultConnTestRunner + ctr.AfterConnect = func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + pgxtest.SkipCockroachDB(t, conn, "Server does not support type line") - conn := testutil.MustConnectPgx(t) - defer conn.Close(context.Background()) - if _, ok := conn.TypeMap().TypeForName("line"); !ok { - t.Skip("Skipping due to no line type") + if _, ok := conn.TypeMap().TypeForName("line"); !ok { + t.Skip("Skipping due to no line type") + } + + // line may exist but not be usable on 9.3 :( + var isPG93 bool + err := conn.QueryRow(context.Background(), "select version() ~ '9.3'").Scan(&isPG93) + if err != nil { + t.Fatal(err) + } + if isPG93 { + t.Skip("Skipping due to unimplemented line type in PG 9.3") + } } - // line may exist but not be usable on 9.3 :( - var isPG93 bool - err := conn.QueryRow(context.Background(), "select version() ~ '9.3'").Scan(&isPG93) - if err != nil { - t.Fatal(err) - } - if isPG93 { - t.Skip("Skipping due to unimplemented line type in PG 9.3") - } - - testutil.RunTranscodeTests(t, "line", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, nil, "line", []pgxtest.ValueRoundTripTest{ { pgtype.Line{ A: 1.23, B: 4.56, C: 7.89012345, diff --git a/pgtype/lseg_test.go b/pgtype/lseg_test.go index e754b3b2..04fde0eb 100644 --- a/pgtype/lseg_test.go +++ b/pgtype/lseg_test.go @@ -1,16 +1,17 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestLsegTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support type lseg") - testutil.RunTranscodeTests(t, "lseg", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "lseg", []pgxtest.ValueRoundTripTest{ { pgtype.Lseg{ P: [2]pgtype.Vec2{{3.14, 1.678}, {7.1, 5.2345678901}}, diff --git a/pgtype/macaddr_test.go b/pgtype/macaddr_test.go index 06262876..e2463271 100644 --- a/pgtype/macaddr_test.go +++ b/pgtype/macaddr_test.go @@ -2,10 +2,11 @@ package pgtype_test import ( "bytes" + "context" "net" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqHardwareAddr(a interface{}) func(interface{}) bool { @@ -28,7 +29,8 @@ func isExpectedEqHardwareAddr(a interface{}) func(interface{}) bool { func TestMacaddrCodec(t *testing.T) { skipCockroachDB(t, "Server does not support type macaddr") - testutil.RunTranscodeTests(t, "macaddr", []testutil.TranscodeTestCase{ + // Only testing known OID query exec modes as net.HardwareAddr could map to macaddr or macaddr8. + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, "macaddr", []pgxtest.ValueRoundTripTest{ { mustParseMacaddr(t, "01:23:45:67:89:ab"), new(net.HardwareAddr), diff --git a/pgtype/numeric_test.go b/pgtype/numeric_test.go index 281efa0f..8be8ce55 100644 --- a/pgtype/numeric_test.go +++ b/pgtype/numeric_test.go @@ -9,8 +9,9 @@ import ( "strconv" "testing" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -77,7 +78,7 @@ func TestNumericCodec(t *testing.T) { max.Add(max, big.NewInt(1)) longestNumeric := pgtype.Numeric{Int: max, Exp: -16383, Valid: true} - testutil.RunTranscodeTests(t, "numeric", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "numeric", []pgxtest.ValueRoundTripTest{ {mustParseNumeric(t, "1"), new(pgtype.Numeric), isExpectedEqNumeric(mustParseNumeric(t, "1"))}, {mustParseNumeric(t, "3.14159"), new(pgtype.Numeric), isExpectedEqNumeric(mustParseNumeric(t, "3.14159"))}, {mustParseNumeric(t, "100010001"), new(pgtype.Numeric), isExpectedEqNumeric(mustParseNumeric(t, "100010001"))}, @@ -118,7 +119,7 @@ func TestNumericCodecInfinity(t *testing.T) { skipCockroachDB(t, "server formats numeric text format differently") skipPostgreSQLVersionLessThan(t, 14) - testutil.RunTranscodeTests(t, "numeric", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "numeric", []pgxtest.ValueRoundTripTest{ {math.Inf(1), new(float64), isExpectedEq(math.Inf(1))}, {float32(math.Inf(1)), new(float32), isExpectedEq(float32(math.Inf(1)))}, {math.Inf(-1), new(float64), isExpectedEq(math.Inf(-1))}, @@ -159,54 +160,54 @@ func TestNumericCodecFuzz(t *testing.T) { max := &big.Int{} max.SetString("9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 10) - tests := make([]testutil.TranscodeTestCase, 0, 2000) + tests := make([]pgxtest.ValueRoundTripTest, 0, 2000) for i := 0; i < 10; i++ { for j := -50; j < 50; j++ { num := (&big.Int{}).Rand(r, max) n := pgtype.Numeric{Int: num, Exp: int32(j), Valid: true} - tests = append(tests, testutil.TranscodeTestCase{n, new(pgtype.Numeric), isExpectedEqNumeric(n)}) + tests = append(tests, pgxtest.ValueRoundTripTest{n, new(pgtype.Numeric), isExpectedEqNumeric(n)}) negNum := &big.Int{} negNum.Neg(num) n = pgtype.Numeric{Int: negNum, Exp: int32(j), Valid: true} - tests = append(tests, testutil.TranscodeTestCase{n, new(pgtype.Numeric), isExpectedEqNumeric(n)}) + tests = append(tests, pgxtest.ValueRoundTripTest{n, new(pgtype.Numeric), isExpectedEqNumeric(n)}) } } - testutil.RunTranscodeTests(t, "numeric", tests) + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "numeric", tests) } func TestNumericMarshalJSON(t *testing.T) { skipCockroachDB(t, "server formats numeric text format differently") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - for i, tt := range []struct { - decString string - }{ - {"NaN"}, - {"0"}, - {"1"}, - {"-1"}, - {"1000000000000000000"}, - {"1234.56789"}, - {"1.56789"}, - {"0.00000000000056789"}, - {"0.00123000"}, - {"123e-3"}, - {"243723409723490243842378942378901237502734019231380123e23790"}, - {"3409823409243892349028349023482934092340892390101e-14021"}, - } { - var num pgtype.Numeric - var pgJSON string - err := conn.QueryRow(context.Background(), `select $1::numeric, to_json($1::numeric)`, tt.decString).Scan(&num, &pgJSON) - require.NoErrorf(t, err, "%d", i) + for i, tt := range []struct { + decString string + }{ + {"NaN"}, + {"0"}, + {"1"}, + {"-1"}, + {"1000000000000000000"}, + {"1234.56789"}, + {"1.56789"}, + {"0.00000000000056789"}, + {"0.00123000"}, + {"123e-3"}, + {"243723409723490243842378942378901237502734019231380123e23790"}, + {"3409823409243892349028349023482934092340892390101e-14021"}, + } { + var num pgtype.Numeric + var pgJSON string + err := conn.QueryRow(ctx, `select $1::numeric, to_json($1::numeric)`, tt.decString).Scan(&num, &pgJSON) + require.NoErrorf(t, err, "%d", i) - goJSON, err := json.Marshal(num) - require.NoErrorf(t, err, "%d", i) + goJSON, err := json.Marshal(num) + require.NoErrorf(t, err, "%d", i) - require.Equal(t, pgJSON, string(goJSON)) - } + require.Equal(t, pgJSON, string(goJSON)) + } + }) } diff --git a/pgtype/path_test.go b/pgtype/path_test.go index 40df2bfb..f9e13294 100644 --- a/pgtype/path_test.go +++ b/pgtype/path_test.go @@ -1,10 +1,11 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqPath(a interface{}) func(interface{}) bool { @@ -29,7 +30,7 @@ func isExpectedEqPath(a interface{}) func(interface{}) bool { func TestPathTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support type path") - testutil.RunTranscodeTests(t, "path", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "path", []pgxtest.ValueRoundTripTest{ { pgtype.Path{ P: []pgtype.Vec2{{3.14, 1.678901234}, {7.1, 5.234}}, diff --git a/pgtype/pgtype.go b/pgtype/pgtype.go index ffc017f8..94158cb8 100644 --- a/pgtype/pgtype.go +++ b/pgtype/pgtype.go @@ -374,7 +374,7 @@ func NewMap() *Map { registerDefaultPgTypeVariants("daterange", "_daterange", Daterange{}) registerDefaultPgTypeVariants("float4", "_float4", Float4{}) registerDefaultPgTypeVariants("float8", "_float8", Float8{}) - registerDefaultPgTypeVariants("float8range", "_float8range", Float8range{}) + registerDefaultPgTypeVariants("numrange", "_numrange", Float8range{}) // There is no PostgreSQL builtin float8range so map it to numrange. registerDefaultPgTypeVariants("inet", "_inet", Inet{}) registerDefaultPgTypeVariants("int2", "_int2", Int2{}) registerDefaultPgTypeVariants("int4", "_int4", Int4{}) diff --git a/pgtype/pgtype_test.go b/pgtype/pgtype_test.go index dd0150fb..9778c335 100644 --- a/pgtype/pgtype_test.go +++ b/pgtype/pgtype_test.go @@ -1,21 +1,34 @@ package pgtype_test import ( + "context" "database/sql" "errors" "net" + "os" "regexp" "strconv" "testing" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" _ "github.com/jackc/pgx/v5/stdlib" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +var defaultConnTestRunner pgxtest.ConnTestRunner + +func init() { + defaultConnTestRunner = pgxtest.DefaultConnTestRunner() + defaultConnTestRunner.CreateConfig = func(ctx context.Context, t testing.TB) *pgx.ConnConfig { + config, err := pgx.ParseConfig(os.Getenv("PGX_TEST_DATABASE")) + require.NoError(t, err) + return config + } +} + // Test for renamed types type _string string type _bool bool @@ -70,8 +83,11 @@ func mustParseMacaddr(t testing.TB, s string) net.HardwareAddr { } func skipCockroachDB(t testing.TB, msg string) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE")) + if err != nil { + t.Fatal(err) + } + defer conn.Close(context.Background()) if conn.PgConn().ParameterStatus("crdb_version") != "" { t.Skip(msg) @@ -79,8 +95,11 @@ func skipCockroachDB(t testing.TB, msg string) { } func skipPostgreSQLVersionLessThan(t testing.TB, minVersion int64) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE")) + if err != nil { + t.Fatal(err) + } + defer conn.Close(context.Background()) serverVersionStr := conn.PgConn().ParameterStatus("server_version") serverVersionStr = regexp.MustCompile(`^[0-9]+`).FindString(serverVersionStr) diff --git a/pgtype/point_test.go b/pgtype/point_test.go index 62fcfc51..336f1a47 100644 --- a/pgtype/point_test.go +++ b/pgtype/point_test.go @@ -1,18 +1,19 @@ package pgtype_test import ( + "context" "reflect" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/require" ) func TestPointCodec(t *testing.T) { skipCockroachDB(t, "Server does not support type point") - testutil.RunTranscodeTests(t, "point", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "point", []pgxtest.ValueRoundTripTest{ { pgtype.Point{P: pgtype.Vec2{1.234, 5.6789012345}, Valid: true}, new(pgtype.Point), diff --git a/pgtype/polygon_test.go b/pgtype/polygon_test.go index 6c6fc60d..a6a60de2 100644 --- a/pgtype/polygon_test.go +++ b/pgtype/polygon_test.go @@ -1,10 +1,11 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqPolygon(a interface{}) func(interface{}) bool { @@ -29,7 +30,7 @@ func isExpectedEqPolygon(a interface{}) func(interface{}) bool { func TestPolygonTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support type polygon") - testutil.RunTranscodeTests(t, "polygon", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "polygon", []pgxtest.ValueRoundTripTest{ { pgtype.Polygon{ P: []pgtype.Vec2{{3.14, 1.678901234}, {7.1, 5.234}, {5.0, 3.234}}, diff --git a/pgtype/qchar_test.go b/pgtype/qchar_test.go index 0bf781a4..da00b89e 100644 --- a/pgtype/qchar_test.go +++ b/pgtype/qchar_test.go @@ -1,22 +1,24 @@ package pgtype_test import ( + "context" "math" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestQcharTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support qchar") - var tests []testutil.TranscodeTestCase + var tests []pgxtest.ValueRoundTripTest for i := 0; i <= math.MaxUint8; i++ { - tests = append(tests, testutil.TranscodeTestCase{rune(i), new(rune), isExpectedEq(rune(i))}) - tests = append(tests, testutil.TranscodeTestCase{byte(i), new(byte), isExpectedEq(byte(i))}) + tests = append(tests, pgxtest.ValueRoundTripTest{rune(i), new(rune), isExpectedEq(rune(i))}) + tests = append(tests, pgxtest.ValueRoundTripTest{byte(i), new(byte), isExpectedEq(byte(i))}) } - tests = append(tests, testutil.TranscodeTestCase{nil, new(*rune), isExpectedEq((*rune)(nil))}) - tests = append(tests, testutil.TranscodeTestCase{nil, new(*byte), isExpectedEq((*byte)(nil))}) + tests = append(tests, pgxtest.ValueRoundTripTest{nil, new(*rune), isExpectedEq((*rune)(nil))}) + tests = append(tests, pgxtest.ValueRoundTripTest{nil, new(*byte), isExpectedEq((*byte)(nil))}) - testutil.RunTranscodeTests(t, `"char"`, tests) + // Can only test with known OIDs as rune and byte would be considered numbers. + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, `"char"`, tests) } diff --git a/pgtype/range_codec_test.go b/pgtype/range_codec_test.go index b4127769..8c1116a0 100644 --- a/pgtype/range_codec_test.go +++ b/pgtype/range_codec_test.go @@ -4,15 +4,16 @@ import ( "context" "testing" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/require" ) func TestRangeCodecTranscode(t *testing.T) { skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)") - testutil.RunTranscodeTests(t, "int4range", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int4range", []pgxtest.ValueRoundTripTest{ { pgtype.Int4range{LowerType: pgtype.Empty, UpperType: pgtype.Empty, Valid: true}, new(pgtype.Int4range), @@ -39,9 +40,12 @@ func TestRangeCodecTranscode(t *testing.T) { } func TestRangeCodecTranscodeCompatibleRangeElementTypes(t *testing.T) { - skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)") + ctr := defaultConnTestRunner + ctr.AfterConnect = func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + pgxtest.SkipCockroachDB(t, conn, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)") + } - testutil.RunTranscodeTests(t, "numrange", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, nil, "numrange", []pgxtest.ValueRoundTripTest{ { pgtype.Float8range{LowerType: pgtype.Empty, UpperType: pgtype.Empty, Valid: true}, new(pgtype.Float8range), @@ -70,90 +74,90 @@ func TestRangeCodecTranscodeCompatibleRangeElementTypes(t *testing.T) { func TestRangeCodecScanRangeTwiceWithUnbounded(t *testing.T) { skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { - var r pgtype.Int4range + var r pgtype.Int4range - err := conn.QueryRow(context.Background(), `select '[1,5)'::int4range`).Scan(&r) - require.NoError(t, err) + err := conn.QueryRow(context.Background(), `select '[1,5)'::int4range`).Scan(&r) + require.NoError(t, err) - require.Equal( - t, - pgtype.Int4range{ - Lower: pgtype.Int4{Int32: 1, Valid: true}, - Upper: pgtype.Int4{Int32: 5, Valid: true}, - LowerType: pgtype.Inclusive, - UpperType: pgtype.Exclusive, - Valid: true, - }, - r, - ) + require.Equal( + t, + pgtype.Int4range{ + Lower: pgtype.Int4{Int32: 1, Valid: true}, + Upper: pgtype.Int4{Int32: 5, Valid: true}, + LowerType: pgtype.Inclusive, + UpperType: pgtype.Exclusive, + Valid: true, + }, + r, + ) - err = conn.QueryRow(context.Background(), `select '[1,)'::int4range`).Scan(&r) - require.NoError(t, err) + err = conn.QueryRow(ctx, `select '[1,)'::int4range`).Scan(&r) + require.NoError(t, err) - require.Equal( - t, - pgtype.Int4range{ - Lower: pgtype.Int4{Int32: 1, Valid: true}, - Upper: pgtype.Int4{}, - LowerType: pgtype.Inclusive, - UpperType: pgtype.Unbounded, - Valid: true, - }, - r, - ) + require.Equal( + t, + pgtype.Int4range{ + Lower: pgtype.Int4{Int32: 1, Valid: true}, + Upper: pgtype.Int4{}, + LowerType: pgtype.Inclusive, + UpperType: pgtype.Unbounded, + Valid: true, + }, + r, + ) - err = conn.QueryRow(context.Background(), `select 'empty'::int4range`).Scan(&r) - require.NoError(t, err) + err = conn.QueryRow(ctx, `select 'empty'::int4range`).Scan(&r) + require.NoError(t, err) - require.Equal( - t, - pgtype.Int4range{ - Lower: pgtype.Int4{}, - Upper: pgtype.Int4{}, - LowerType: pgtype.Empty, - UpperType: pgtype.Empty, - Valid: true, - }, - r, - ) + require.Equal( + t, + pgtype.Int4range{ + Lower: pgtype.Int4{}, + Upper: pgtype.Int4{}, + LowerType: pgtype.Empty, + UpperType: pgtype.Empty, + Valid: true, + }, + r, + ) + }) } func TestRangeCodecDecodeValue(t *testing.T) { skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { - for _, tt := range []struct { - sql string - expected interface{} - }{ - { - sql: `select '[1,5)'::int4range`, - expected: pgtype.GenericRange{ - Lower: int32(1), - Upper: int32(5), - LowerType: pgtype.Inclusive, - UpperType: pgtype.Exclusive, - Valid: true, + for _, tt := range []struct { + sql string + expected interface{} + }{ + { + sql: `select '[1,5)'::int4range`, + expected: pgtype.GenericRange{ + Lower: int32(1), + Upper: int32(5), + LowerType: pgtype.Inclusive, + UpperType: pgtype.Exclusive, + Valid: true, + }, }, - }, - } { - t.Run(tt.sql, func(t *testing.T) { - rows, err := conn.Query(context.Background(), tt.sql) - require.NoError(t, err) - - for rows.Next() { - values, err := rows.Values() + } { + t.Run(tt.sql, func(t *testing.T) { + rows, err := conn.Query(ctx, tt.sql) require.NoError(t, err) - require.Len(t, values, 1) - require.Equal(t, tt.expected, values[0]) - } - require.NoError(t, rows.Err()) - }) - } + for rows.Next() { + values, err := rows.Values() + require.NoError(t, err) + require.Len(t, values, 1) + require.Equal(t, tt.expected, values[0]) + } + + require.NoError(t, rows.Err()) + }) + } + }) } diff --git a/pgtype/record_codec_test.go b/pgtype/record_codec_test.go index d6fe603c..57fa87ff 100644 --- a/pgtype/record_codec_test.go +++ b/pgtype/record_codec_test.go @@ -4,72 +4,70 @@ import ( "context" "testing" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/stretchr/testify/require" ) func TestRecordCodec(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + var a string + var b int32 + err := conn.QueryRow(ctx, `select row('foo'::text, 42::int4)`).Scan(pgtype.CompositeFields{&a, &b}) + require.NoError(t, err) - var a string - var b int32 - err := conn.QueryRow(context.Background(), `select row('foo'::text, 42::int4)`).Scan(pgtype.CompositeFields{&a, &b}) - require.NoError(t, err) - - require.Equal(t, "foo", a) - require.Equal(t, int32(42), b) + require.Equal(t, "foo", a) + require.Equal(t, int32(42), b) + }) } func TestRecordCodecDecodeValue(t *testing.T) { skipCockroachDB(t, "Server converts row int4 to int8") - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - for _, tt := range []struct { - sql string - expected interface{} - }{ - { - sql: `select row()`, - expected: []interface{}{}, - }, - { - sql: `select row('foo'::text, 42::int4)`, - expected: []interface{}{"foo", int32(42)}, - }, - { - sql: `select row(100.0::float4, 1.09::float4)`, - expected: []interface{}{float32(100), float32(1.09)}, - }, - { - sql: `select row('foo'::text, array[1, 2, null, 4]::int4[], 42::int4)`, - expected: []interface{}{"foo", []interface{}{int32(1), int32(2), nil, int32(4)}, int32(42)}, - }, - { - sql: `select row(null)`, - expected: []interface{}{nil}, - }, - { - sql: `select null::record`, - expected: nil, - }, - } { - t.Run(tt.sql, func(t *testing.T) { - rows, err := conn.Query(context.Background(), tt.sql) - require.NoError(t, err) - defer rows.Close() - - for rows.Next() { - values, err := rows.Values() + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) { + for _, tt := range []struct { + sql string + expected interface{} + }{ + { + sql: `select row()`, + expected: []interface{}{}, + }, + { + sql: `select row('foo'::text, 42::int4)`, + expected: []interface{}{"foo", int32(42)}, + }, + { + sql: `select row(100.0::float4, 1.09::float4)`, + expected: []interface{}{float32(100), float32(1.09)}, + }, + { + sql: `select row('foo'::text, array[1, 2, null, 4]::int4[], 42::int4)`, + expected: []interface{}{"foo", []interface{}{int32(1), int32(2), nil, int32(4)}, int32(42)}, + }, + { + sql: `select row(null)`, + expected: []interface{}{nil}, + }, + { + sql: `select null::record`, + expected: nil, + }, + } { + t.Run(tt.sql, func(t *testing.T) { + rows, err := conn.Query(context.Background(), tt.sql) require.NoError(t, err) - require.Len(t, values, 1) - require.Equal(t, tt.expected, values[0]) - } + defer rows.Close() - require.NoError(t, rows.Err()) - }) - } + for rows.Next() { + values, err := rows.Values() + require.NoError(t, err) + require.Len(t, values, 1) + require.Equal(t, tt.expected, values[0]) + } + + require.NoError(t, rows.Err()) + }) + } + }) } diff --git a/pgtype/testutil/testutil.go b/pgtype/testutil/testutil.go deleted file mode 100644 index 19ed4412..00000000 --- a/pgtype/testutil/testutil.go +++ /dev/null @@ -1,85 +0,0 @@ -package testutil - -import ( - "context" - "fmt" - "os" - "reflect" - "testing" - - "github.com/jackc/pgx/v5" - _ "github.com/jackc/pgx/v5/stdlib" -) - -func MustConnectPgx(t testing.TB) *pgx.Conn { - conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE")) - if err != nil { - t.Fatal(err) - } - - return conn -} - -func MustClose(t testing.TB, conn interface { - Close() error -}) { - err := conn.Close() - if err != nil { - t.Fatal(err) - } -} - -func MustCloseContext(t testing.TB, conn interface { - Close(context.Context) error -}) { - err := conn.Close(context.Background()) - if err != nil { - t.Fatal(err) - } -} - -type TranscodeTestCase struct { - Src interface{} - Dst interface{} - Test func(interface{}) bool -} - -func RunTranscodeTests(t testing.TB, pgTypeName string, tests []TranscodeTestCase) { - conn := MustConnectPgx(t) - defer MustCloseContext(t, conn) - - formats := []struct { - name string - code int16 - }{ - {name: "TextFormat", code: pgx.TextFormatCode}, - {name: "BinaryFormat", code: pgx.BinaryFormatCode}, - } - - for _, format := range formats { - RunTranscodeTestsFormat(t, pgTypeName, tests, conn, format.name, format.code) - } -} - -func RunTranscodeTestsFormat(t testing.TB, pgTypeName string, tests []TranscodeTestCase, conn *pgx.Conn, formatName string, formatCode int16) { - _, err := conn.Prepare(context.Background(), "test", fmt.Sprintf("select $1::%s", pgTypeName)) - if err != nil { - t.Fatal(err) - } - - for i, tt := range tests { - err := conn.QueryRow(context.Background(), "test", pgx.QueryResultFormats{formatCode}, tt.Src).Scan(tt.Dst) - if err != nil { - t.Errorf("%s %d: %v", formatName, i, err) - } - - dst := reflect.ValueOf(tt.Dst) - if dst.Kind() == reflect.Ptr { - dst = dst.Elem() - } - - if !tt.Test(dst.Interface()) { - t.Errorf("%s %d: unexpected result for %v: %v", formatName, i, tt.Src, dst.Interface()) - } - } -} diff --git a/pgtype/text_test.go b/pgtype/text_test.go index c80c404b..1d717f49 100644 --- a/pgtype/text_test.go +++ b/pgtype/text_test.go @@ -4,8 +4,9 @@ import ( "context" "testing" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/require" ) @@ -17,7 +18,7 @@ func (someFmtStringer) String() string { func TestTextCodec(t *testing.T) { for _, pgTypeName := range []string{"text", "varchar"} { - testutil.RunTranscodeTests(t, pgTypeName, []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, pgTypeName, []pgxtest.ValueRoundTripTest{ { pgtype.Text{String: "", Valid: true}, new(pgtype.Text), @@ -31,6 +32,10 @@ func TestTextCodec(t *testing.T) { {nil, new(pgtype.Text), isExpectedEq(pgtype.Text{})}, {"foo", new(string), isExpectedEq("foo")}, {someFmtStringer{}, new(string), isExpectedEq("some fmt.Stringer")}, + }) + + // rune requires known OID because otherwise it is considered an int32. + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, pgTypeName, []pgxtest.ValueRoundTripTest{ {rune('R'), new(rune), isExpectedEq(rune('R'))}, }) } @@ -47,7 +52,7 @@ func TestTextCodec(t *testing.T) { // // So this is simply a smoke test of the name type. func TestTextCodecName(t *testing.T) { - testutil.RunTranscodeTests(t, "name", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "name", []pgxtest.ValueRoundTripTest{ { pgtype.Text{String: "", Valid: true}, new(pgtype.Text), @@ -67,7 +72,7 @@ func TestTextCodecName(t *testing.T) { func TestTextCodecBPChar(t *testing.T) { skipCockroachDB(t, "Server does not properly handle bpchar with multi-byte character") - testutil.RunTranscodeTests(t, "char(3)", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "char(3)", []pgxtest.ValueRoundTripTest{ { pgtype.Text{String: "a ", Valid: true}, new(pgtype.Text), @@ -94,12 +99,12 @@ func TestTextCodecBPChar(t *testing.T) { // // It only supports the text format. func TestTextCodecACLItem(t *testing.T) { - skipCockroachDB(t, "Server does not support type aclitem") + ctr := defaultConnTestRunner + ctr.AfterConnect = func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + pgxtest.SkipCockroachDB(t, conn, "Server does not support type aclitem") + } - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) - - testutil.RunTranscodeTestsFormat(t, "aclitem", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, nil, "aclitem", []pgxtest.ValueRoundTripTest{ { pgtype.Text{String: "postgres=arwdDxt/postgres", Valid: true}, new(pgtype.Text), @@ -107,33 +112,33 @@ func TestTextCodecACLItem(t *testing.T) { }, {pgtype.Text{}, new(pgtype.Text), isExpectedEq(pgtype.Text{})}, {nil, new(pgtype.Text), isExpectedEq(pgtype.Text{})}, - }, conn, "Text", pgtype.TextFormatCode) + }) } func TestTextCodecACLItemRoleWithSpecialCharacters(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + ctr := defaultConnTestRunner + ctr.AfterConnect = func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + pgxtest.SkipCockroachDB(t, conn, "Server does not support type aclitem") - ctx := context.Background() + // The tricky test user, below, has to actually exist so that it can be used in a test + // of aclitem formatting. It turns out aclitems cannot contain non-existing users/roles. + roleWithSpecialCharacters := ` tricky, ' } " \ test user ` - // The tricky test user, below, has to actually exist so that it can be used in a test - // of aclitem formatting. It turns out aclitems cannot contain non-existing users/roles. - roleWithSpecialCharacters := ` tricky, ' } " \ test user ` + commandTag, err := conn.Exec(ctx, `select * from pg_roles where rolname = $1`, roleWithSpecialCharacters) + require.NoError(t, err) - commandTag, err := conn.Exec(ctx, `select * from pg_roles where rolname = $1`, roleWithSpecialCharacters) - require.NoError(t, err) - - if commandTag.RowsAffected() == 0 { - t.Skipf("Role with special characters does not exist.") + if commandTag.RowsAffected() == 0 { + t.Skipf("Role with special characters does not exist.") + } } - testutil.RunTranscodeTestsFormat(t, "aclitem", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, nil, "aclitem", []pgxtest.ValueRoundTripTest{ { pgtype.Text{String: `postgres=arwdDxt/" tricky, ' } "" \ test user "`, Valid: true}, new(pgtype.Text), isExpectedEq(pgtype.Text{String: `postgres=arwdDxt/" tricky, ' } "" \ test user "`, Valid: true}), }, - }, conn, "Text", pgtype.TextFormatCode) + }) } func TestTextMarshalJSON(t *testing.T) { diff --git a/pgtype/tid_test.go b/pgtype/tid_test.go index 08636aa8..3e7a1a50 100644 --- a/pgtype/tid_test.go +++ b/pgtype/tid_test.go @@ -1,16 +1,17 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestTIDCodec(t *testing.T) { skipCockroachDB(t, "Server does not support type tid") - testutil.RunTranscodeTests(t, "tid", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "tid", []pgxtest.ValueRoundTripTest{ { pgtype.TID{BlockNumber: 42, OffsetNumber: 43, Valid: true}, new(pgtype.TID), diff --git a/pgtype/time_test.go b/pgtype/time_test.go index 61f9ef0e..01bcee0f 100644 --- a/pgtype/time_test.go +++ b/pgtype/time_test.go @@ -1,15 +1,16 @@ package pgtype_test import ( + "context" "testing" "time" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestTimeCodec(t *testing.T) { - testutil.RunTranscodeTests(t, "time", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "time", []pgxtest.ValueRoundTripTest{ { pgtype.Time{Microseconds: 0, Valid: true}, new(pgtype.Time), diff --git a/pgtype/timestamp.go b/pgtype/timestamp.go index 3a0bd275..10525229 100644 --- a/pgtype/timestamp.go +++ b/pgtype/timestamp.go @@ -4,6 +4,7 @@ import ( "database/sql/driver" "encoding/binary" "fmt" + "strings" "time" "github.com/jackc/pgx/v5/internal/pgio" @@ -127,12 +128,29 @@ func (encodePlanTimestampCodecText) Encode(value interface{}, buf []byte) (newBu return nil, err } + if !ts.Valid { + return nil, nil + } + var s string switch ts.InfinityModifier { case Finite: t := discardTimeZone(ts.Time) + + // Year 0000 is 1 BC + bc := false + if year := t.Year(); year <= 0 { + year = -year + 1 + t = time.Date(year, t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), time.UTC) + bc = true + } + s = t.Truncate(time.Microsecond).Format(pgTimestampFormat) + + if bc { + s = s + " BC" + } case Infinity: s = "infinity" case NegativeInfinity: @@ -219,11 +237,21 @@ func (scanPlanTextTimestampToTimestampScanner) Scan(src []byte, dst interface{}) case "-infinity": ts = Timestamp{Valid: true, InfinityModifier: -Infinity} default: + bc := false + if strings.HasSuffix(sbuf, " BC") { + sbuf = sbuf[:len(sbuf)-3] + bc = true + } tim, err := time.Parse(pgTimestampFormat, sbuf) if err != nil { return err } + if bc { + year := -tim.Year() + 1 + tim = time.Date(year, tim.Month(), tim.Day(), tim.Hour(), tim.Minute(), tim.Second(), tim.Nanosecond(), tim.Location()) + } + ts = Timestamp{Time: tim, Valid: true} } diff --git a/pgtype/timestamp_test.go b/pgtype/timestamp_test.go index 764baff1..849f55f6 100644 --- a/pgtype/timestamp_test.go +++ b/pgtype/timestamp_test.go @@ -5,15 +5,21 @@ import ( "testing" "time" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/require" ) func TestTimestampCodec(t *testing.T) { skipCockroachDB(t, "Server does not support infinite timestamps (see https://github.com/cockroachdb/cockroach/issues/41564)") - testutil.RunTranscodeTests(t, "timestamp", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "timestamp", []pgxtest.ValueRoundTripTest{ + {time.Date(-100, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(-100, 1, 1, 0, 0, 0, 0, time.UTC))}, + {time.Date(-1, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(-1, 1, 1, 0, 0, 0, 0, time.UTC))}, + {time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC))}, + {time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC))}, + {time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC))}, {time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC))}, {time.Date(1999, 12, 31, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(1999, 12, 31, 0, 0, 0, 0, time.UTC))}, @@ -34,19 +40,18 @@ func TestTimestampCodec(t *testing.T) { // https://github.com/jackc/pgx/v4/pgtype/pull/128 func TestTimestampTranscodeBigTimeBinary(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + in := &pgtype.Timestamp{Time: time.Date(294276, 12, 31, 23, 59, 59, 999999000, time.UTC), Valid: true} + var out pgtype.Timestamp - in := &pgtype.Timestamp{Time: time.Date(294276, 12, 31, 23, 59, 59, 999999000, time.UTC), Valid: true} - var out pgtype.Timestamp + err := conn.QueryRow(ctx, "select $1::timestamp", in).Scan(&out) + if err != nil { + t.Fatal(err) + } - err := conn.QueryRow(context.Background(), "select $1::timestamp", in).Scan(&out) - if err != nil { - t.Fatal(err) - } - - require.Equal(t, in.Valid, out.Valid) - require.Truef(t, in.Time.Equal(out.Time), "expected %v got %v", in.Time, out.Time) + require.Equal(t, in.Valid, out.Valid) + require.Truef(t, in.Time.Equal(out.Time), "expected %v got %v", in.Time, out.Time) + }) } // https://github.com/jackc/pgtype/issues/74 diff --git a/pgtype/timestamptz.go b/pgtype/timestamptz.go index 5069af02..7709e0aa 100644 --- a/pgtype/timestamptz.go +++ b/pgtype/timestamptz.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "encoding/json" "fmt" + "strings" "time" "github.com/jackc/pgx/v5/internal/pgio" @@ -184,11 +185,30 @@ func (encodePlanTimestamptzCodecText) Encode(value interface{}, buf []byte) (new return nil, err } + if !ts.Valid { + return nil, nil + } + var s string switch ts.InfinityModifier { case Finite: - s = ts.Time.UTC().Truncate(time.Microsecond).Format(pgTimestamptzSecondFormat) + + t := ts.Time.UTC().Truncate(time.Microsecond) + + // Year 0000 is 1 BC + bc := false + if year := t.Year(); year <= 0 { + year = -year + 1 + t = time.Date(year, t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), time.UTC) + bc = true + } + + s = t.Format(pgTimestamptzSecondFormat) + + if bc { + s = s + " BC" + } case Infinity: s = "infinity" case NegativeInfinity: @@ -267,6 +287,12 @@ func (scanPlanTextTimestamptzToTimestamptzScanner) Scan(src []byte, dst interfac case "-infinity": tstz = Timestamptz{Valid: true, InfinityModifier: -Infinity} default: + bc := false + if strings.HasSuffix(sbuf, " BC") { + sbuf = sbuf[:len(sbuf)-3] + bc = true + } + var format string if len(sbuf) >= 9 && (sbuf[len(sbuf)-9] == '-' || sbuf[len(sbuf)-9] == '+') { format = pgTimestamptzSecondFormat @@ -281,6 +307,11 @@ func (scanPlanTextTimestamptzToTimestamptzScanner) Scan(src []byte, dst interfac return err } + if bc { + year := -tim.Year() + 1 + tim = time.Date(year, tim.Month(), tim.Day(), tim.Hour(), tim.Minute(), tim.Second(), tim.Nanosecond(), tim.Location()) + } + tstz = Timestamptz{Time: tim, Valid: true} } diff --git a/pgtype/timestamptz_test.go b/pgtype/timestamptz_test.go index 678f3013..0486ecdb 100644 --- a/pgtype/timestamptz_test.go +++ b/pgtype/timestamptz_test.go @@ -5,15 +5,21 @@ import ( "testing" "time" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/require" ) func TestTimestamptzCodec(t *testing.T) { skipCockroachDB(t, "Server does not support infinite timestamps (see https://github.com/cockroachdb/cockroach/issues/41564)") - testutil.RunTranscodeTests(t, "timestamptz", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "timestamptz", []pgxtest.ValueRoundTripTest{ + {time.Date(-100, 1, 1, 0, 0, 0, 0, time.Local), new(time.Time), isExpectedEqTime(time.Date(-100, 1, 1, 0, 0, 0, 0, time.Local))}, + {time.Date(-1, 1, 1, 0, 0, 0, 0, time.Local), new(time.Time), isExpectedEqTime(time.Date(-1, 1, 1, 0, 0, 0, 0, time.Local))}, + {time.Date(0, 1, 1, 0, 0, 0, 0, time.Local), new(time.Time), isExpectedEqTime(time.Date(0, 1, 1, 0, 0, 0, 0, time.Local))}, + {time.Date(1, 1, 1, 0, 0, 0, 0, time.Local), new(time.Time), isExpectedEqTime(time.Date(1, 1, 1, 0, 0, 0, 0, time.Local))}, + {time.Date(1900, 1, 1, 0, 0, 0, 0, time.Local), new(time.Time), isExpectedEqTime(time.Date(1900, 1, 1, 0, 0, 0, 0, time.Local))}, {time.Date(1970, 1, 1, 0, 0, 0, 0, time.Local), new(time.Time), isExpectedEqTime(time.Date(1970, 1, 1, 0, 0, 0, 0, time.Local))}, {time.Date(1999, 12, 31, 0, 0, 0, 0, time.Local), new(time.Time), isExpectedEqTime(time.Date(1999, 12, 31, 0, 0, 0, 0, time.Local))}, @@ -34,19 +40,18 @@ func TestTimestamptzCodec(t *testing.T) { // https://github.com/jackc/pgx/v4/pgtype/pull/128 func TestTimestamptzTranscodeBigTimeBinary(t *testing.T) { - conn := testutil.MustConnectPgx(t) - defer testutil.MustCloseContext(t, conn) + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + in := &pgtype.Timestamptz{Time: time.Date(294276, 12, 31, 23, 59, 59, 999999000, time.UTC), Valid: true} + var out pgtype.Timestamptz - in := &pgtype.Timestamptz{Time: time.Date(294276, 12, 31, 23, 59, 59, 999999000, time.UTC), Valid: true} - var out pgtype.Timestamptz + err := conn.QueryRow(ctx, "select $1::timestamptz", in).Scan(&out) + if err != nil { + t.Fatal(err) + } - err := conn.QueryRow(context.Background(), "select $1::timestamptz", in).Scan(&out) - if err != nil { - t.Fatal(err) - } - - require.Equal(t, in.Valid, out.Valid) - require.Truef(t, in.Time.Equal(out.Time), "expected %v got %v", in.Time, out.Time) + require.Equal(t, in.Valid, out.Valid) + require.Truef(t, in.Time.Equal(out.Time), "expected %v got %v", in.Time, out.Time) + }) } // https://github.com/jackc/pgtype/issues/74 diff --git a/pgtype/uint32_test.go b/pgtype/uint32_test.go index d6699a03..842de643 100644 --- a/pgtype/uint32_test.go +++ b/pgtype/uint32_test.go @@ -1,14 +1,15 @@ package pgtype_test import ( + "context" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" ) func TestUint32Codec(t *testing.T) { - testutil.RunTranscodeTests(t, "oid", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, "oid", []pgxtest.ValueRoundTripTest{ { pgtype.Uint32{Uint32: pgtype.TextOID, Valid: true}, new(pgtype.Uint32), diff --git a/pgtype/uuid_test.go b/pgtype/uuid_test.go index 870e7ae1..06ff38c2 100644 --- a/pgtype/uuid_test.go +++ b/pgtype/uuid_test.go @@ -1,31 +1,22 @@ package pgtype_test import ( + "context" "reflect" "testing" "github.com/jackc/pgx/v5/pgtype" - "github.com/jackc/pgx/v5/pgtype/testutil" + "github.com/jackc/pgx/v5/pgxtest" "github.com/stretchr/testify/require" ) func TestUUIDCodec(t *testing.T) { - testutil.RunTranscodeTests(t, "uuid", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "uuid", []pgxtest.ValueRoundTripTest{ { pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}, new(pgtype.UUID), isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}), }, - { - [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - new(pgtype.UUID), - isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}), - }, - { - []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - new(pgtype.UUID), - isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}), - }, { "00010203-0405-0607-0809-0a0b0c0d0e0f", new(pgtype.UUID), @@ -40,6 +31,19 @@ func TestUUIDCodec(t *testing.T) { {pgtype.UUID{}, new(pgtype.UUID), isExpectedEq(pgtype.UUID{})}, {nil, new(pgtype.UUID), isExpectedEq(pgtype.UUID{})}, }) + + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, "uuid", []pgxtest.ValueRoundTripTest{ + { + [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + new(pgtype.UUID), + isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}), + }, + { + []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + new(pgtype.UUID), + isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}), + }, + }) } func TestUUID_MarshalJSON(t *testing.T) { diff --git a/pgtype/zeronull/float8_test.go b/pgtype/zeronull/float8_test.go index fd683657..a8c1b6a1 100644 --- a/pgtype/zeronull/float8_test.go +++ b/pgtype/zeronull/float8_test.go @@ -1,10 +1,11 @@ package zeronull_test import ( + "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/jackc/pgx/v5/pgtype/zeronull" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEq(a interface{}) func(interface{}) bool { @@ -14,7 +15,7 @@ func isExpectedEq(a interface{}) func(interface{}) bool { } func TestFloat8Transcode(t *testing.T) { - testutil.RunTranscodeTests(t, "float8", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "float8", []pgxtest.ValueRoundTripTest{ { (zeronull.Float8)(1), new(zeronull.Float8), diff --git a/pgtype/zeronull/int_test.go b/pgtype/zeronull/int_test.go index d687a733..30e4808f 100644 --- a/pgtype/zeronull/int_test.go +++ b/pgtype/zeronull/int_test.go @@ -2,14 +2,15 @@ package zeronull_test import ( + "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/jackc/pgx/v5/pgtype/zeronull" + "github.com/jackc/pgx/v5/pgxtest" ) func TestInt2Transcode(t *testing.T) { - testutil.RunTranscodeTests(t, "int2", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int2", []pgxtest.ValueRoundTripTest{ { (zeronull.Int2)(1), new(zeronull.Int2), @@ -29,7 +30,7 @@ func TestInt2Transcode(t *testing.T) { } func TestInt4Transcode(t *testing.T) { - testutil.RunTranscodeTests(t, "int4", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int4", []pgxtest.ValueRoundTripTest{ { (zeronull.Int4)(1), new(zeronull.Int4), @@ -49,7 +50,7 @@ func TestInt4Transcode(t *testing.T) { } func TestInt8Transcode(t *testing.T) { - testutil.RunTranscodeTests(t, "int8", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int8", []pgxtest.ValueRoundTripTest{ { (zeronull.Int8)(1), new(zeronull.Int8), diff --git a/pgtype/zeronull/int_test.go.erb b/pgtype/zeronull/int_test.go.erb index b33cfa4a..2c7ddc46 100644 --- a/pgtype/zeronull/int_test.go.erb +++ b/pgtype/zeronull/int_test.go.erb @@ -10,7 +10,7 @@ import ( <% [2, 4, 8].each do |pg_byte_size| %> <% pg_bit_size = pg_byte_size * 8 %> func TestInt<%= pg_byte_size %>Transcode(t *testing.T) { - testutil.RunTranscodeTests(t, "int<%= pg_byte_size %>", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int<%= pg_byte_size %>", []pgxtest.ValueRoundTripTest{ { (zeronull.Int<%= pg_byte_size %>)(1), new(zeronull.Int<%= pg_byte_size %>), diff --git a/pgtype/zeronull/text_test.go b/pgtype/zeronull/text_test.go index e20ab868..e0d6ec43 100644 --- a/pgtype/zeronull/text_test.go +++ b/pgtype/zeronull/text_test.go @@ -1,14 +1,15 @@ package zeronull_test import ( + "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/jackc/pgx/v5/pgtype/zeronull" + "github.com/jackc/pgx/v5/pgxtest" ) func TestTextTranscode(t *testing.T) { - testutil.RunTranscodeTests(t, "text", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "text", []pgxtest.ValueRoundTripTest{ { (zeronull.Text)("foo"), new(zeronull.Text), diff --git a/pgtype/zeronull/timestamp_test.go b/pgtype/zeronull/timestamp_test.go index 9d8ee7ae..78393e9b 100644 --- a/pgtype/zeronull/timestamp_test.go +++ b/pgtype/zeronull/timestamp_test.go @@ -1,11 +1,12 @@ package zeronull_test import ( + "context" "testing" "time" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/jackc/pgx/v5/pgtype/zeronull" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqTimestamp(a interface{}) func(interface{}) bool { @@ -18,7 +19,7 @@ func isExpectedEqTimestamp(a interface{}) func(interface{}) bool { } func TestTimestampTranscode(t *testing.T) { - testutil.RunTranscodeTests(t, "timestamp", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "timestamp", []pgxtest.ValueRoundTripTest{ { (zeronull.Timestamp)(time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)), new(zeronull.Timestamp), diff --git a/pgtype/zeronull/timestamptz_test.go b/pgtype/zeronull/timestamptz_test.go index 15ac66da..d8273258 100644 --- a/pgtype/zeronull/timestamptz_test.go +++ b/pgtype/zeronull/timestamptz_test.go @@ -1,11 +1,12 @@ package zeronull_test import ( + "context" "testing" "time" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/jackc/pgx/v5/pgtype/zeronull" + "github.com/jackc/pgx/v5/pgxtest" ) func isExpectedEqTimestamptz(a interface{}) func(interface{}) bool { @@ -18,7 +19,7 @@ func isExpectedEqTimestamptz(a interface{}) func(interface{}) bool { } func TestTimestamptzTranscode(t *testing.T) { - testutil.RunTranscodeTests(t, "timestamptz", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "timestamptz", []pgxtest.ValueRoundTripTest{ { (zeronull.Timestamptz)(time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)), new(zeronull.Timestamptz), diff --git a/pgtype/zeronull/uuid_test.go b/pgtype/zeronull/uuid_test.go index 5be1d22e..0cb169fa 100644 --- a/pgtype/zeronull/uuid_test.go +++ b/pgtype/zeronull/uuid_test.go @@ -1,14 +1,15 @@ package zeronull_test import ( + "context" "testing" - "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/jackc/pgx/v5/pgtype/zeronull" + "github.com/jackc/pgx/v5/pgxtest" ) func TestUUIDTranscode(t *testing.T) { - testutil.RunTranscodeTests(t, "uuid", []testutil.TranscodeTestCase{ + pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "uuid", []pgxtest.ValueRoundTripTest{ { (zeronull.UUID)([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}), new(zeronull.UUID), diff --git a/pgtype/zeronull/zeronull.go b/pgtype/zeronull/zeronull.go new file mode 100644 index 00000000..bba7b423 --- /dev/null +++ b/pgtype/zeronull/zeronull.go @@ -0,0 +1,17 @@ +package zeronull + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +// Register registers the zeronull types so they can be used in query exec modes that do not know the server OIDs. +func Register(m *pgtype.Map) { + m.RegisterDefaultPgType(Float8(0), "float8") + m.RegisterDefaultPgType(Int2(0), "int2") + m.RegisterDefaultPgType(Int4(0), "int4") + m.RegisterDefaultPgType(Int8(0), "int8") + m.RegisterDefaultPgType(Text(""), "text") + m.RegisterDefaultPgType(Timestamp{}, "timestamp") + m.RegisterDefaultPgType(Timestamptz{}, "timestamptz") + m.RegisterDefaultPgType(UUID{}, "uuid") +} diff --git a/pgtype/zeronull/zeronull_test.go b/pgtype/zeronull/zeronull_test.go new file mode 100644 index 00000000..9ee45cb7 --- /dev/null +++ b/pgtype/zeronull/zeronull_test.go @@ -0,0 +1,26 @@ +package zeronull_test + +import ( + "context" + "os" + "testing" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgtype/zeronull" + "github.com/jackc/pgx/v5/pgxtest" + "github.com/stretchr/testify/require" +) + +var defaultConnTestRunner pgxtest.ConnTestRunner + +func init() { + defaultConnTestRunner = pgxtest.DefaultConnTestRunner() + defaultConnTestRunner.CreateConfig = func(ctx context.Context, t testing.TB) *pgx.ConnConfig { + config, err := pgx.ParseConfig(os.Getenv("PGX_TEST_DATABASE")) + require.NoError(t, err) + return config + } + defaultConnTestRunner.AfterConnect = func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + zeronull.Register(conn.TypeMap()) + } +} diff --git a/pgxtest/pgxtest.go b/pgxtest/pgxtest.go index dec6a520..3a416dc2 100644 --- a/pgxtest/pgxtest.go +++ b/pgxtest/pgxtest.go @@ -3,11 +3,28 @@ package pgxtest import ( "context" + "fmt" + "reflect" "testing" "github.com/jackc/pgx/v5" ) +var AllQueryExecModes = []pgx.QueryExecMode{ + pgx.QueryExecModeCacheStatement, + pgx.QueryExecModeCacheDescribe, + pgx.QueryExecModeDescribeExec, + pgx.QueryExecModeExec, + pgx.QueryExecModeSimpleProtocol, +} + +// KnownOIDQueryExecModes is a slice of all query exec modes where the param and result OIDs are known before sending the query. +var KnownOIDQueryExecModes = []pgx.QueryExecMode{ + pgx.QueryExecModeCacheStatement, + pgx.QueryExecModeCacheDescribe, + pgx.QueryExecModeDescribeExec, +} + // ConnTestRunner controls how a *pgx.Conn is created and closed by tests. All fields are required. Use DefaultConnTestRunner to get a // ConnTestRunner with reasonable default values. type ConnTestRunner struct { @@ -46,6 +63,8 @@ func DefaultConnTestRunner() ConnTestRunner { } func (ctr *ConnTestRunner) RunTest(ctx context.Context, t testing.TB, f func(ctx context.Context, t testing.TB, conn *pgx.Conn)) { + t.Helper() + config := ctr.CreateConfig(ctx, t) conn, err := pgx.ConnectConfig(ctx, config) if err != nil { @@ -62,13 +81,7 @@ func (ctr *ConnTestRunner) RunTest(ctx context.Context, t testing.TB, f func(ctx // If modes is nil all pgx.QueryExecModes are tested. func RunWithQueryExecModes(ctx context.Context, t *testing.T, ctr ConnTestRunner, modes []pgx.QueryExecMode, f func(ctx context.Context, t testing.TB, conn *pgx.Conn)) { if modes == nil { - modes = []pgx.QueryExecMode{ - pgx.QueryExecModeCacheStatement, - pgx.QueryExecModeCacheDescribe, - pgx.QueryExecModeDescribeExec, - pgx.QueryExecModeExec, - pgx.QueryExecModeSimpleProtocol, - } + modes = AllQueryExecModes } for _, mode := range modes { @@ -87,6 +100,51 @@ func RunWithQueryExecModes(ctx context.Context, t *testing.T, ctr ConnTestRunner } } +type ValueRoundTripTest struct { + Param interface{} + Result interface{} + Test func(interface{}) bool +} + +func RunValueRoundTripTests( + ctx context.Context, + t testing.TB, + ctr ConnTestRunner, + modes []pgx.QueryExecMode, + pgTypeName string, + tests []ValueRoundTripTest, +) { + t.Helper() + + if modes == nil { + modes = AllQueryExecModes + } + + ctr.RunTest(ctx, t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + t.Helper() + + sql := fmt.Sprintf("select $1::%s", pgTypeName) + + for i, tt := range tests { + for _, mode := range modes { + err := conn.QueryRow(ctx, sql, mode, tt.Param).Scan(tt.Result) + if err != nil { + t.Errorf("%d. %v: %v", i, mode, err) + } + + result := reflect.ValueOf(tt.Result) + if result.Kind() == reflect.Ptr { + result = result.Elem() + } + + if !tt.Test(result.Interface()) { + t.Errorf("%d. %v: unexpected result for %v: %v", i, mode, tt.Param, result.Interface()) + } + } + } + }) +} + // SkipCockroachDB calls Skip on t with msg if the connection is to a CockroachDB server. func SkipCockroachDB(t testing.TB, conn *pgx.Conn, msg string) { if conn.PgConn().ParameterStatus("crdb_version") != "" { diff --git a/values.go b/values.go index 595f2b4d..12e5db47 100644 --- a/values.go +++ b/values.go @@ -17,7 +17,7 @@ func convertSimpleArgument(m *pgtype.Map, arg interface{}) (interface{}, error) return nil, nil } - buf, err := m.Encode(0, TextFormatCode, arg, nil) + buf, err := m.Encode(0, TextFormatCode, arg, []byte{}) if err != nil { return nil, err }