package pgtype_test import ( "bytes" "context" "testing" "github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype/testutil" "github.com/stretchr/testify/require" ) func isExpectedEqBytes(a interface{}) func(interface{}) bool { return func(v interface{}) bool { ab := a.([]byte) vb := v.([]byte) if (ab == nil) != (vb == nil) { return false } if ab == nil { return true } return bytes.Compare(ab, vb) == 0 } } func TestByteaCodec(t *testing.T) { testutil.RunTranscodeTests(t, "bytea", []testutil.TranscodeTestCase{ {[]byte{1, 2, 3}, new([]byte), isExpectedEqBytes([]byte{1, 2, 3})}, {[]byte{}, new([]byte), isExpectedEqBytes([]byte{})}, {[]byte(nil), new([]byte), isExpectedEqBytes([]byte(nil))}, {nil, new([]byte), isExpectedEqBytes([]byte(nil))}, }) } func TestDriverBytesQueryRow(t *testing.T) { conn := testutil.MustConnectPgx(t) defer testutil.MustCloseContext(t, conn) ctx := context.Background() var buf []byte err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.DriverBytes)(&buf)) require.EqualError(t, err, "cannot scan into *pgtype.DriverBytes from QueryRow") } func TestDriverBytes(t *testing.T) { conn := testutil.MustConnectPgx(t) defer testutil.MustCloseContext(t, conn) ctx := context.Background() argBuf := make([]byte, 128) for i := range argBuf { argBuf[i] = byte(i) } rows, err := conn.Query(ctx, `select $1::bytea from generate_series(1, 1000)`, argBuf) require.NoError(t, err) defer rows.Close() rowCount := 0 resultBuf := argBuf detectedResultMutation := false for rows.Next() { rowCount++ // At some point the buffer should be reused and change. if bytes.Compare(argBuf, resultBuf) != 0 { detectedResultMutation = true } err = rows.Scan((*pgtype.DriverBytes)(&resultBuf)) require.NoError(t, err) require.Len(t, resultBuf, len(argBuf)) require.Equal(t, resultBuf, argBuf) require.Equalf(t, cap(resultBuf), len(resultBuf), "cap(resultBuf) is larger than len(resultBuf)") } require.True(t, detectedResultMutation) err = rows.Err() require.NoError(t, err) } func TestPreallocBytes(t *testing.T) { conn := testutil.MustConnectPgx(t) defer testutil.MustCloseContext(t, conn) ctx := context.Background() origBuf := []byte{5, 6, 7, 8} buf := origBuf err := conn.QueryRow(ctx, `select $1::bytea`, []byte{1, 2}).Scan((*pgtype.PreallocBytes)(&buf)) require.NoError(t, err) require.Len(t, buf, 2) require.Equal(t, 4, cap(buf)) require.Equal(t, buf, []byte{1, 2}) 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) { conn := testutil.MustConnectPgx(t) defer testutil.MustCloseContext(t, conn) ctx := context.Background() var buf []byte err := conn.QueryRow(ctx, `select 1`).Scan((*pgtype.UndecodedBytes)(&buf)) require.NoError(t, err) require.Len(t, buf, 4) require.Equal(t, buf, []byte{0, 0, 0, 1}) }