mirror of
https://github.com/jackc/pgx.git
synced 2025-05-31 11:42:24 +00:00
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.
This commit is contained in:
parent
83e50f21e8
commit
ee93440ac1
35
conn.go
35
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
|
// 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.
|
// no way to safely use binary or to specify the parameter OIDs.
|
||||||
func (c *Conn) appendParamsForQueryExecModeExec(args []interface{}) error {
|
func (c *Conn) appendParamsForQueryExecModeExec(args []interface{}) error {
|
||||||
for i := range args {
|
for _, arg := range args {
|
||||||
if args[i] == nil {
|
if arg == nil {
|
||||||
err := c.eqb.AppendParamFormat(c.typeMap, 0, TextFormatCode, args[i])
|
err := c.eqb.AppendParamFormat(c.typeMap, 0, TextFormatCode, arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dt, ok := c.TypeMap().TypeForValue(args[i])
|
dt, ok := c.TypeMap().TypeForValue(arg)
|
||||||
if !ok {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4,191 +4,184 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestArrayCodec(t *testing.T) {
|
func TestArrayCodec(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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 {
|
newInt16 := func(n int16) *int16 { return &n }
|
||||||
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 }
|
for i, tt := range []struct {
|
||||||
|
expected interface{}
|
||||||
for i, tt := range []struct {
|
}{
|
||||||
expected interface{}
|
{[]*int16{newInt16(1), nil, newInt16(3), nil, newInt16(5)}},
|
||||||
}{
|
} {
|
||||||
{[]*int16{newInt16(1), nil, newInt16(3), nil, newInt16(5)}},
|
var actual []*int16
|
||||||
} {
|
err := conn.QueryRow(
|
||||||
var actual []*int16
|
ctx,
|
||||||
err := conn.QueryRow(
|
"select $1::smallint[]",
|
||||||
context.Background(),
|
tt.expected,
|
||||||
"select $1::smallint[]",
|
).Scan(&actual)
|
||||||
tt.expected,
|
assert.NoErrorf(t, err, "%d", i)
|
||||||
).Scan(&actual)
|
assert.Equalf(t, tt.expected, actual, "%d", i)
|
||||||
assert.NoErrorf(t, err, "%d", i)
|
}
|
||||||
assert.Equalf(t, tt.expected, actual, "%d", i)
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayCodecAnySlice(t *testing.T) {
|
func TestArrayCodecAnySlice(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
type _int16Slice []int16
|
||||||
|
|
||||||
type _int16Slice []int16
|
for i, tt := range []struct {
|
||||||
|
expected interface{}
|
||||||
for i, tt := range []struct {
|
}{
|
||||||
expected interface{}
|
{_int16Slice(nil)},
|
||||||
}{
|
{_int16Slice{}},
|
||||||
{_int16Slice(nil)},
|
{_int16Slice{1, 2, 3}},
|
||||||
{_int16Slice{}},
|
} {
|
||||||
{_int16Slice{1, 2, 3}},
|
var actual _int16Slice
|
||||||
} {
|
err := conn.QueryRow(
|
||||||
var actual _int16Slice
|
ctx,
|
||||||
err := conn.QueryRow(
|
"select $1::smallint[]",
|
||||||
context.Background(),
|
tt.expected,
|
||||||
"select $1::smallint[]",
|
).Scan(&actual)
|
||||||
tt.expected,
|
assert.NoErrorf(t, err, "%d", i)
|
||||||
).Scan(&actual)
|
assert.Equalf(t, tt.expected, actual, "%d", i)
|
||||||
assert.NoErrorf(t, err, "%d", i)
|
}
|
||||||
assert.Equalf(t, tt.expected, actual, "%d", i)
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayCodecDecodeValue(t *testing.T) {
|
func TestArrayCodecDecodeValue(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
for _, tt := range []struct {
|
||||||
|
sql string
|
||||||
for _, tt := range []struct {
|
expected interface{}
|
||||||
sql string
|
}{
|
||||||
expected interface{}
|
{
|
||||||
}{
|
sql: `select '{}'::int4[]`,
|
||||||
{
|
expected: []interface{}{},
|
||||||
sql: `select '{}'::int4[]`,
|
},
|
||||||
expected: []interface{}{},
|
{
|
||||||
},
|
sql: `select '{1,2}'::int8[]`,
|
||||||
{
|
expected: []interface{}{int64(1), int64(2)},
|
||||||
sql: `select '{1,2}'::int8[]`,
|
},
|
||||||
expected: []interface{}{int64(1), int64(2)},
|
{
|
||||||
},
|
sql: `select '{foo,bar}'::text[]`,
|
||||||
{
|
expected: []interface{}{"foo", "bar"},
|
||||||
sql: `select '{foo,bar}'::text[]`,
|
},
|
||||||
expected: []interface{}{"foo", "bar"},
|
} {
|
||||||
},
|
t.Run(tt.sql, func(t *testing.T) {
|
||||||
} {
|
rows, err := conn.Query(ctx, tt.sql)
|
||||||
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()
|
|
||||||
require.NoError(t, err)
|
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) {
|
func TestArrayCodecScanMultipleDimensions(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
rows, err := conn.Query(context.Background(), `select '{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}'::int4[]`)
|
rows, err := conn.Query(ctx, `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.NoError(t, err)
|
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) {
|
func TestArrayCodecScanMultipleDimensionsEmpty(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
rows, err := conn.Query(ctx, `select '{}'::int4[]`)
|
||||||
|
|
||||||
rows, err := conn.Query(context.Background(), `select '{}'::int4[]`)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var ss [][]int32
|
|
||||||
err := rows.Scan(&ss)
|
|
||||||
require.NoError(t, err)
|
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) {
|
func TestArrayCodecScanWrongMultipleDimensions(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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[]`)
|
for rows.Next() {
|
||||||
require.NoError(t, err)
|
var ss [][][]int32
|
||||||
|
err := rows.Scan(&ss)
|
||||||
for rows.Next() {
|
require.Error(t, err, "can't scan into dest[0]: PostgreSQL array has 2 dimensions but slice has 3 dimensions")
|
||||||
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) {
|
func TestArrayCodecEncodeMultipleDimensions(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
rows, err := conn.Query(ctx, `select $1::int4[]`, [][]int32{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}})
|
||||||
|
|
||||||
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)
|
|
||||||
require.NoError(t, err)
|
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) {
|
func TestArrayCodecEncodeMultipleDimensionsRagged(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
skipCockroachDB(t, "Server does not support nested arrays (https://github.com/cockroachdb/cockroach/issues/36815)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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")
|
||||||
rows, err := conn.Query(context.Background(), `select $1::int4[]`, [][]int32{{1, 2, 3, 4}, {5}, {9, 10, 11, 12}})
|
defer rows.Close()
|
||||||
require.Error(t, err, "cannot convert [][]int32 to ArrayGetter because it is a ragged multi-dimensional")
|
})
|
||||||
defer rows.Close()
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,11 @@ package pgtype_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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 {
|
func isExpectedEqBits(a interface{}) func(interface{}) bool {
|
||||||
@ -17,7 +18,7 @@ func isExpectedEqBits(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBitsCodecBit(t *testing.T) {
|
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},
|
pgtype.Bits{Bytes: []byte{0, 0, 0, 0, 0}, Len: 40, Valid: true},
|
||||||
new(pgtype.Bits),
|
new(pgtype.Bits),
|
||||||
@ -34,7 +35,7 @@ func TestBitsCodecBit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBitsCodecVarbit(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},
|
pgtype.Bits{Bytes: []byte{}, Len: 0, Valid: true},
|
||||||
new(pgtype.Bits),
|
new(pgtype.Bits),
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBoolCodec(t *testing.T) {
|
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)},
|
{true, new(bool), isExpectedEq(true)},
|
||||||
{false, new(bool), isExpectedEq(false)},
|
{false, new(bool), isExpectedEq(false)},
|
||||||
{true, new(pgtype.Bool), isExpectedEq(pgtype.Bool{Bool: true, Valid: true})},
|
{true, new(pgtype.Bool), isExpectedEq(pgtype.Bool{Bool: true, Valid: true})},
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBoxCodec(t *testing.T) {
|
func TestBoxCodec(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support box type")
|
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{
|
pgtype.Box{
|
||||||
P: [2]pgtype.Vec2{{7.1, 5.2345678}, {3.14, 1.678}},
|
P: [2]pgtype.Vec2{{7.1, 5.2345678}, {3.14, 1.678}},
|
||||||
|
@ -5,8 +5,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ func isExpectedEqBytes(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestByteaCodec(t *testing.T) {
|
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{1, 2, 3}, new([]byte), isExpectedEqBytes([]byte{1, 2, 3})},
|
||||||
{[]byte{}, new([]byte), isExpectedEqBytes([]byte{})},
|
{[]byte{}, new([]byte), isExpectedEqBytes([]byte{})},
|
||||||
{[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))},
|
{[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))},
|
||||||
@ -37,91 +38,79 @@ func TestByteaCodec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDriverBytesQueryRow(t *testing.T) {
|
func TestDriverBytesQueryRow(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
var buf []byte
|
||||||
|
err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.DriverBytes)(&buf))
|
||||||
ctx := context.Background()
|
require.EqualError(t, err, "cannot scan into *pgtype.DriverBytes from QueryRow")
|
||||||
|
})
|
||||||
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) {
|
func TestDriverBytes(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
argBuf := make([]byte, 128)
|
||||||
|
for i := range argBuf {
|
||||||
ctx := context.Background()
|
argBuf[i] = byte(i)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = rows.Scan((*pgtype.DriverBytes)(&resultBuf))
|
rows, err := conn.Query(ctx, `select $1::bytea from generate_series(1, 1000)`, argBuf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
require.Len(t, resultBuf, len(argBuf))
|
rowCount := 0
|
||||||
require.Equal(t, resultBuf, argBuf)
|
resultBuf := argBuf
|
||||||
require.Equalf(t, cap(resultBuf), len(resultBuf), "cap(resultBuf) is larger than len(resultBuf)")
|
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()
|
err = rows.Scan((*pgtype.DriverBytes)(&resultBuf))
|
||||||
require.NoError(t, err)
|
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) {
|
func TestPreallocBytes(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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}
|
require.Equal(t, []byte{1, 2, 7, 8}, origBuf)
|
||||||
buf := origBuf
|
|
||||||
err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.PreallocBytes)(&buf))
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Len(t, buf, 2)
|
err = conn.QueryRow(ctx, `select $1::bytea`, []byte{3, 4, 5, 6, 7}).Scan((*pgtype.PreallocBytes)(&buf))
|
||||||
require.Equal(t, 4, cap(buf))
|
require.NoError(t, err)
|
||||||
require.Equal(t, buf, []byte{1, 2})
|
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)
|
||||||
|
})
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUndecodedBytes(t *testing.T) {
|
func TestUndecodedBytes(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
var buf []byte
|
||||||
|
err := conn.QueryRow(ctx, `select 1::int4`).Scan((*pgtype.UndecodedBytes)(&buf))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx := context.Background()
|
require.Len(t, buf, 4)
|
||||||
|
require.Equal(t, buf, []byte{0, 0, 0, 1})
|
||||||
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})
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCircleTranscode(t *testing.T) {
|
func TestCircleTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support box type")
|
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},
|
pgtype.Circle{P: pgtype.Vec2{1.234, 5.67890123}, R: 3.5, Valid: true},
|
||||||
new(pgtype.Circle),
|
new(pgtype.Circle),
|
||||||
|
@ -7,50 +7,49 @@ import (
|
|||||||
|
|
||||||
pgx "github.com/jackc/pgx/v5"
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCompositeCodecTranscode(t *testing.T) {
|
func TestCompositeCodecTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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 (
|
create type ct_test as (
|
||||||
a text,
|
a text,
|
||||||
b int4
|
b int4
|
||||||
);`)
|
);`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer conn.Exec(context.Background(), "drop type ct_test")
|
defer conn.Exec(ctx, "drop type ct_test")
|
||||||
|
|
||||||
dt, err := conn.LoadType(context.Background(), "ct_test")
|
dt, err := conn.LoadType(ctx, "ct_test")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
conn.TypeMap().RegisterType(dt)
|
conn.TypeMap().RegisterType(dt)
|
||||||
|
|
||||||
formats := []struct {
|
formats := []struct {
|
||||||
name string
|
name string
|
||||||
code int16
|
code int16
|
||||||
}{
|
}{
|
||||||
{name: "TextFormat", code: pgx.TextFormatCode},
|
{name: "TextFormat", code: pgx.TextFormatCode},
|
||||||
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, format := range formats {
|
for _, format := range formats {
|
||||||
var a string
|
var a string
|
||||||
var b int32
|
var b int32
|
||||||
|
|
||||||
err := conn.QueryRow(context.Background(), "select $1::ct_test", pgx.QueryResultFormats{format.code},
|
err := conn.QueryRow(ctx, "select $1::ct_test", pgx.QueryResultFormats{format.code},
|
||||||
pgtype.CompositeFields{"hi", int32(42)},
|
pgtype.CompositeFields{"hi", int32(42)},
|
||||||
).Scan(
|
).Scan(
|
||||||
pgtype.CompositeFields{&a, &b},
|
pgtype.CompositeFields{&a, &b},
|
||||||
)
|
)
|
||||||
require.NoErrorf(t, err, "%v", format.name)
|
require.NoErrorf(t, err, "%v", format.name)
|
||||||
require.EqualValuesf(t, "hi", a, "%v", format.name)
|
require.EqualValuesf(t, "hi", a, "%v", format.name)
|
||||||
require.EqualValuesf(t, 42, b, "%v", format.name)
|
require.EqualValuesf(t, 42, b, "%v", format.name)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type point3d struct {
|
type point3d struct {
|
||||||
@ -94,118 +93,118 @@ func (p *point3d) ScanIndex(i int) interface{} {
|
|||||||
func TestCompositeCodecTranscodeStruct(t *testing.T) {
|
func TestCompositeCodecTranscodeStruct(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
_, err := conn.Exec(context.Background(), `drop type if exists point3d;
|
_, err := conn.Exec(ctx, `drop type if exists point3d;
|
||||||
|
|
||||||
create type point3d as (
|
create type point3d as (
|
||||||
x float8,
|
x float8,
|
||||||
y float8,
|
y float8,
|
||||||
z float8
|
z float8
|
||||||
);`)
|
);`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer conn.Exec(context.Background(), "drop type point3d")
|
defer conn.Exec(ctx, "drop type point3d")
|
||||||
|
|
||||||
dt, err := conn.LoadType(context.Background(), "point3d")
|
dt, err := conn.LoadType(ctx, "point3d")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
conn.TypeMap().RegisterType(dt)
|
conn.TypeMap().RegisterType(dt)
|
||||||
|
|
||||||
formats := []struct {
|
formats := []struct {
|
||||||
name string
|
name string
|
||||||
code int16
|
code int16
|
||||||
}{
|
}{
|
||||||
{name: "TextFormat", code: pgx.TextFormatCode},
|
{name: "TextFormat", code: pgx.TextFormatCode},
|
||||||
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, format := range formats {
|
for _, format := range formats {
|
||||||
input := point3d{X: 1, Y: 2, Z: 3}
|
input := point3d{X: 1, Y: 2, Z: 3}
|
||||||
var output point3d
|
var output point3d
|
||||||
err := conn.QueryRow(context.Background(), "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output)
|
err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output)
|
||||||
require.NoErrorf(t, err, "%v", format.name)
|
require.NoErrorf(t, err, "%v", format.name)
|
||||||
require.Equalf(t, input, output, "%v", format.name)
|
require.Equalf(t, input, output, "%v", format.name)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompositeCodecTranscodeStructWrapper(t *testing.T) {
|
func TestCompositeCodecTranscodeStructWrapper(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
_, err := conn.Exec(context.Background(), `drop type if exists point3d;
|
_, err := conn.Exec(ctx, `drop type if exists point3d;
|
||||||
|
|
||||||
create type point3d as (
|
create type point3d as (
|
||||||
x float8,
|
x float8,
|
||||||
y float8,
|
y float8,
|
||||||
z float8
|
z float8
|
||||||
);`)
|
);`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer conn.Exec(context.Background(), "drop type point3d")
|
defer conn.Exec(ctx, "drop type point3d")
|
||||||
|
|
||||||
dt, err := conn.LoadType(context.Background(), "point3d")
|
dt, err := conn.LoadType(ctx, "point3d")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
conn.TypeMap().RegisterType(dt)
|
conn.TypeMap().RegisterType(dt)
|
||||||
|
|
||||||
formats := []struct {
|
formats := []struct {
|
||||||
name string
|
name string
|
||||||
code int16
|
code int16
|
||||||
}{
|
}{
|
||||||
{name: "TextFormat", code: pgx.TextFormatCode},
|
{name: "TextFormat", code: pgx.TextFormatCode},
|
||||||
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
||||||
}
|
}
|
||||||
|
|
||||||
type anotherPoint struct {
|
type anotherPoint struct {
|
||||||
X, Y, Z float64
|
X, Y, Z float64
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, format := range formats {
|
for _, format := range formats {
|
||||||
input := anotherPoint{X: 1, Y: 2, Z: 3}
|
input := anotherPoint{X: 1, Y: 2, Z: 3}
|
||||||
var output anotherPoint
|
var output anotherPoint
|
||||||
err := conn.QueryRow(context.Background(), "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output)
|
err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output)
|
||||||
require.NoErrorf(t, err, "%v", format.name)
|
require.NoErrorf(t, err, "%v", format.name)
|
||||||
require.Equalf(t, input, output, "%v", format.name)
|
require.Equalf(t, input, output, "%v", format.name)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompositeCodecDecodeValue(t *testing.T) {
|
func TestCompositeCodecDecodeValue(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
_, err := conn.Exec(context.Background(), `drop type if exists point3d;
|
_, err := conn.Exec(ctx, `drop type if exists point3d;
|
||||||
|
|
||||||
create type point3d as (
|
create type point3d as (
|
||||||
x float8,
|
x float8,
|
||||||
y float8,
|
y float8,
|
||||||
z float8
|
z float8
|
||||||
);`)
|
);`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer conn.Exec(context.Background(), "drop type point3d")
|
defer conn.Exec(ctx, "drop type point3d")
|
||||||
|
|
||||||
dt, err := conn.LoadType(context.Background(), "point3d")
|
dt, err := conn.LoadType(ctx, "point3d")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
conn.TypeMap().RegisterType(dt)
|
conn.TypeMap().RegisterType(dt)
|
||||||
|
|
||||||
formats := []struct {
|
formats := []struct {
|
||||||
name string
|
name string
|
||||||
code int16
|
code int16
|
||||||
}{
|
}{
|
||||||
{name: "TextFormat", code: pgx.TextFormatCode},
|
{name: "TextFormat", code: pgx.TextFormatCode},
|
||||||
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
{name: "BinaryFormat", code: pgx.BinaryFormatCode},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, format := range formats {
|
for _, format := range formats {
|
||||||
rows, err := conn.Query(context.Background(), "select '(1,2,3)'::point3d", pgx.QueryResultFormats{format.code})
|
rows, err := conn.Query(ctx, "select '(1,2,3)'::point3d", pgx.QueryResultFormats{format.code})
|
||||||
require.NoErrorf(t, err, "%v", format.name)
|
require.NoErrorf(t, err, "%v", format.name)
|
||||||
require.True(t, rows.Next())
|
require.True(t, rows.Next())
|
||||||
values, err := rows.Values()
|
values, err := rows.Values()
|
||||||
require.NoErrorf(t, err, "%v", format.name)
|
require.NoErrorf(t, err, "%v", format.name)
|
||||||
require.Lenf(t, values, 1, "%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.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.False(t, rows.Next())
|
||||||
require.NoErrorf(t, rows.Err(), "%v", format.name)
|
require.NoErrorf(t, rows.Err(), "%v", format.name)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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 {
|
func isExpectedEqTime(a interface{}) func(interface{}) bool {
|
||||||
@ -18,7 +19,7 @@ func isExpectedEqTime(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDateCodec(t *testing.T) {
|
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(-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(-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(0, 1, 1, 0, 0, 0, 0, time.UTC), new(time.Time), isExpectedEqTime(time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC))},
|
||||||
|
@ -4,66 +4,66 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEnumCodec(t *testing.T) {
|
func TestEnumCodec(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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');`)
|
create type enum_test as enum ('foo', 'bar', 'baz');`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer conn.Exec(context.Background(), "drop type enum_test")
|
defer conn.Exec(ctx, "drop type enum_test")
|
||||||
|
|
||||||
dt, err := conn.LoadType(context.Background(), "enum_test")
|
dt, err := conn.LoadType(ctx, "enum_test")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn.TypeMap().RegisterType(dt)
|
conn.TypeMap().RegisterType(dt)
|
||||||
|
|
||||||
var s string
|
var s string
|
||||||
err = conn.QueryRow(context.Background(), `select 'foo'::enum_test`).Scan(&s)
|
err = conn.QueryRow(ctx, `select 'foo'::enum_test`).Scan(&s)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "foo", s)
|
require.Equal(t, "foo", s)
|
||||||
|
|
||||||
err = conn.QueryRow(context.Background(), `select $1::enum_test`, "bar").Scan(&s)
|
err = conn.QueryRow(ctx, `select $1::enum_test`, "bar").Scan(&s)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "bar", s)
|
require.Equal(t, "bar", s)
|
||||||
|
|
||||||
err = conn.QueryRow(context.Background(), `select 'foo'::enum_test`).Scan(&s)
|
err = conn.QueryRow(ctx, `select 'foo'::enum_test`).Scan(&s)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "foo", s)
|
require.Equal(t, "foo", s)
|
||||||
|
|
||||||
err = conn.QueryRow(context.Background(), `select $1::enum_test`, "bar").Scan(&s)
|
err = conn.QueryRow(ctx, `select $1::enum_test`, "bar").Scan(&s)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "bar", s)
|
require.Equal(t, "bar", s)
|
||||||
|
|
||||||
err = conn.QueryRow(context.Background(), `select 'baz'::enum_test`).Scan(&s)
|
err = conn.QueryRow(ctx, `select 'baz'::enum_test`).Scan(&s)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "baz", s)
|
require.Equal(t, "baz", s)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnumCodecValues(t *testing.T) {
|
func TestEnumCodecValues(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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');`)
|
create type enum_test as enum ('foo', 'bar', 'baz');`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer conn.Exec(context.Background(), "drop type enum_test")
|
defer conn.Exec(ctx, "drop type enum_test")
|
||||||
|
|
||||||
dt, err := conn.LoadType(context.Background(), "enum_test")
|
dt, err := conn.LoadType(ctx, "enum_test")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn.TypeMap().RegisterType(dt)
|
conn.TypeMap().RegisterType(dt)
|
||||||
|
|
||||||
rows, err := conn.Query(context.Background(), `select 'foo'::enum_test`)
|
rows, err := conn.Query(ctx, `select 'foo'::enum_test`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, rows.Next())
|
require.True(t, rows.Next())
|
||||||
values, err := rows.Values()
|
values, err := rows.Values()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, values, []interface{}{"foo"})
|
require.Equal(t, values, []interface{}{"foo"})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFloat4Codec(t *testing.T) {
|
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: -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: 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})},
|
{pgtype.Float4{Float32: 1, Valid: true}, new(pgtype.Float4), isExpectedEq(pgtype.Float4{Float32: 1, Valid: true})},
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFloat8Codec(t *testing.T) {
|
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: -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: 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})},
|
{pgtype.Float8{Float64: 1, Valid: true}, new(pgtype.Float8), isExpectedEq(pgtype.Float8{Float64: 1, Valid: true})},
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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 {
|
func isExpectedEqMapStringString(a interface{}) func(interface{}) bool {
|
||||||
@ -52,30 +52,22 @@ func isExpectedEqMapStringPointerString(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHstoreCodec(t *testing.T) {
|
func TestHstoreCodec(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
ctr := defaultConnTestRunner
|
||||||
defer testutil.MustCloseContext(t, conn)
|
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
|
conn.TypeMap().RegisterType(&pgtype.Type{Name: "hstore", OID: hstoreOID, Codec: pgtype.HstoreCodec{}})
|
||||||
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},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fs := func(s string) *string {
|
fs := func(s string) *string {
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []testutil.TranscodeTestCase{
|
tests := []pgxtest.ValueRoundTripTest{
|
||||||
{
|
{
|
||||||
map[string]string{},
|
map[string]string{},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
@ -134,25 +126,25 @@ func TestHstoreCodec(t *testing.T) {
|
|||||||
// Special key values
|
// Special key values
|
||||||
|
|
||||||
// at beginning
|
// at beginning
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{s + "foo": "bar"},
|
map[string]string{s + "foo": "bar"},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{s + "foo": "bar"}),
|
isExpectedEqMapStringString(map[string]string{s + "foo": "bar"}),
|
||||||
})
|
})
|
||||||
// in middle
|
// in middle
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{"foo" + s + "bar": "bar"},
|
map[string]string{"foo" + s + "bar": "bar"},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{"foo" + s + "bar": "bar"}),
|
isExpectedEqMapStringString(map[string]string{"foo" + s + "bar": "bar"}),
|
||||||
})
|
})
|
||||||
// at end
|
// at end
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{"foo" + s: "bar"},
|
map[string]string{"foo" + s: "bar"},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{"foo" + s: "bar"}),
|
isExpectedEqMapStringString(map[string]string{"foo" + s: "bar"}),
|
||||||
})
|
})
|
||||||
// is key
|
// is key
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{s: "bar"},
|
map[string]string{s: "bar"},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{s: "bar"}),
|
isExpectedEqMapStringString(map[string]string{s: "bar"}),
|
||||||
@ -161,32 +153,30 @@ func TestHstoreCodec(t *testing.T) {
|
|||||||
// Special value values
|
// Special value values
|
||||||
|
|
||||||
// at beginning
|
// at beginning
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{"foo": s + "bar"},
|
map[string]string{"foo": s + "bar"},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{"foo": s + "bar"}),
|
isExpectedEqMapStringString(map[string]string{"foo": s + "bar"}),
|
||||||
})
|
})
|
||||||
// in middle
|
// in middle
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{"foo": "foo" + s + "bar"},
|
map[string]string{"foo": "foo" + s + "bar"},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{"foo": "foo" + s + "bar"}),
|
isExpectedEqMapStringString(map[string]string{"foo": "foo" + s + "bar"}),
|
||||||
})
|
})
|
||||||
// at end
|
// at end
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{"foo": "foo" + s},
|
map[string]string{"foo": "foo" + s},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{"foo": "foo" + s}),
|
isExpectedEqMapStringString(map[string]string{"foo": "foo" + s}),
|
||||||
})
|
})
|
||||||
// is key
|
// is key
|
||||||
tests = append(tests, testutil.TranscodeTestCase{
|
tests = append(tests, pgxtest.ValueRoundTripTest{
|
||||||
map[string]string{"foo": s},
|
map[string]string{"foo": s},
|
||||||
new(map[string]string),
|
new(map[string]string),
|
||||||
isExpectedEqMapStringString(map[string]string{"foo": s}),
|
isExpectedEqMapStringString(map[string]string{"foo": s}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, format := range formats {
|
pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, pgxtest.KnownOIDQueryExecModes, "hstore", tests)
|
||||||
testutil.RunTranscodeTestsFormat(t, "hstore", tests, conn, format.name, format.code)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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 {
|
func isExpectedEqIPNet(a interface{}) func(interface{}) bool {
|
||||||
@ -18,7 +19,7 @@ func isExpectedEqIPNet(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInetTranscode(t *testing.T) {
|
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, "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, "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"))},
|
{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) {
|
func TestCidrTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support cidr type (see https://github.com/cockroachdb/cockroach/issues/18846)")
|
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, "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, "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"))},
|
{mustParseInet(t, "12.34.56.0/32"), new(net.IPNet), isExpectedEqIPNet(mustParseInet(t, "12.34.56.0/32"))},
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInt2Codec(t *testing.T) {
|
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))},
|
{int8(1), new(int16), isExpectedEq(int16(1))},
|
||||||
{int16(1), new(int16), isExpectedEq(int16(1))},
|
{int16(1), new(int16), isExpectedEq(int16(1))},
|
||||||
{int32(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) {
|
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))},
|
{int8(1), new(int32), isExpectedEq(int32(1))},
|
||||||
{int16(1), new(int32), isExpectedEq(int32(1))},
|
{int16(1), new(int32), isExpectedEq(int32(1))},
|
||||||
{int32(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) {
|
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))},
|
{int8(1), new(int64), isExpectedEq(int64(1))},
|
||||||
{int16(1), new(int64), isExpectedEq(int64(1))},
|
{int16(1), new(int64), isExpectedEq(int64(1))},
|
||||||
{int32(1), new(int64), isExpectedEq(int64(1))},
|
{int32(1), new(int64), isExpectedEq(int64(1))},
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
<% [2, 4, 8].each do |pg_byte_size| %>
|
<% [2, 4, 8].each do |pg_byte_size| %>
|
||||||
<% pg_bit_size = pg_byte_size * 8 %>
|
<% pg_bit_size = pg_byte_size * 8 %>
|
||||||
func TestInt<%= pg_byte_size %>Codec(t *testing.T) {
|
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))},
|
{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))},
|
{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))},
|
{int32(1), new(int<%= pg_bit_size %>), isExpectedEq(int<%= pg_bit_size %>(1))},
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -18,23 +18,22 @@ import (
|
|||||||
<% rows_columns.each do |rows, columns| %>
|
<% rows_columns.each do |rows, columns| %>
|
||||||
<% [["Text", "pgx.TextFormatCode"], ["Binary", "pgx.BinaryFormatCode"]].each do |format_name, format_code| %>
|
<% [["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) {
|
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)
|
defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(b, conn)
|
b.ResetTimer()
|
||||||
|
var v [<%= columns %>]<%= go_type %>
|
||||||
b.ResetTimer()
|
for i := 0; i < b.N; i++ {
|
||||||
var v [<%= columns %>]<%= go_type %>
|
_, err := conn.QueryFunc(
|
||||||
for i := 0; i < b.N; i++ {
|
ctx,
|
||||||
_, err := conn.QueryFunc(
|
`select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`,
|
||||||
context.Background(),
|
[]interface{}{pgx.QueryResultFormats{<%= format_code %>}},
|
||||||
`select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`,
|
[]interface{}{<% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>&v[<%= col_idx%>]<% end %>},
|
||||||
[]interface{}{pgx.QueryResultFormats{<%= format_code %>}},
|
func(pgx.QueryFuncRow) error { return nil },
|
||||||
[]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)
|
||||||
if err != nil {
|
}
|
||||||
b.Fatal(err)
|
}
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -44,23 +43,22 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_<%= pg_type %>_to_Go_<%= go
|
|||||||
<% [10, 100, 1000].each do |array_size| %>
|
<% [10, 100, 1000].each do |array_size| %>
|
||||||
<% [["Text", "pgx.TextFormatCode"], ["Binary", "pgx.BinaryFormatCode"]].each do |format_name, format_code| %>
|
<% [["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) {
|
func BenchmarkQuery<%= format_name %>FormatDecode_PG_Int4Array_With_Go_Int4Array_<%= array_size %>(b *testing.B) {
|
||||||
conn := testutil.MustConnectPgx(b)
|
defaultConnTestRunner.RunTest(context.Background(), b, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(b, conn)
|
b.ResetTimer()
|
||||||
|
var v []int32
|
||||||
b.ResetTimer()
|
for i := 0; i < b.N; i++ {
|
||||||
var v []int32
|
_, err := conn.QueryFunc(
|
||||||
for i := 0; i < b.N; i++ {
|
ctx,
|
||||||
_, err := conn.QueryFunc(
|
`select array_agg(n) from generate_series(1, <%= array_size %>) n`,
|
||||||
context.Background(),
|
[]interface{}{pgx.QueryResultFormats{<%= format_code %>}},
|
||||||
`select array_agg(n) from generate_series(1, <%= array_size %>) n`,
|
[]interface{}{&v},
|
||||||
[]interface{}{pgx.QueryResultFormats{<%= format_code %>}},
|
func(pgx.QueryFuncRow) error { return nil },
|
||||||
[]interface{}{&v},
|
)
|
||||||
func(pgx.QueryFuncRow) error { return nil },
|
if err != nil {
|
||||||
)
|
b.Fatal(err)
|
||||||
if err != nil {
|
}
|
||||||
b.Fatal(err)
|
}
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIntervalCodec(t *testing.T) {
|
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},
|
pgtype.Interval{Microseconds: 1, Valid: true},
|
||||||
new(pgtype.Interval),
|
new(pgtype.Interval),
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isExpectedEqMap(a interface{}) func(interface{}) bool {
|
func isExpectedEqMap(a interface{}) func(interface{}) bool {
|
||||||
@ -39,7 +40,15 @@ func TestJSONCodec(t *testing.T) {
|
|||||||
Age int `json:"age"`
|
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("{}"), new([]byte), isExpectedEqBytes([]byte("{}"))},
|
||||||
{[]byte("null"), new([]byte), isExpectedEqBytes([]byte("null"))},
|
{[]byte("null"), new([]byte), isExpectedEqBytes([]byte("null"))},
|
||||||
{[]byte("42"), new([]byte), isExpectedEqBytes([]byte("42"))},
|
{[]byte("42"), new([]byte), isExpectedEqBytes([]byte("42"))},
|
||||||
@ -47,10 +56,5 @@ func TestJSONCodec(t *testing.T) {
|
|||||||
{[]byte(`"hello"`), new(string), isExpectedEq(`"hello"`)},
|
{[]byte(`"hello"`), new(string), isExpectedEq(`"hello"`)},
|
||||||
{map[string]interface{}{"foo": "bar"}, new(map[string]interface{}), isExpectedEqMap(map[string]interface{}{"foo": "bar"})},
|
{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})},
|
{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))},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestJSONBTranscode(t *testing.T) {
|
func TestJSONBTranscode(t *testing.T) {
|
||||||
@ -12,7 +13,15 @@ func TestJSONBTranscode(t *testing.T) {
|
|||||||
Age int `json:"age"`
|
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("{}"), new([]byte), isExpectedEqBytes([]byte("{}"))},
|
||||||
{[]byte("null"), new([]byte), isExpectedEqBytes([]byte("null"))},
|
{[]byte("null"), new([]byte), isExpectedEqBytes([]byte("null"))},
|
||||||
{[]byte("42"), new([]byte), isExpectedEqBytes([]byte("42"))},
|
{[]byte("42"), new([]byte), isExpectedEqBytes([]byte("42"))},
|
||||||
@ -20,10 +29,5 @@ func TestJSONBTranscode(t *testing.T) {
|
|||||||
{[]byte(`"hello"`), new(string), isExpectedEq(`"hello"`)},
|
{[]byte(`"hello"`), new(string), isExpectedEq(`"hello"`)},
|
||||||
{map[string]interface{}{"foo": "bar"}, new(map[string]interface{}), isExpectedEqMap(map[string]interface{}{"foo": "bar"})},
|
{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})},
|
{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))},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,30 +4,32 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLineTranscode(t *testing.T) {
|
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)
|
if _, ok := conn.TypeMap().TypeForName("line"); !ok {
|
||||||
defer conn.Close(context.Background())
|
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 :(
|
pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, nil, "line", []pgxtest.ValueRoundTripTest{
|
||||||
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{
|
|
||||||
{
|
{
|
||||||
pgtype.Line{
|
pgtype.Line{
|
||||||
A: 1.23, B: 4.56, C: 7.89012345,
|
A: 1.23, B: 4.56, C: 7.89012345,
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLsegTranscode(t *testing.T) {
|
func TestLsegTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support type lseg")
|
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{
|
pgtype.Lseg{
|
||||||
P: [2]pgtype.Vec2{{3.14, 1.678}, {7.1, 5.2345678901}},
|
P: [2]pgtype.Vec2{{3.14, 1.678}, {7.1, 5.2345678901}},
|
||||||
|
@ -2,10 +2,11 @@ package pgtype_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isExpectedEqHardwareAddr(a interface{}) func(interface{}) bool {
|
func isExpectedEqHardwareAddr(a interface{}) func(interface{}) bool {
|
||||||
@ -28,7 +29,8 @@ func isExpectedEqHardwareAddr(a interface{}) func(interface{}) bool {
|
|||||||
func TestMacaddrCodec(t *testing.T) {
|
func TestMacaddrCodec(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support type macaddr")
|
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"),
|
mustParseMacaddr(t, "01:23:45:67:89:ab"),
|
||||||
new(net.HardwareAddr),
|
new(net.HardwareAddr),
|
||||||
|
@ -9,8 +9,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -77,7 +78,7 @@ func TestNumericCodec(t *testing.T) {
|
|||||||
max.Add(max, big.NewInt(1))
|
max.Add(max, big.NewInt(1))
|
||||||
longestNumeric := pgtype.Numeric{Int: max, Exp: -16383, Valid: true}
|
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, "1"), new(pgtype.Numeric), isExpectedEqNumeric(mustParseNumeric(t, "1"))},
|
||||||
{mustParseNumeric(t, "3.14159"), new(pgtype.Numeric), isExpectedEqNumeric(mustParseNumeric(t, "3.14159"))},
|
{mustParseNumeric(t, "3.14159"), new(pgtype.Numeric), isExpectedEqNumeric(mustParseNumeric(t, "3.14159"))},
|
||||||
{mustParseNumeric(t, "100010001"), new(pgtype.Numeric), isExpectedEqNumeric(mustParseNumeric(t, "100010001"))},
|
{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")
|
skipCockroachDB(t, "server formats numeric text format differently")
|
||||||
skipPostgreSQLVersionLessThan(t, 14)
|
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))},
|
{math.Inf(1), new(float64), isExpectedEq(math.Inf(1))},
|
||||||
{float32(math.Inf(1)), new(float32), isExpectedEq(float32(math.Inf(1)))},
|
{float32(math.Inf(1)), new(float32), isExpectedEq(float32(math.Inf(1)))},
|
||||||
{math.Inf(-1), new(float64), isExpectedEq(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 := &big.Int{}
|
||||||
max.SetString("9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 10)
|
max.SetString("9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 10)
|
||||||
|
|
||||||
tests := make([]testutil.TranscodeTestCase, 0, 2000)
|
tests := make([]pgxtest.ValueRoundTripTest, 0, 2000)
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
for j := -50; j < 50; j++ {
|
for j := -50; j < 50; j++ {
|
||||||
num := (&big.Int{}).Rand(r, max)
|
num := (&big.Int{}).Rand(r, max)
|
||||||
|
|
||||||
n := pgtype.Numeric{Int: num, Exp: int32(j), Valid: true}
|
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 := &big.Int{}
|
||||||
negNum.Neg(num)
|
negNum.Neg(num)
|
||||||
n = pgtype.Numeric{Int: negNum, Exp: int32(j), Valid: true}
|
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) {
|
func TestNumericMarshalJSON(t *testing.T) {
|
||||||
skipCockroachDB(t, "server formats numeric text format differently")
|
skipCockroachDB(t, "server formats numeric text format differently")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
for i, tt := range []struct {
|
for i, tt := range []struct {
|
||||||
decString string
|
decString string
|
||||||
}{
|
}{
|
||||||
{"NaN"},
|
{"NaN"},
|
||||||
{"0"},
|
{"0"},
|
||||||
{"1"},
|
{"1"},
|
||||||
{"-1"},
|
{"-1"},
|
||||||
{"1000000000000000000"},
|
{"1000000000000000000"},
|
||||||
{"1234.56789"},
|
{"1234.56789"},
|
||||||
{"1.56789"},
|
{"1.56789"},
|
||||||
{"0.00000000000056789"},
|
{"0.00000000000056789"},
|
||||||
{"0.00123000"},
|
{"0.00123000"},
|
||||||
{"123e-3"},
|
{"123e-3"},
|
||||||
{"243723409723490243842378942378901237502734019231380123e23790"},
|
{"243723409723490243842378942378901237502734019231380123e23790"},
|
||||||
{"3409823409243892349028349023482934092340892390101e-14021"},
|
{"3409823409243892349028349023482934092340892390101e-14021"},
|
||||||
} {
|
} {
|
||||||
var num pgtype.Numeric
|
var num pgtype.Numeric
|
||||||
var pgJSON string
|
var pgJSON string
|
||||||
err := conn.QueryRow(context.Background(), `select $1::numeric, to_json($1::numeric)`, tt.decString).Scan(&num, &pgJSON)
|
err := conn.QueryRow(ctx, `select $1::numeric, to_json($1::numeric)`, tt.decString).Scan(&num, &pgJSON)
|
||||||
require.NoErrorf(t, err, "%d", i)
|
require.NoErrorf(t, err, "%d", i)
|
||||||
|
|
||||||
goJSON, err := json.Marshal(num)
|
goJSON, err := json.Marshal(num)
|
||||||
require.NoErrorf(t, err, "%d", i)
|
require.NoErrorf(t, err, "%d", i)
|
||||||
|
|
||||||
require.Equal(t, pgJSON, string(goJSON))
|
require.Equal(t, pgJSON, string(goJSON))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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 {
|
func isExpectedEqPath(a interface{}) func(interface{}) bool {
|
||||||
@ -29,7 +30,7 @@ func isExpectedEqPath(a interface{}) func(interface{}) bool {
|
|||||||
func TestPathTranscode(t *testing.T) {
|
func TestPathTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support type path")
|
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{
|
pgtype.Path{
|
||||||
P: []pgtype.Vec2{{3.14, 1.678901234}, {7.1, 5.234}},
|
P: []pgtype.Vec2{{3.14, 1.678901234}, {7.1, 5.234}},
|
||||||
|
@ -374,7 +374,7 @@ func NewMap() *Map {
|
|||||||
registerDefaultPgTypeVariants("daterange", "_daterange", Daterange{})
|
registerDefaultPgTypeVariants("daterange", "_daterange", Daterange{})
|
||||||
registerDefaultPgTypeVariants("float4", "_float4", Float4{})
|
registerDefaultPgTypeVariants("float4", "_float4", Float4{})
|
||||||
registerDefaultPgTypeVariants("float8", "_float8", Float8{})
|
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("inet", "_inet", Inet{})
|
||||||
registerDefaultPgTypeVariants("int2", "_int2", Int2{})
|
registerDefaultPgTypeVariants("int2", "_int2", Int2{})
|
||||||
registerDefaultPgTypeVariants("int4", "_int4", Int4{})
|
registerDefaultPgTypeVariants("int4", "_int4", Int4{})
|
||||||
|
@ -1,21 +1,34 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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/jackc/pgx/v5/stdlib"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"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
|
// Test for renamed types
|
||||||
type _string string
|
type _string string
|
||||||
type _bool bool
|
type _bool bool
|
||||||
@ -70,8 +83,11 @@ func mustParseMacaddr(t testing.TB, s string) net.HardwareAddr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func skipCockroachDB(t testing.TB, msg string) {
|
func skipCockroachDB(t testing.TB, msg string) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
||||||
defer testutil.MustCloseContext(t, conn)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer conn.Close(context.Background())
|
||||||
|
|
||||||
if conn.PgConn().ParameterStatus("crdb_version") != "" {
|
if conn.PgConn().ParameterStatus("crdb_version") != "" {
|
||||||
t.Skip(msg)
|
t.Skip(msg)
|
||||||
@ -79,8 +95,11 @@ func skipCockroachDB(t testing.TB, msg string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func skipPostgreSQLVersionLessThan(t testing.TB, minVersion int64) {
|
func skipPostgreSQLVersionLessThan(t testing.TB, minVersion int64) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
|
||||||
defer testutil.MustCloseContext(t, conn)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer conn.Close(context.Background())
|
||||||
|
|
||||||
serverVersionStr := conn.PgConn().ParameterStatus("server_version")
|
serverVersionStr := conn.PgConn().ParameterStatus("server_version")
|
||||||
serverVersionStr = regexp.MustCompile(`^[0-9]+`).FindString(serverVersionStr)
|
serverVersionStr = regexp.MustCompile(`^[0-9]+`).FindString(serverVersionStr)
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPointCodec(t *testing.T) {
|
func TestPointCodec(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support type point")
|
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},
|
pgtype.Point{P: pgtype.Vec2{1.234, 5.6789012345}, Valid: true},
|
||||||
new(pgtype.Point),
|
new(pgtype.Point),
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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 {
|
func isExpectedEqPolygon(a interface{}) func(interface{}) bool {
|
||||||
@ -29,7 +30,7 @@ func isExpectedEqPolygon(a interface{}) func(interface{}) bool {
|
|||||||
func TestPolygonTranscode(t *testing.T) {
|
func TestPolygonTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support type polygon")
|
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{
|
pgtype.Polygon{
|
||||||
P: []pgtype.Vec2{{3.14, 1.678901234}, {7.1, 5.234}, {5.0, 3.234}},
|
P: []pgtype.Vec2{{3.14, 1.678901234}, {7.1, 5.234}, {5.0, 3.234}},
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestQcharTranscode(t *testing.T) {
|
func TestQcharTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support qchar")
|
skipCockroachDB(t, "Server does not support qchar")
|
||||||
|
|
||||||
var tests []testutil.TranscodeTestCase
|
var tests []pgxtest.ValueRoundTripTest
|
||||||
for i := 0; i <= math.MaxUint8; i++ {
|
for i := 0; i <= math.MaxUint8; i++ {
|
||||||
tests = append(tests, testutil.TranscodeTestCase{rune(i), new(rune), isExpectedEq(rune(i))})
|
tests = append(tests, pgxtest.ValueRoundTripTest{rune(i), new(rune), isExpectedEq(rune(i))})
|
||||||
tests = append(tests, testutil.TranscodeTestCase{byte(i), new(byte), isExpectedEq(byte(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, pgxtest.ValueRoundTripTest{nil, new(*rune), isExpectedEq((*rune)(nil))})
|
||||||
tests = append(tests, testutil.TranscodeTestCase{nil, new(*byte), isExpectedEq((*byte)(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)
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,16 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRangeCodecTranscode(t *testing.T) {
|
func TestRangeCodecTranscode(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)")
|
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},
|
pgtype.Int4range{LowerType: pgtype.Empty, UpperType: pgtype.Empty, Valid: true},
|
||||||
new(pgtype.Int4range),
|
new(pgtype.Int4range),
|
||||||
@ -39,9 +40,12 @@ func TestRangeCodecTranscode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRangeCodecTranscodeCompatibleRangeElementTypes(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},
|
pgtype.Float8range{LowerType: pgtype.Empty, UpperType: pgtype.Empty, Valid: true},
|
||||||
new(pgtype.Float8range),
|
new(pgtype.Float8range),
|
||||||
@ -70,90 +74,90 @@ func TestRangeCodecTranscodeCompatibleRangeElementTypes(t *testing.T) {
|
|||||||
func TestRangeCodecScanRangeTwiceWithUnbounded(t *testing.T) {
|
func TestRangeCodecScanRangeTwiceWithUnbounded(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)")
|
skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
var r pgtype.Int4range
|
var r pgtype.Int4range
|
||||||
|
|
||||||
err := conn.QueryRow(context.Background(), `select '[1,5)'::int4range`).Scan(&r)
|
err := conn.QueryRow(context.Background(), `select '[1,5)'::int4range`).Scan(&r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t,
|
t,
|
||||||
pgtype.Int4range{
|
pgtype.Int4range{
|
||||||
Lower: pgtype.Int4{Int32: 1, Valid: true},
|
Lower: pgtype.Int4{Int32: 1, Valid: true},
|
||||||
Upper: pgtype.Int4{Int32: 5, Valid: true},
|
Upper: pgtype.Int4{Int32: 5, Valid: true},
|
||||||
LowerType: pgtype.Inclusive,
|
LowerType: pgtype.Inclusive,
|
||||||
UpperType: pgtype.Exclusive,
|
UpperType: pgtype.Exclusive,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
},
|
},
|
||||||
r,
|
r,
|
||||||
)
|
)
|
||||||
|
|
||||||
err = conn.QueryRow(context.Background(), `select '[1,)'::int4range`).Scan(&r)
|
err = conn.QueryRow(ctx, `select '[1,)'::int4range`).Scan(&r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t,
|
t,
|
||||||
pgtype.Int4range{
|
pgtype.Int4range{
|
||||||
Lower: pgtype.Int4{Int32: 1, Valid: true},
|
Lower: pgtype.Int4{Int32: 1, Valid: true},
|
||||||
Upper: pgtype.Int4{},
|
Upper: pgtype.Int4{},
|
||||||
LowerType: pgtype.Inclusive,
|
LowerType: pgtype.Inclusive,
|
||||||
UpperType: pgtype.Unbounded,
|
UpperType: pgtype.Unbounded,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
},
|
},
|
||||||
r,
|
r,
|
||||||
)
|
)
|
||||||
|
|
||||||
err = conn.QueryRow(context.Background(), `select 'empty'::int4range`).Scan(&r)
|
err = conn.QueryRow(ctx, `select 'empty'::int4range`).Scan(&r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t,
|
t,
|
||||||
pgtype.Int4range{
|
pgtype.Int4range{
|
||||||
Lower: pgtype.Int4{},
|
Lower: pgtype.Int4{},
|
||||||
Upper: pgtype.Int4{},
|
Upper: pgtype.Int4{},
|
||||||
LowerType: pgtype.Empty,
|
LowerType: pgtype.Empty,
|
||||||
UpperType: pgtype.Empty,
|
UpperType: pgtype.Empty,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
},
|
},
|
||||||
r,
|
r,
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRangeCodecDecodeValue(t *testing.T) {
|
func TestRangeCodecDecodeValue(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)")
|
skipCockroachDB(t, "Server does not support range types (see https://github.com/cockroachdb/cockroach/issues/27791)")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
for _, tt := range []struct {
|
for _, tt := range []struct {
|
||||||
sql string
|
sql string
|
||||||
expected interface{}
|
expected interface{}
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
sql: `select '[1,5)'::int4range`,
|
sql: `select '[1,5)'::int4range`,
|
||||||
expected: pgtype.GenericRange{
|
expected: pgtype.GenericRange{
|
||||||
Lower: int32(1),
|
Lower: int32(1),
|
||||||
Upper: int32(5),
|
Upper: int32(5),
|
||||||
LowerType: pgtype.Inclusive,
|
LowerType: pgtype.Inclusive,
|
||||||
UpperType: pgtype.Exclusive,
|
UpperType: pgtype.Exclusive,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
} {
|
||||||
} {
|
t.Run(tt.sql, func(t *testing.T) {
|
||||||
t.Run(tt.sql, func(t *testing.T) {
|
rows, err := conn.Query(ctx, tt.sql)
|
||||||
rows, err := conn.Query(context.Background(), tt.sql)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
values, err := rows.Values()
|
|
||||||
require.NoError(t, err)
|
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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,72 +4,70 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRecordCodec(t *testing.T) {
|
func TestRecordCodec(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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
|
require.Equal(t, "foo", a)
|
||||||
var b int32
|
require.Equal(t, int32(42), b)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRecordCodecDecodeValue(t *testing.T) {
|
func TestRecordCodecDecodeValue(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server converts row int4 to int8")
|
skipCockroachDB(t, "Server converts row int4 to int8")
|
||||||
|
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, conn)
|
for _, tt := range []struct {
|
||||||
|
sql string
|
||||||
for _, tt := range []struct {
|
expected interface{}
|
||||||
sql string
|
}{
|
||||||
expected interface{}
|
{
|
||||||
}{
|
sql: `select row()`,
|
||||||
{
|
expected: []interface{}{},
|
||||||
sql: `select row()`,
|
},
|
||||||
expected: []interface{}{},
|
{
|
||||||
},
|
sql: `select row('foo'::text, 42::int4)`,
|
||||||
{
|
expected: []interface{}{"foo", int32(42)},
|
||||||
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(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('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 row(null)`,
|
},
|
||||||
expected: []interface{}{nil},
|
{
|
||||||
},
|
sql: `select null::record`,
|
||||||
{
|
expected: nil,
|
||||||
sql: `select null::record`,
|
},
|
||||||
expected: nil,
|
} {
|
||||||
},
|
t.Run(tt.sql, func(t *testing.T) {
|
||||||
} {
|
rows, err := conn.Query(context.Background(), tt.sql)
|
||||||
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()
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, values, 1)
|
defer rows.Close()
|
||||||
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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,8 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ func (someFmtStringer) String() string {
|
|||||||
|
|
||||||
func TestTextCodec(t *testing.T) {
|
func TestTextCodec(t *testing.T) {
|
||||||
for _, pgTypeName := range []string{"text", "varchar"} {
|
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},
|
pgtype.Text{String: "", Valid: true},
|
||||||
new(pgtype.Text),
|
new(pgtype.Text),
|
||||||
@ -31,6 +32,10 @@ func TestTextCodec(t *testing.T) {
|
|||||||
{nil, new(pgtype.Text), isExpectedEq(pgtype.Text{})},
|
{nil, new(pgtype.Text), isExpectedEq(pgtype.Text{})},
|
||||||
{"foo", new(string), isExpectedEq("foo")},
|
{"foo", new(string), isExpectedEq("foo")},
|
||||||
{someFmtStringer{}, new(string), isExpectedEq("some fmt.Stringer")},
|
{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'))},
|
{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.
|
// So this is simply a smoke test of the name type.
|
||||||
func TestTextCodecName(t *testing.T) {
|
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},
|
pgtype.Text{String: "", Valid: true},
|
||||||
new(pgtype.Text),
|
new(pgtype.Text),
|
||||||
@ -67,7 +72,7 @@ func TestTextCodecName(t *testing.T) {
|
|||||||
func TestTextCodecBPChar(t *testing.T) {
|
func TestTextCodecBPChar(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not properly handle bpchar with multi-byte character")
|
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},
|
pgtype.Text{String: "a ", Valid: true},
|
||||||
new(pgtype.Text),
|
new(pgtype.Text),
|
||||||
@ -94,12 +99,12 @@ func TestTextCodecBPChar(t *testing.T) {
|
|||||||
//
|
//
|
||||||
// It only supports the text format.
|
// It only supports the text format.
|
||||||
func TestTextCodecACLItem(t *testing.T) {
|
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)
|
pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, nil, "aclitem", []pgxtest.ValueRoundTripTest{
|
||||||
defer testutil.MustCloseContext(t, conn)
|
|
||||||
|
|
||||||
testutil.RunTranscodeTestsFormat(t, "aclitem", []testutil.TranscodeTestCase{
|
|
||||||
{
|
{
|
||||||
pgtype.Text{String: "postgres=arwdDxt/postgres", Valid: true},
|
pgtype.Text{String: "postgres=arwdDxt/postgres", Valid: true},
|
||||||
new(pgtype.Text),
|
new(pgtype.Text),
|
||||||
@ -107,33 +112,33 @@ func TestTextCodecACLItem(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{pgtype.Text{}, new(pgtype.Text), isExpectedEq(pgtype.Text{})},
|
{pgtype.Text{}, new(pgtype.Text), isExpectedEq(pgtype.Text{})},
|
||||||
{nil, new(pgtype.Text), isExpectedEq(pgtype.Text{})},
|
{nil, new(pgtype.Text), isExpectedEq(pgtype.Text{})},
|
||||||
}, conn, "Text", pgtype.TextFormatCode)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTextCodecACLItemRoleWithSpecialCharacters(t *testing.T) {
|
func TestTextCodecACLItemRoleWithSpecialCharacters(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
ctr := defaultConnTestRunner
|
||||||
defer testutil.MustCloseContext(t, conn)
|
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
|
commandTag, err := conn.Exec(ctx, `select * from pg_roles where rolname = $1`, roleWithSpecialCharacters)
|
||||||
// of aclitem formatting. It turns out aclitems cannot contain non-existing users/roles.
|
require.NoError(t, err)
|
||||||
roleWithSpecialCharacters := ` tricky, ' } " \ test user `
|
|
||||||
|
|
||||||
commandTag, err := conn.Exec(ctx, `select * from pg_roles where rolname = $1`, roleWithSpecialCharacters)
|
if commandTag.RowsAffected() == 0 {
|
||||||
require.NoError(t, err)
|
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},
|
pgtype.Text{String: `postgres=arwdDxt/" tricky, ' } "" \ test user "`, Valid: true},
|
||||||
new(pgtype.Text),
|
new(pgtype.Text),
|
||||||
isExpectedEq(pgtype.Text{String: `postgres=arwdDxt/" tricky, ' } "" \ test user "`, Valid: true}),
|
isExpectedEq(pgtype.Text{String: `postgres=arwdDxt/" tricky, ' } "" \ test user "`, Valid: true}),
|
||||||
},
|
},
|
||||||
}, conn, "Text", pgtype.TextFormatCode)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTextMarshalJSON(t *testing.T) {
|
func TestTextMarshalJSON(t *testing.T) {
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTIDCodec(t *testing.T) {
|
func TestTIDCodec(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support type tid")
|
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},
|
pgtype.TID{BlockNumber: 42, OffsetNumber: 43, Valid: true},
|
||||||
new(pgtype.TID),
|
new(pgtype.TID),
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTimeCodec(t *testing.T) {
|
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},
|
pgtype.Time{Microseconds: 0, Valid: true},
|
||||||
new(pgtype.Time),
|
new(pgtype.Time),
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/internal/pgio"
|
"github.com/jackc/pgx/v5/internal/pgio"
|
||||||
@ -127,12 +128,29 @@ func (encodePlanTimestampCodecText) Encode(value interface{}, buf []byte) (newBu
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ts.Valid {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
var s string
|
var s string
|
||||||
|
|
||||||
switch ts.InfinityModifier {
|
switch ts.InfinityModifier {
|
||||||
case Finite:
|
case Finite:
|
||||||
t := discardTimeZone(ts.Time)
|
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)
|
s = t.Truncate(time.Microsecond).Format(pgTimestampFormat)
|
||||||
|
|
||||||
|
if bc {
|
||||||
|
s = s + " BC"
|
||||||
|
}
|
||||||
case Infinity:
|
case Infinity:
|
||||||
s = "infinity"
|
s = "infinity"
|
||||||
case NegativeInfinity:
|
case NegativeInfinity:
|
||||||
@ -219,11 +237,21 @@ func (scanPlanTextTimestampToTimestampScanner) Scan(src []byte, dst interface{})
|
|||||||
case "-infinity":
|
case "-infinity":
|
||||||
ts = Timestamp{Valid: true, InfinityModifier: -Infinity}
|
ts = Timestamp{Valid: true, InfinityModifier: -Infinity}
|
||||||
default:
|
default:
|
||||||
|
bc := false
|
||||||
|
if strings.HasSuffix(sbuf, " BC") {
|
||||||
|
sbuf = sbuf[:len(sbuf)-3]
|
||||||
|
bc = true
|
||||||
|
}
|
||||||
tim, err := time.Parse(pgTimestampFormat, sbuf)
|
tim, err := time.Parse(pgTimestampFormat, sbuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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}
|
ts = Timestamp{Time: tim, Valid: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,15 +5,21 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTimestampCodec(t *testing.T) {
|
func TestTimestampCodec(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support infinite timestamps (see https://github.com/cockroachdb/cockroach/issues/41564)")
|
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(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(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))},
|
{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
|
// https://github.com/jackc/pgx/v4/pgtype/pull/128
|
||||||
func TestTimestampTranscodeBigTimeBinary(t *testing.T) {
|
func TestTimestampTranscodeBigTimeBinary(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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}
|
err := conn.QueryRow(ctx, "select $1::timestamp", in).Scan(&out)
|
||||||
var out pgtype.Timestamp
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
err := conn.QueryRow(context.Background(), "select $1::timestamp", in).Scan(&out)
|
require.Equal(t, in.Valid, out.Valid)
|
||||||
if err != nil {
|
require.Truef(t, in.Time.Equal(out.Time), "expected %v got %v", in.Time, out.Time)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/jackc/pgtype/issues/74
|
// https://github.com/jackc/pgtype/issues/74
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/internal/pgio"
|
"github.com/jackc/pgx/v5/internal/pgio"
|
||||||
@ -184,11 +185,30 @@ func (encodePlanTimestamptzCodecText) Encode(value interface{}, buf []byte) (new
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ts.Valid {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
var s string
|
var s string
|
||||||
|
|
||||||
switch ts.InfinityModifier {
|
switch ts.InfinityModifier {
|
||||||
case Finite:
|
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:
|
case Infinity:
|
||||||
s = "infinity"
|
s = "infinity"
|
||||||
case NegativeInfinity:
|
case NegativeInfinity:
|
||||||
@ -267,6 +287,12 @@ func (scanPlanTextTimestamptzToTimestamptzScanner) Scan(src []byte, dst interfac
|
|||||||
case "-infinity":
|
case "-infinity":
|
||||||
tstz = Timestamptz{Valid: true, InfinityModifier: -Infinity}
|
tstz = Timestamptz{Valid: true, InfinityModifier: -Infinity}
|
||||||
default:
|
default:
|
||||||
|
bc := false
|
||||||
|
if strings.HasSuffix(sbuf, " BC") {
|
||||||
|
sbuf = sbuf[:len(sbuf)-3]
|
||||||
|
bc = true
|
||||||
|
}
|
||||||
|
|
||||||
var format string
|
var format string
|
||||||
if len(sbuf) >= 9 && (sbuf[len(sbuf)-9] == '-' || sbuf[len(sbuf)-9] == '+') {
|
if len(sbuf) >= 9 && (sbuf[len(sbuf)-9] == '-' || sbuf[len(sbuf)-9] == '+') {
|
||||||
format = pgTimestamptzSecondFormat
|
format = pgTimestamptzSecondFormat
|
||||||
@ -281,6 +307,11 @@ func (scanPlanTextTimestamptzToTimestamptzScanner) Scan(src []byte, dst interfac
|
|||||||
return err
|
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}
|
tstz = Timestamptz{Time: tim, Valid: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,15 +5,21 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTimestamptzCodec(t *testing.T) {
|
func TestTimestamptzCodec(t *testing.T) {
|
||||||
skipCockroachDB(t, "Server does not support infinite timestamps (see https://github.com/cockroachdb/cockroach/issues/41564)")
|
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(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(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))},
|
{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
|
// https://github.com/jackc/pgx/v4/pgtype/pull/128
|
||||||
func TestTimestamptzTranscodeBigTimeBinary(t *testing.T) {
|
func TestTimestamptzTranscodeBigTimeBinary(t *testing.T) {
|
||||||
conn := testutil.MustConnectPgx(t)
|
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||||
defer testutil.MustCloseContext(t, 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}
|
err := conn.QueryRow(ctx, "select $1::timestamptz", in).Scan(&out)
|
||||||
var out pgtype.Timestamptz
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
err := conn.QueryRow(context.Background(), "select $1::timestamptz", in).Scan(&out)
|
require.Equal(t, in.Valid, out.Valid)
|
||||||
if err != nil {
|
require.Truef(t, in.Time.Equal(out.Time), "expected %v got %v", in.Time, out.Time)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/jackc/pgtype/issues/74
|
// https://github.com/jackc/pgtype/issues/74
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUint32Codec(t *testing.T) {
|
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},
|
pgtype.Uint32{Uint32: pgtype.TextOID, Valid: true},
|
||||||
new(pgtype.Uint32),
|
new(pgtype.Uint32),
|
||||||
|
@ -1,31 +1,22 @@
|
|||||||
package pgtype_test
|
package pgtype_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUUIDCodec(t *testing.T) {
|
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},
|
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),
|
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}),
|
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",
|
"00010203-0405-0607-0809-0a0b0c0d0e0f",
|
||||||
new(pgtype.UUID),
|
new(pgtype.UUID),
|
||||||
@ -40,6 +31,19 @@ func TestUUIDCodec(t *testing.T) {
|
|||||||
{pgtype.UUID{}, new(pgtype.UUID), isExpectedEq(pgtype.UUID{})},
|
{pgtype.UUID{}, new(pgtype.UUID), isExpectedEq(pgtype.UUID{})},
|
||||||
{nil, 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) {
|
func TestUUID_MarshalJSON(t *testing.T) {
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package zeronull_test
|
package zeronull_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
||||||
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isExpectedEq(a interface{}) func(interface{}) bool {
|
func isExpectedEq(a interface{}) func(interface{}) bool {
|
||||||
@ -14,7 +15,7 @@ func isExpectedEq(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFloat8Transcode(t *testing.T) {
|
func TestFloat8Transcode(t *testing.T) {
|
||||||
testutil.RunTranscodeTests(t, "float8", []testutil.TranscodeTestCase{
|
pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "float8", []pgxtest.ValueRoundTripTest{
|
||||||
{
|
{
|
||||||
(zeronull.Float8)(1),
|
(zeronull.Float8)(1),
|
||||||
new(zeronull.Float8),
|
new(zeronull.Float8),
|
||||||
|
@ -2,14 +2,15 @@
|
|||||||
package zeronull_test
|
package zeronull_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
||||||
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInt2Transcode(t *testing.T) {
|
func TestInt2Transcode(t *testing.T) {
|
||||||
testutil.RunTranscodeTests(t, "int2", []testutil.TranscodeTestCase{
|
pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "int2", []pgxtest.ValueRoundTripTest{
|
||||||
{
|
{
|
||||||
(zeronull.Int2)(1),
|
(zeronull.Int2)(1),
|
||||||
new(zeronull.Int2),
|
new(zeronull.Int2),
|
||||||
@ -29,7 +30,7 @@ func TestInt2Transcode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInt4Transcode(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),
|
(zeronull.Int4)(1),
|
||||||
new(zeronull.Int4),
|
new(zeronull.Int4),
|
||||||
@ -49,7 +50,7 @@ func TestInt4Transcode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInt8Transcode(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),
|
(zeronull.Int8)(1),
|
||||||
new(zeronull.Int8),
|
new(zeronull.Int8),
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
<% [2, 4, 8].each do |pg_byte_size| %>
|
<% [2, 4, 8].each do |pg_byte_size| %>
|
||||||
<% pg_bit_size = pg_byte_size * 8 %>
|
<% pg_bit_size = pg_byte_size * 8 %>
|
||||||
func TestInt<%= pg_byte_size %>Transcode(t *testing.T) {
|
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),
|
(zeronull.Int<%= pg_byte_size %>)(1),
|
||||||
new(zeronull.Int<%= pg_byte_size %>),
|
new(zeronull.Int<%= pg_byte_size %>),
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package zeronull_test
|
package zeronull_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
||||||
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTextTranscode(t *testing.T) {
|
func TestTextTranscode(t *testing.T) {
|
||||||
testutil.RunTranscodeTests(t, "text", []testutil.TranscodeTestCase{
|
pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "text", []pgxtest.ValueRoundTripTest{
|
||||||
{
|
{
|
||||||
(zeronull.Text)("foo"),
|
(zeronull.Text)("foo"),
|
||||||
new(zeronull.Text),
|
new(zeronull.Text),
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package zeronull_test
|
package zeronull_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
||||||
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isExpectedEqTimestamp(a interface{}) func(interface{}) bool {
|
func isExpectedEqTimestamp(a interface{}) func(interface{}) bool {
|
||||||
@ -18,7 +19,7 @@ func isExpectedEqTimestamp(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTimestampTranscode(t *testing.T) {
|
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)),
|
(zeronull.Timestamp)(time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)),
|
||||||
new(zeronull.Timestamp),
|
new(zeronull.Timestamp),
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package zeronull_test
|
package zeronull_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
||||||
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isExpectedEqTimestamptz(a interface{}) func(interface{}) bool {
|
func isExpectedEqTimestamptz(a interface{}) func(interface{}) bool {
|
||||||
@ -18,7 +19,7 @@ func isExpectedEqTimestamptz(a interface{}) func(interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTimestamptzTranscode(t *testing.T) {
|
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)),
|
(zeronull.Timestamptz)(time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)),
|
||||||
new(zeronull.Timestamptz),
|
new(zeronull.Timestamptz),
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package zeronull_test
|
package zeronull_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/testutil"
|
|
||||||
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
"github.com/jackc/pgx/v5/pgtype/zeronull"
|
||||||
|
"github.com/jackc/pgx/v5/pgxtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUUIDTranscode(t *testing.T) {
|
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}),
|
(zeronull.UUID)([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
|
||||||
new(zeronull.UUID),
|
new(zeronull.UUID),
|
||||||
|
17
pgtype/zeronull/zeronull.go
Normal file
17
pgtype/zeronull/zeronull.go
Normal file
@ -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")
|
||||||
|
}
|
26
pgtype/zeronull/zeronull_test.go
Normal file
26
pgtype/zeronull/zeronull_test.go
Normal file
@ -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())
|
||||||
|
}
|
||||||
|
}
|
@ -3,11 +3,28 @@ package pgxtest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"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 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.
|
// ConnTestRunner with reasonable default values.
|
||||||
type ConnTestRunner struct {
|
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)) {
|
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)
|
config := ctr.CreateConfig(ctx, t)
|
||||||
conn, err := pgx.ConnectConfig(ctx, config)
|
conn, err := pgx.ConnectConfig(ctx, config)
|
||||||
if err != nil {
|
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.
|
// 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)) {
|
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 {
|
if modes == nil {
|
||||||
modes = []pgx.QueryExecMode{
|
modes = AllQueryExecModes
|
||||||
pgx.QueryExecModeCacheStatement,
|
|
||||||
pgx.QueryExecModeCacheDescribe,
|
|
||||||
pgx.QueryExecModeDescribeExec,
|
|
||||||
pgx.QueryExecModeExec,
|
|
||||||
pgx.QueryExecModeSimpleProtocol,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mode := range modes {
|
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.
|
// 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) {
|
func SkipCockroachDB(t testing.TB, conn *pgx.Conn, msg string) {
|
||||||
if conn.PgConn().ParameterStatus("crdb_version") != "" {
|
if conn.PgConn().ParameterStatus("crdb_version") != "" {
|
||||||
|
@ -17,7 +17,7 @@ func convertSimpleArgument(m *pgtype.Map, arg interface{}) (interface{}, error)
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := m.Encode(0, TextFormatCode, arg, nil)
|
buf, err := m.Encode(0, TextFormatCode, arg, []byte{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user