Files
2026-07-13 12:32:25 +08:00

7872 lines
215 KiB
Go

// Copyright 2026 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package _go
import (
"fmt"
"net"
"os"
"reflect"
"strings"
"testing"
"time"
"github.com/dolthub/go-mysql-server/sql"
"github.com/cockroachdb/errors"
"github.com/jackc/pgx/v5/pgproto3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/xdg-go/scram"
)
// TestWireTypesSending allows us to directly test what is sent on the wire regarding types, ensuring that the wire
// protocol is correctly implemented. ANY changes made to ANY test must be validated against an external Postgres server
// using the `ExternalServerPort` field.
func TestWireTypesSending(t *testing.T) {
RunWireScripts(t, []WireScriptTest{
{
Name: "Smoke Test",
SetUpScript: []string{
"CREATE TABLE test (pk INT4 PRIMARY KEY);",
"INSERT INTO test VALUES (7);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Query{String: "SELECT * FROM test;"},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("pk"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 23,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.DataRow{Values: [][]byte{[]byte("7")}},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BIT returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 BIT(8), v2 BIT(3));",
"INSERT INTO test VALUES (B'11011010', '101');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1560,
DataTypeSize: -1,
TypeModifier: 8,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1560,
DataTypeSize: -1,
TypeModifier: 3,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("11011010"),
[]byte("101"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BIT returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BIT(65), v2 BIT(3));",
"INSERT INTO test VALUES (B'10101010001000110110110010110011000101010110101010010110101011001', '101');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1560,
DataTypeSize: -1,
TypeModifier: 65,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1560,
DataTypeSize: -1,
TypeModifier: 3,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 65, 170, 35, 108, 179, 21, 106, 150, 172, 128},
{0, 0, 0, 3, 160},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BIT VARYING returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 BIT VARYING, v2 BIT VARYING(5));",
"INSERT INTO test VALUES (B'100101010110011001', '110');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1562,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1562,
DataTypeSize: -1,
TypeModifier: 5,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("100101010110011001"),
[]byte("110"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BIT VARYING returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BIT VARYING, v2 BIT VARYING(5));",
"INSERT INTO test VALUES (B'100101010110011001', '110');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1562,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1562,
DataTypeSize: -1,
TypeModifier: 5,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 18, 149, 102, 64},
{0, 0, 0, 3, 192},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BOOL returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 BOOL, v2 BOOL);",
"INSERT INTO test VALUES (true, false);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 16,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 16,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("t"),
[]byte("f"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BOOL returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BOOL, v2 BOOL);",
"INSERT INTO test VALUES (true, false);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 16,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 16,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{1},
{0},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BPCHAR returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 BPCHAR, v2 BPCHAR(7));",
"INSERT INTO test VALUES ('', 'abc'), ('more text', 'text');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1042,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1042,
DataTypeSize: -1,
TypeModifier: 11,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{},
[]byte("abc "),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("more text"),
[]byte("text "),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BPCHAR returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BPCHAR, v2 BPCHAR(7));",
"INSERT INTO test VALUES ('', 'abc'), ('more text', 'text');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1042,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1042,
DataTypeSize: -1,
TypeModifier: 11,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{},
[]byte("abc "),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("more text"),
[]byte("text "),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BYTEA returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 BYTEA, v2 BYTEA);",
"INSERT INTO test VALUES ('', E'\\\\xDEADBEEF'), ('\\xC0FFEE', NULL);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 17,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 17,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`\x`),
[]byte(`\xdeadbeef`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`\xc0ffee`),
nil,
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BYTEA returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BYTEA, v2 BYTEA);",
"INSERT INTO test VALUES ('', E'\\\\xDEADBEEF'), ('\\xC0FFEE', NULL);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 17,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 17,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{},
{222, 173, 190, 239},
},
},
&pgproto3.DataRow{
Values: [][]byte{
{192, 255, 238},
nil,
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `"char" returning text format`,
SetUpScript: []string{
`CREATE TABLE test (v1 "char", v2 "char");`,
`INSERT INTO test VALUES ('123', 'v');`,
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 18,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 18,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1"),
[]byte("v"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `"char" returning binary format`,
SetUpScript: []string{
`CREATE TABLE test (v1 "char", v2 "char");`,
`INSERT INTO test VALUES ('123', 'v');`,
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 18,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 18,
DataTypeSize: 1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{'1'},
{'v'},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "DATE returning text format",
Skip: true, // TODO: datestyle isn't working for DATE
SetUpScript: []string{
"SET datestyle TO 'ISO, YMD';",
"CREATE TABLE test (v1 DATE, v2 DATE);",
"INSERT INTO test VALUES ('1999-01-08', 'April 17, 2025');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1082,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1082,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1999-01-08"),
[]byte("2025-04-17"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "DATE returning binary format",
SetUpScript: []string{
"SET datestyle TO 'ISO, YMD';",
"CREATE TABLE test (v1 DATE, v2 DATE);",
"INSERT INTO test VALUES ('1999-01-08', 'April 17, 2025');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1082,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1082,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{255, 255, 254, 154},
{0, 0, 36, 22},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "ENUM returning text format",
SetUpScript: []string{
"CREATE TYPE enumType AS ENUM ('eval1', 'eval2', 'eval3');",
"CREATE TABLE test (v1 enumType, v2 enumType);",
"INSERT INTO test VALUES ('eval1', 'eval3');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 0,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 0,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("eval1"),
[]byte("eval3"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "ENUM returning binary format",
SetUpScript: []string{
"CREATE TYPE enumType AS ENUM ('eval1', 'eval2', 'eval3');",
"CREATE TABLE test (v1 enumType, v2 enumType);",
"INSERT INTO test VALUES ('eval1', 'eval3');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 0,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 0,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("eval1"),
[]byte("eval3"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "FLOAT4 returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 FLOAT4, v2 FLOAT4);",
"INSERT INTO test VALUES (-0.5, 26.015625);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 700,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 700,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-0.5"),
[]byte("26.015625"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "FLOAT4 returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 FLOAT4, v2 FLOAT4);",
"INSERT INTO test VALUES (-0.5, 26.015625);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 700,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 700,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{191, 0, 0, 0},
{65, 208, 32, 0},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "FLOAT8 returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 FLOAT8, v2 FLOAT8);",
"INSERT INTO test VALUES (-0.5, 26.015625);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 701,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 701,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-0.5"),
[]byte("26.015625"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "FLOAT8 returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 FLOAT8, v2 FLOAT8);",
"INSERT INTO test VALUES (-0.5, 26.015625);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 701,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 701,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{191, 224, 0, 0, 0, 0, 0, 0},
{64, 58, 4, 0, 0, 0, 0, 0},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT2 returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 INT2, v2 INT2);",
"INSERT INTO test VALUES (3, 12646);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 21,
DataTypeSize: 2,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 21,
DataTypeSize: 2,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("3"),
[]byte("12646"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT2 returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 INT2, v2 INT2);",
"INSERT INTO test VALUES (3, 12646);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 21,
DataTypeSize: 2,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 21,
DataTypeSize: 2,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 3},
{49, 102},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT2VECTOR returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 int2vector, v2 int2vector);",
"INSERT INTO test VALUES ('1 2 4 5', '5 87 991');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 22,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 22,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1 2 4 5"),
[]byte("5 87 991"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT2VECTOR returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 int2vector, v2 int2vector);",
"INSERT INTO test VALUES ('1 2 4 5', '5 87 991');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 22,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 22,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 4, 0, 0, 0, 2, 0, 5},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 5, 0, 0, 0, 2, 0, 87, 0, 0, 0, 2, 3, 223},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT4 returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 INT4, v2 INT4);",
"INSERT INTO test VALUES (-5, 3578457);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 23,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 23,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-5"),
[]byte("3578457"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT4 returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 INT4, v2 INT4);",
"INSERT INTO test VALUES (-5, 3578457);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 23,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 23,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{255, 255, 255, 251},
{0, 54, 154, 89},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT8 returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 INT8, v2 INT8);",
"INSERT INTO test VALUES (-44, 2578457279345);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 20,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 20,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-44"),
[]byte("2578457279345"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INT8 returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 INT8, v2 INT8);",
"INSERT INTO test VALUES (-44, 2578457279345);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 20,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 20,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{255, 255, 255, 255, 255, 255, 255, 212},
{0, 0, 2, 88, 88, 7, 187, 113},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INTERVAL returning text format",
Skip: true, // TODO: need to fix our text output for intervals
SetUpScript: []string{
"CREATE TABLE test (v1 INTERVAL, v2 INTERVAL);",
"INSERT INTO test VALUES ('@ 1 minute', '2 years 15 months 100 weeks 99 hours 123456789 milliseconds');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1186,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1186,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("@ 1 min"),
[]byte("@ 3 years 3 mons 700 days 133 hours 17 mins 36.789 secs"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "INTERVAL returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 INTERVAL, v2 INTERVAL);",
"INSERT INTO test VALUES ('@ 1 minute', '2 years 15 months 100 weeks 99 hours 123456789 milliseconds');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1186,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1186,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 3, 147, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 111, 185, 177, 134, 8, 0, 0, 2, 188, 0, 0, 0, 39},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "JSON returning text format",
SetUpScript: []string{
`CREATE TABLE test (v1 JSON, v2 JSON, v3 INT4);`,
`INSERT INTO test VALUES ('{"key1": {"key": "value"}}', '{}', 1), ('{"key1": {"key": [2, 3]}}', '[]', 2);`,
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT v1, v2 FROM test ORDER BY v3;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 114,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 114,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1":{"key":"value"}}`),
[]byte(`{}`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1":{"key":[2,3]}}`),
[]byte(`[]`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "JSON returning binary format",
SetUpScript: []string{
`CREATE TABLE test (v1 JSON, v2 JSON, v3 INT4);`,
`INSERT INTO test VALUES ('{"key1": {"key": "value"}}', '{}', 1), ('{"key1": {"key": [2, 3]}}', '[]', 2);`,
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT v1, v2 FROM test ORDER BY v3;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 114,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 114,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1": {"key": "value"}}`),
[]byte(`{}`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1": {"key": [2, 3]}}`),
[]byte(`[]`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "JSONB returning text format",
SetUpScript: []string{
`CREATE TABLE test (v1 JSONB, v2 JSONB, v3 INT4);`,
`INSERT INTO test VALUES ('{"key1": {"key": "value"}}', '{}', 1), ('{"key1": {"key": [2, 3]}}', '[]', 2);`,
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT v1, v2 FROM test ORDER BY v3;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 3802,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 3802,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1": {"key": "value"}}`),
[]byte(`{}`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1": {"key": [2, 3]}}`),
[]byte(`[]`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "JSONB returning binary format",
SetUpScript: []string{
`CREATE TABLE test (v1 JSONB, v2 JSONB, v3 INT4);`,
`INSERT INTO test VALUES ('{"key1": {"key": "value"}}', '{}', 1), ('{"key1": {"key": [2, 3]}}', '[]', 2);`,
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT v1, v2 FROM test ORDER BY v3;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 3802,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 3802,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
append([]byte{1}, []byte(`{"key1": {"key": "value"}}`)...),
{1, 123, 125},
},
},
&pgproto3.DataRow{
Values: [][]byte{
append([]byte{1}, []byte(`{"key1": {"key": [2, 3]}}`)...),
{1, 91, 93},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "NAME returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 NAME, v2 NAME);",
"INSERT INTO test VALUES ('', 'abc'), (NULL, 'a\",c');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 19,
DataTypeSize: 64,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 19,
DataTypeSize: 64,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
nil,
[]byte(`a",c`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "NAME returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 NAME, v2 NAME);",
"INSERT INTO test VALUES ('', 'abc'), (NULL, 'a\",c');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 19,
DataTypeSize: 64,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 19,
DataTypeSize: 64,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
nil,
[]byte(`a",c`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "NUMERIC returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 NUMERIC, v2 NUMERIC(5,2), v3 NUMERIC(14,5));",
"INSERT INTO test VALUES (0, -0.1, NULL), (12357232.456786653224768755799, 235.67, 4278.009), ('Infinity', 'NaN', 'NaN'), ('-Infinity', '0.05', '0.1045678');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1700,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1700,
DataTypeSize: -1,
TypeModifier: 327686,
Format: 0,
},
{
Name: []byte("v3"),
TableOID: 0,
TableAttributeNumber: 3,
DataTypeOID: 1700,
DataTypeSize: -1,
TypeModifier: 917513,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`-Infinity`),
[]byte(`0.05`),
[]byte(`0.10457`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`0`),
[]byte(`-0.10`),
nil,
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`12357232.456786653224768755799`),
[]byte(`235.67`),
[]byte(`4278.00900`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`Infinity`),
[]byte(`NaN`),
[]byte(`NaN`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 4")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "NUMERIC returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 NUMERIC, v2 NUMERIC(5,2), v3 NUMERIC(14,5));",
"INSERT INTO test VALUES (0, -0.1, NULL), (12357232.456786653224768755799, 235.67, 4278.009), ('Infinity', 'NaN', 'NaN'), ('-Infinity', '0.05', '0.1045678');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1700,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1700,
DataTypeSize: -1,
TypeModifier: 327686,
Format: 0,
},
{
Name: []byte("v3"),
TableOID: 0,
TableAttributeNumber: 3,
DataTypeOID: 1700,
DataTypeSize: -1,
TypeModifier: 917513,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 240, 0, 0, 32},
{0, 1, 255, 255, 0, 0, 0, 2, 1, 244},
{0, 2, 255, 255, 0, 0, 0, 5, 4, 21, 27, 88},
},
},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 255, 255, 64, 0, 0, 2, 3, 232},
nil,
},
},
&pgproto3.DataRow{
Values: [][]byte{
{0, 8, 0, 1, 0, 0, 0, 21, 4, 211, 28, 64, 17, 215, 33, 217, 12, 152, 30, 7, 21, 203, 35, 40},
{0, 2, 0, 0, 0, 0, 0, 2, 0, 235, 26, 44},
{0, 2, 0, 0, 0, 0, 0, 5, 16, 182, 0, 90},
},
},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 208, 0, 0, 32},
{0, 0, 0, 0, 192, 0, 0, 0},
{0, 0, 0, 0, 192, 0, 0, 0},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 4")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "OID returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 OID, v2 OID);",
"INSERT INTO test VALUES (1, 2483574913);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 26,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 26,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1"),
[]byte("2483574913"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "OID returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 OID, v2 OID);",
"INSERT INTO test VALUES (1, 2483574913);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 26,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 26,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 1},
{148, 8, 88, 129},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "OIDVECTOR returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 oidvector, v2 oidvector);",
"INSERT INTO test VALUES ('1234 2489', '2483 574 913');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 30,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 30,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1234 2489"),
[]byte("2483 574 913"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "OIDVECTOR returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 oidvector, v2 oidvector);",
"INSERT INTO test VALUES ('1234 2489', '2483 574 913');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 30,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 30,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 210, 0, 0, 0, 4, 0, 0, 9, 185},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 9, 179, 0, 0, 0, 4, 0, 0, 2, 62, 0, 0, 0, 4, 0, 0, 3, 145},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "RECORD returning text format",
SetUpScript: []string{
"CREATE TABLE pre1 (v1 TEXT, v2 INT8, v3 NUMERIC(6,1));",
"CREATE TABLE pre2 (v1 VARCHAR, v2 OID, v3 BOOL);",
"CREATE TABLE test (v1 pre1, v2 pre2);",
"INSERT INTO test VALUES (ROW('abc'::TEXT, 1::INT8, '12345.6'::NUMERIC(6,1)), ROW('def'::VARCHAR, 2::OID, 't'::BOOL));",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 0, // User-defined OID will always differ
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 0, // User-defined OID will always differ
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`(abc,1,12345.6)`),
[]byte(`(def,2,t)`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "RECORD returning binary format",
SetUpScript: []string{
"CREATE TABLE pre1 (v1 TEXT, v2 INT8, v3 NUMERIC(6,1));",
"CREATE TABLE pre2 (v1 VARCHAR, v2 OID, v3 BOOL);",
"CREATE TABLE test (v1 pre1, v2 pre2);",
"INSERT INTO test VALUES (ROW('abc'::TEXT, 1::INT8, '12345.6'::NUMERIC(6,1)), ROW('def'::VARCHAR, 2::OID, 't'::BOOL));",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 0, // User-defined OID will always differ
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 0, // User-defined OID will always differ
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 3, 0, 0, 0, 25, 0, 0, 0, 3, 97, 98, 99, 0, 0, 0, 20, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 6, 164, 0, 0, 0, 14, 0, 3, 0, 1, 0, 0, 0, 1, 0, 1, 9, 41, 23, 112},
{0, 0, 0, 3, 0, 0, 4, 19, 0, 0, 0, 3, 100, 101, 102, 0, 0, 0, 26, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 1, 1},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "REGTYPE returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 REGTYPE, v2 REGTYPE);",
"INSERT INTO test VALUES ('numeric'::REGTYPE, 'text'::REGTYPE);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 2206,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 2206,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("numeric"),
[]byte("text"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "REGTYPE returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 REGTYPE, v2 REGTYPE);",
"INSERT INTO test VALUES ('numeric'::REGTYPE, 'text'::REGTYPE);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 2206,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 2206,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 6, 164},
{0, 0, 0, 25},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TEXT returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 TEXT, v2 TEXT);",
"INSERT INTO test VALUES ('', 'abc'), (NULL, 'a\",c');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 25,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 25,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
nil,
[]byte(`a",c`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TEXT returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 TEXT, v2 TEXT);",
"INSERT INTO test VALUES ('', 'abc'), (NULL, 'a\",c');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 25,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 25,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
nil,
[]byte(`a",c`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TEXT ARRAY returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 TEXT[], v2 TEXT[]);",
"INSERT INTO test VALUES (ARRAY[]::text[], ARRAY['a','bb','ccc']), (NULL, ARRAY['dd',NULL,'ee']);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1009,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1009,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("{}"),
[]byte("{a,bb,ccc}"),
},
},
&pgproto3.DataRow{
Values: [][]byte{
nil,
[]byte("{dd,NULL,ee}"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TEXT ARRAY returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 TEXT[], v2 TEXT[]);",
"INSERT INTO test VALUES (ARRAY[]::text[], ARRAY['a','bb','ccc']), (NULL, ARRAY['dd',NULL,'ee']);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1009,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1009,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 97, 0, 0, 0, 2, 98, 98, 0, 0, 0, 3, 99, 99, 99},
},
},
&pgproto3.DataRow{
Values: [][]byte{
nil,
{0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 2, 100, 100, 255, 255, 255, 255, 0, 0, 0, 2, 101, 101},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIME returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 TIME, v2 TIME);",
"INSERT INTO test VALUES ('0:0', '04:05:06.789'), ('09:27 PM', '12:12');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1083,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1083,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`00:00:00`),
[]byte(`04:05:06.789`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`21:27:00`),
[]byte(`12:12:00`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIME returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 TIME, v2 TIME);",
"INSERT INTO test VALUES ('0:0', '04:05:06.789'), ('09:27 PM', '12:12');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1083,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1083,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 3, 108, 151, 202, 136},
},
},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 17, 250, 171, 177, 0},
{0, 0, 0, 10, 57, 214, 4, 0},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIMETZ returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 TIMETZ, v2 TIMETZ);",
"INSERT INTO test VALUES ('0:0 PST', '04:05:06.789 MST'), ('09:27 PM CST', '12:12 EST');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1266,
DataTypeSize: 12,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1266,
DataTypeSize: 12,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`00:00:00-08`),
[]byte(`04:05:06.789-07`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`21:27:00-06`),
[]byte(`12:12:00-05`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIMETZ returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 TIMETZ, v2 TIMETZ);",
"INSERT INTO test VALUES ('0:0 PST', '04:05:06.789 PDT'), ('09:27 PM CST', '12:12 EST');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1266,
DataTypeSize: 12,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1266,
DataTypeSize: 12,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 128},
{0, 0, 0, 3, 108, 151, 202, 136, 0, 0, 98, 112},
},
},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 17, 250, 171, 177, 0, 0, 0, 84, 96},
{0, 0, 0, 10, 57, 214, 4, 0, 0, 0, 70, 80},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIMESTAMP returning text format",
SetUpScript: []string{
"SET datestyle TO 'Postgres, MDY';",
"CREATE TABLE test (v1 TIMESTAMP, v2 TIMESTAMP);",
"INSERT INTO test VALUES ('2020-01-12 00:00:00', '2021-02-13 04:05:06.789'), ('2022-03-14 10:11:12', '2023-04-15 11:12:13');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1114,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1114,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`Sun Jan 12 00:00:00 2020`),
[]byte(`Sat Feb 13 04:05:06.789 2021`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`Mon Mar 14 10:11:12 2022`),
[]byte(`Sat Apr 15 11:12:13 2023`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIMESTAMP returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 TIMESTAMP, v2 TIMESTAMP);",
"INSERT INTO test VALUES ('2020-01-12 00:00:00', '2021-02-13 04:05:06.789'), ('2022-03-14 10:11:12', '2023-04-15 11:12:13');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1114,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1114,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 2, 62, 228, 207, 3, 128, 0},
{0, 2, 94, 46, 160, 114, 138, 136},
},
},
&pgproto3.DataRow{
Values: [][]byte{
{0, 2, 125, 41, 171, 38, 208, 0},
{0, 2, 156, 92, 204, 93, 29, 64},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIMESTAMPTZ returning text format",
SetUpScript: []string{
"SET datestyle TO 'Postgres, MDY';",
"CREATE TABLE test (v1 TIMESTAMPTZ, v2 TIMESTAMPTZ);",
"INSERT INTO test VALUES ('2020-01-12 00:00:00 PST', '2021-02-13 04:05:06.789 MST'), ('2022-03-14 10:11:12 CST', '2023-04-15 11:12:13 EST');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1184,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1184,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`Sun Jan 12 00:00:00 2020 PST`),
[]byte(`Sat Feb 13 03:05:06.789 2021 PST`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`Mon Mar 14 09:11:12 2022 PDT`),
[]byte(`Sat Apr 15 09:12:13 2023 PDT`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "TIMESTAMPTZ returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 TIMESTAMPTZ, v2 TIMESTAMPTZ);",
"INSERT INTO test VALUES ('2020-01-12 00:00:00 PST', '2021-02-13 04:05:06.789 MST'), ('2022-03-14 10:11:12 CST', '2023-04-15 11:12:13 EST');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1184,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1184,
DataTypeSize: 8,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 2, 62, 235, 131, 160, 160, 0},
{0, 2, 94, 52, 126, 124, 6, 136},
},
},
&pgproto3.DataRow{
Values: [][]byte{
{0, 2, 125, 46, 178, 156, 168, 0},
{0, 2, 156, 96, 253, 63, 81, 64},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "UUID returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 UUID, v2 UUID);",
"INSERT INTO test VALUES ('fdabf03d-9b21-4531-b900-c6f6cff8386c', '0730791c-c0dd-4972-9e72-11ead9317a5a');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 2950,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 2950,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("fdabf03d-9b21-4531-b900-c6f6cff8386c"),
[]byte("0730791c-c0dd-4972-9e72-11ead9317a5a"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "UUID returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 UUID, v2 UUID);",
"INSERT INTO test VALUES ('fdabf03d-9b21-4531-b900-c6f6cff8386c', '0730791c-c0dd-4972-9e72-11ead9317a5a');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 2950,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 2950,
DataTypeSize: 16,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{253, 171, 240, 61, 155, 33, 69, 49, 185, 0, 198, 246, 207, 248, 56, 108},
{7, 48, 121, 28, 192, 221, 73, 114, 158, 114, 17, 234, 217, 49, 122, 90},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "VARCHAR returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 VARCHAR, v2 VARCHAR(5));",
"INSERT INTO test VALUES ('', 'abc'), (NULL, 'a\",c');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1043,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1043,
DataTypeSize: -1,
TypeModifier: 9,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
nil,
[]byte(`a",c`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "VARCHAR returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 VARCHAR, v2 VARCHAR(5));",
"INSERT INTO test VALUES ('', 'abc'), (NULL, 'a\",c');",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test ORDER BY v1 NULLS FIRST;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 1043,
DataTypeSize: -1,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 1043,
DataTypeSize: -1,
TypeModifier: 9,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
nil,
[]byte(`a",c`),
},
},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 2")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "XID returning text format",
SetUpScript: []string{
"CREATE TABLE test (v1 XID, v2 XID);",
"INSERT INTO test VALUES (1::TEXT::XID, 2483574913::TEXT::XID);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 28,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 28,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1"),
[]byte("2483574913"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "XID returning binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 XID, v2 XID);",
"INSERT INTO test VALUES (1::TEXT::XID, 2483574913::TEXT::XID);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name",
Query: "SELECT * FROM test;",
},
&pgproto3.Describe{
ObjectType: 'S',
Name: "stmt_name",
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.ParameterDescription{ParameterOIDs: []uint32{}},
&pgproto3.RowDescription{
Fields: []pgproto3.FieldDescription{
{
Name: []byte("v1"),
TableOID: 0,
TableAttributeNumber: 1,
DataTypeOID: 28,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
{
Name: []byte("v2"),
TableOID: 0,
TableAttributeNumber: 2,
DataTypeOID: 28,
DataTypeSize: 4,
TypeModifier: -1,
Format: 0,
},
},
},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 1},
{148, 8, 88, 129},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
})
}
// TestWireTypesReceiving allows us to directly test what is received on the wire regarding types, ensuring that the
// wire protocol is correctly implemented. ANY changes made to ANY test must be validated against an external Postgres
// server using the `ExternalServerPort` field.
func TestWireTypesReceiving(t *testing.T) {
RunWireScripts(t, []WireScriptTest{
{
Name: "BIT receiving binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BIT(65), v2 BIT(3));",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1, 1},
Parameters: [][]byte{
{0, 0, 0, 65, 170, 35, 108, 179, 21, 106, 150, 172, 128},
{0, 0, 0, 3, 160},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("10101010001000110110110010110011000101010110101010010110101011001"),
[]byte("101"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BIT VARYING receiving binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BIT VARYING, v2 BIT VARYING(5));",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 18, 149, 102, 64},
{0, 0, 0, 3, 192},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("100101010110011001"),
[]byte("110"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BOOL receiving binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BOOL, v2 BOOL);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{1},
{0},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("t"),
[]byte("f"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: "BYTEA receiving binary format",
SetUpScript: []string{
"CREATE TABLE test (v1 BYTEA, v2 BYTEA);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{222, 173, 190, 239},
{192, 255, 238},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`\xdeadbeef`),
[]byte(`\xc0ffee`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `"char" receiving binary format`,
SetUpScript: []string{
`CREATE TABLE test (v1 "char", v2 "char");`,
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{'1'},
{'v'},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{'1'},
{'v'},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `DATE receiving binary format`,
SetUpScript: []string{
"SET datestyle TO 'ISO, YMD';",
"CREATE TABLE test (v1 DATE, v2 DATE);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{255, 255, 254, 154},
{0, 0, 36, 22},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{255, 255, 254, 154},
{0, 0, 36, 22},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `ENUM receiving binary format`,
SetUpScript: []string{
"CREATE TYPE enumType AS ENUM ('eval1', 'eval2', 'eval3');",
"CREATE TABLE test (v1 enumType, v2 enumType);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
[]byte("eval1"),
[]byte("eval3"),
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("eval1"),
[]byte("eval3"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `FLOAT4 receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 FLOAT4, v2 FLOAT4);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{191, 0, 0, 0},
{65, 208, 32, 0},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-0.5"),
[]byte("26.015625"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `FLOAT8 receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 FLOAT8, v2 FLOAT8);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{191, 224, 0, 0, 0, 0, 0, 0},
{64, 58, 4, 0, 0, 0, 0, 0},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-0.5"),
[]byte("26.015625"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `INT2 receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 INT2, v2 INT2);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 3},
{49, 102},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("3"),
[]byte("12646"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `INT2VECTOR receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 INT2VECTOR, v2 INT2VECTOR);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 4, 0, 0, 0, 2, 0, 5},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 5, 0, 0, 0, 2, 0, 87, 0, 0, 0, 2, 3, 223},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1 2 4 5"),
[]byte("5 87 991"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `INT4 receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 INT4, v2 INT4);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{255, 255, 255, 251},
{0, 54, 154, 89},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-5"),
[]byte("3578457"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `INT8 receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 INT8, v2 INT8);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{255, 255, 255, 255, 255, 255, 255, 212},
{0, 0, 2, 88, 88, 7, 187, 113},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("-44"),
[]byte("2578457279345"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `INTERVAL receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 INTERVAL, v2 INTERVAL);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 0, 3, 147, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 111, 185, 177, 134, 8, 0, 0, 2, 188, 0, 0, 0, 39},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
{0, 0, 0, 0, 3, 147, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 111, 185, 177, 134, 8, 0, 0, 2, 188, 0, 0, 0, 39},
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `JSON receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 JSON, v2 JSON);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
[]byte(`{"key1": {"key": "value"}}`),
[]byte(`{}`),
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{1},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1": {"key": "value"}}`),
[]byte(`{}`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `JSONB receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 JSONB, v2 JSONB);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
append([]byte{1}, []byte(`{"key1": {"key": [2, 3]}}`)...),
{1, 91, 93},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`{"key1": {"key": [2, 3]}}`),
[]byte(`[]`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `NAME receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 NAME, v2 NAME);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
[]byte(""),
[]byte("abc"),
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `NUMERIC receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 NUMERIC, v2 NUMERIC(5,2), v3 NUMERIC(14,5));",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2, $3);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 8, 0, 1, 0, 0, 0, 21, 4, 211, 28, 64, 17, 215, 33, 217, 12, 152, 30, 7, 21, 203, 35, 40},
{0, 2, 0, 0, 0, 0, 0, 2, 0, 235, 26, 44},
{0, 2, 0, 0, 0, 0, 0, 5, 16, 182, 0, 90},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`12357232.456786653224768755799`),
[]byte(`235.67`),
[]byte(`4278.00900`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `OID receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 OID, v2 OID);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 1},
{148, 8, 88, 129},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1"),
[]byte("2483574913"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `OIDVECTOR receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 OIDVECTOR, v2 OIDVECTOR);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 210, 0, 0, 0, 4, 0, 0, 9, 185},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 9, 179, 0, 0, 0, 4, 0, 0, 2, 62, 0, 0, 0, 4, 0, 0, 3, 145},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1234 2489"),
[]byte("2483 574 913"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `RECORD receiving binary format`,
SetUpScript: []string{
"CREATE TABLE pre1 (v1 TEXT, v2 INT8, v3 NUMERIC(6,1));",
"CREATE TABLE pre2 (v1 VARCHAR, v2 OID, v3 BOOL);",
"CREATE TABLE test (v1 pre1, v2 pre2);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 3, 0, 0, 0, 25, 0, 0, 0, 3, 97, 98, 99, 0, 0, 0, 20, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 6, 164, 0, 0, 0, 14, 0, 3, 0, 1, 0, 0, 0, 1, 0, 1, 9, 41, 23, 112},
{0, 0, 0, 3, 0, 0, 4, 19, 0, 0, 0, 3, 100, 101, 102, 0, 0, 0, 26, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 1, 1},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`(abc,1,12345.6)`),
[]byte(`(def,2,t)`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `REGTYPE receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 REGTYPE, v2 REGTYPE);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 6, 164},
{0, 0, 0, 25},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("numeric"),
[]byte("text"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `TEXT receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 TEXT, v2 TEXT);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
[]byte(""),
[]byte("abc"),
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte("abc"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `TEXT ARRAY receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 TEXT[], v2 TEXT[]);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25},
{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 97, 0, 0, 0, 2, 98, 98, 0, 0, 0, 3, 99, 99, 99},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("{}"),
[]byte("{a,bb,ccc}"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `TIME receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 TIME, v2 TIME);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 17, 250, 171, 177, 0},
{0, 0, 0, 10, 57, 214, 4, 0},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`21:27:00`),
[]byte(`12:12:00`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `TIMETZ receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 TIMETZ, v2 TIMETZ);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 17, 250, 171, 177, 0, 0, 0, 112, 128},
{0, 0, 0, 10, 57, 214, 4, 0, 0, 0, 112, 128},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`21:27:00-08`),
[]byte(`12:12:00-08`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `TIMESTAMP receiving binary format`,
SetUpScript: []string{
"SET datestyle TO 'Postgres, MDY';",
"CREATE TABLE test (v1 TIMESTAMP, v2 TIMESTAMP);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 2, 62, 228, 207, 3, 128, 0},
{0, 2, 94, 46, 160, 114, 138, 136},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`Sun Jan 12 00:00:00 2020`),
[]byte(`Sat Feb 13 04:05:06.789 2021`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `TIMESTAMPTZ receiving binary format`,
SetUpScript: []string{
"SET datestyle TO 'Postgres, MDY';",
"CREATE TABLE test (v1 TIMESTAMPTZ, v2 TIMESTAMPTZ);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 2, 62, 235, 131, 160, 160, 0},
{0, 2, 94, 52, 126, 124, 6, 136},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(`Sun Jan 12 00:00:00 2020 PST`),
[]byte(`Sat Feb 13 03:05:06.789 2021 PST`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `UUID receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 UUID, v2 UUID);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{253, 171, 240, 61, 155, 33, 69, 49, 185, 0, 198, 246, 207, 248, 56, 108},
{7, 48, 121, 28, 192, 221, 73, 114, 158, 114, 17, 234, 217, 49, 122, 90},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("fdabf03d-9b21-4531-b900-c6f6cff8386c"),
[]byte("0730791c-c0dd-4972-9e72-11ead9317a5a"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `VARCHAR receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 VARCHAR, v2 VARCHAR(5));",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
[]byte(""),
[]byte(`a",c`),
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte(""),
[]byte(`a",c`),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
{
Name: `XID receiving binary format`,
SetUpScript: []string{
"CREATE TABLE test (v1 XID, v2 XID);",
},
Assertions: []WireScriptTestAssertion{
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name1",
Query: "INSERT INTO test VALUES ($1, $2);",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name1",
ParameterFormatCodes: []int16{1},
Parameters: [][]byte{
{0, 0, 0, 1},
{148, 8, 88, 129},
},
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.CommandComplete{CommandTag: []byte("INSERT 0 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
{
Send: []pgproto3.FrontendMessage{
&pgproto3.Parse{
Name: "stmt_name2",
Query: "SELECT * FROM test;",
},
&pgproto3.Bind{
DestinationPortal: "",
PreparedStatement: "stmt_name2",
ParameterFormatCodes: nil,
Parameters: nil,
ResultFormatCodes: []int16{0},
},
&pgproto3.Execute{},
&pgproto3.Close{
ObjectType: 'P',
},
&pgproto3.Sync{},
},
Receive: []pgproto3.BackendMessage{
&pgproto3.ParseComplete{},
&pgproto3.BindComplete{},
&pgproto3.DataRow{
Values: [][]byte{
[]byte("1"),
[]byte("2483574913"),
},
},
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
&pgproto3.CloseComplete{},
&pgproto3.ReadyForQuery{TxStatus: 'I'},
},
},
},
},
})
}
// IgnoreMessageParameters is used to ignore certain fields within a backend message, as they may not yet be implemented
// and therefore will return incorrect results (or variable results, such as with non-stable OIDs).
func IgnoreMessageParameters(message pgproto3.BackendMessage) pgproto3.BackendMessage {
switch message := message.(type) {
case *pgproto3.RowDescription:
for i := range message.Fields {
message.Fields[i].TableOID = 0
// User-defined types will have an OID outside the reserved range, so we set those to zero
if message.Fields[i].DataTypeOID > 16383 {
message.Fields[i].DataTypeOID = 0
}
}
return message
default:
return message
}
}
// WireScriptTest is used to test wire messages, ensuring that our wire protocol behaves as expected.
type WireScriptTest struct {
// Name of the script.
Name string
// The database to create and use. If not provided, then it defaults to "postgres".
Database string
// The SQL statements to execute as setup, in order. Results are not checked, but statements must not error.
SetUpScript []string
// The set of assertions to make after setup, in order
Assertions []WireScriptTestAssertion
// When using RunScripts, setting this on one (or more) tests causes RunWireScripts to ignore all tests that have
// this set to false (which is the default value). This allows a developer to easily "focus" on a specific test
// without having to comment out other tests, pull it into a different function, etc. In addition, CI ensures that
// this is false before passing, meaning this prevents the commented-out situation where the developer forgets to
// uncomment their code.
Focus bool
// Skip is used to completely skip a test
Skip bool
// When non-zero, this specific test will be run on an external server on the port specified. This is primarily to
// test against an actual Postgres server to ensure that results are correct. CI ensures that this is not set before
// passing, since this is intended for use on a developer's local machine only.
ExternalServerPort int
}
// WireScriptTestAssertion are the assertions upon which the script executes its main "testing" logic.
type WireScriptTestAssertion struct {
// These are sent as a batch to the server
Send []pgproto3.FrontendMessage
// These are the expected results that are received from the server, and must match in both contents and order
Receive []pgproto3.BackendMessage
// This functions the same as Focus on WireScriptTest, except that it applies to the assertion
Focus bool
// This is used to skip an assertion
Skip bool
}
// RawWireConnection is a connection that allows us to directly send and receive messages to a server.
type RawWireConnection struct {
frontend *pgproto3.Frontend
connection net.Conn
username string
password string
network string
timeout time.Duration
startup *pgproto3.StartupMessage
errChan chan error
}
// NewRawWireConnection returns a new RawWireConnection.
func NewRawWireConnection(t *testing.T, host string, port int, username string, password string, timeout time.Duration) *RawWireConnection {
network := net.JoinHostPort(host, fmt.Sprintf("%d", port))
connection, err := (&net.Dialer{}).Dial("tcp", network)
require.NoError(t, err)
if len(username) == 0 && len(password) == 0 {
username = "postgres"
password = "password"
}
c := &RawWireConnection{
frontend: pgproto3.NewFrontend(connection, connection),
connection: connection,
username: username,
password: password,
network: network,
timeout: timeout,
startup: nil,
errChan: make(chan error),
}
c.init(t)
return c
}
// Close closes the internal connection.
func (c *RawWireConnection) Close() {
// We don't close the error channel at all, which is fine since this is only used for these specific tests. Since we
// send to the channel from another thread, it's possible to receive a ping between the time that the connection is
// closed and the channel is closed. This would then cause a panic by trying to send on a closed channel. This could
// be architected around, but it's far easier to just never close it for tests.
_ = c.connection.Close()
}
// EmptyReceiveBuffer empties the buffer used by Receive. Returns an error if the buffer was not empty.
func (c *RawWireConnection) EmptyReceiveBuffer() error {
if c.frontend.ReadBufferLen() > 0 {
for c.frontend.ReadBufferLen() > 0 {
_, _ = c.frontend.Receive()
}
return errors.New("Doltgres sent additional messages after ReadyForQuery")
}
return nil
}
// Receive returns the next message from the backend.
func (c *RawWireConnection) Receive(t *testing.T) (pgproto3.BackendMessage, error) {
var message pgproto3.BackendMessage
go func() {
var err error
message, err = c.frontend.Receive()
c.errChan <- err
}()
return message, c.handleErrorChannel(t, false)
}
// Send sends the given messages over the wire. If an error is returned, then the connection has been closed, and a new
// one should be opened.
func (c *RawWireConnection) Send(t *testing.T, messages ...pgproto3.FrontendMessage) error {
if len(messages) == 0 {
return nil
}
hasMessage := false
for _, message := range messages {
if message == nil {
continue
}
hasMessage = true
if startupMessage, ok := message.(*pgproto3.StartupMessage); ok {
c.startup = startupMessage
}
c.frontend.Send(message)
}
if !hasMessage {
return nil
}
go func() {
c.errChan <- c.frontend.Flush()
}()
return c.handleErrorChannel(t, true)
}
// init handles the startup message, authentication, and initial messages from the server.
func (c *RawWireConnection) init(t *testing.T) {
err := c.Send(t, &pgproto3.StartupMessage{
ProtocolVersion: 196608,
Parameters: map[string]string{
"timezone": "PST8PDT",
"user": "postgres",
"database": "postgres",
"options": " -c intervalstyle=postgres_verbose",
"application_name": "pg_regress",
"client_encoding": "WIN1252",
"datestyle": "Postgres, MDY",
},
})
require.NoError(t, err)
postgresMessage, err := c.Receive(t)
require.NoError(t, err)
// First we'll check if authentication is disabled
if _, ok := postgresMessage.(*pgproto3.AuthenticationOk); ok {
for {
postgresMessage, err = c.Receive(t)
require.NoError(t, err)
switch response := postgresMessage.(type) {
case *pgproto3.BackendKeyData:
case *pgproto3.ErrorResponse:
t.Log(response.Message)
t.FailNow()
case *pgproto3.ParameterStatus:
case *pgproto3.ReadyForQuery:
return
default:
t.Logf("unknown StartupMessage response type: %T", response)
t.FailNow()
}
}
}
// If authentication is not disabled, then we'll do the SASL authentication routine (only one we support for now)
if saslInit, ok := postgresMessage.(*pgproto3.AuthenticationSASL); !ok {
t.Logf("unknown StartupMessage response type: %T", postgresMessage)
t.FailNow()
} else {
found := false
for _, authMech := range saslInit.AuthMechanisms {
switch authMech {
case "SCRAM-SHA-256":
found = true
}
}
if !found {
t.Logf("attempted SASL authentication but did not find a suitable mechanism: %v", saslInit.AuthMechanisms)
t.FailNow()
}
}
client, err := scram.SHA256.NewClient(c.username, c.password, "")
require.NoError(t, err)
conv := client.NewConversation()
saslInitialResponse, err := conv.Step("")
require.NoError(t, err)
err = c.Send(t, &pgproto3.SASLInitialResponse{
AuthMechanism: "SCRAM-SHA-256",
Data: []byte(saslInitialResponse),
})
require.NoError(t, err)
postgresMessage, err = c.Receive(t)
require.NoError(t, err)
saslContinue, ok := postgresMessage.(*pgproto3.AuthenticationSASLContinue)
if !ok {
t.Logf(`received "%T" but expected "AuthenticationSASLContinue"`, postgresMessage)
t.FailNow()
}
saslResponse, err := conv.Step(string(saslContinue.Data))
require.NoError(t, err)
err = c.Send(t, &pgproto3.SASLResponse{
Data: []byte(saslResponse),
})
require.NoError(t, err)
postgresMessage, err = c.Receive(t)
require.NoError(t, err)
saslFinal, ok := postgresMessage.(*pgproto3.AuthenticationSASLFinal)
if !ok {
t.Logf(`received "%T" but expected "AuthenticationSASLFinal"`, postgresMessage)
t.FailNow()
}
_, err = conv.Step(string(saslFinal.Data))
require.NoError(t, err)
postgresMessage, err = c.Receive(t)
require.NoError(t, err)
_, ok = postgresMessage.(*pgproto3.AuthenticationOk)
if !ok {
t.Logf(`received "%T" but expected "AuthenticationOk"`, postgresMessage)
t.FailNow()
}
for {
postgresMessage, err = c.Receive(t)
require.NoError(t, err)
switch response := postgresMessage.(type) {
case *pgproto3.BackendKeyData:
case *pgproto3.ErrorResponse:
t.Log(response.Message)
t.FailNow()
case *pgproto3.ParameterStatus:
case *pgproto3.ReadyForQuery:
return
default:
t.Logf("unknown StartupMessage response type: %T", response)
t.FailNow()
}
}
}
// handleErrorChannel handles errors while ensuring that stuck queries do not cause an infinite loop via a timeout.
func (c *RawWireConnection) handleErrorChannel(t *testing.T, isSend bool) error {
var err error
select {
case err = <-c.errChan:
case <-time.After(c.timeout):
if isSend {
err = errors.New("timeout during Send")
} else {
err = errors.New("timeout during Receive")
}
}
// On error, we must create a new connection since we cut the old one
if err != nil {
_ = c.connection.Close()
connection, nErr := (&net.Dialer{}).Dial("tcp", c.network)
if nErr != nil {
panic(fmt.Errorf("Unable to create a new connection:\n%s\n\nOriginal error:\n%s", nErr.Error(), err.Error()))
}
c.connection = connection
c.frontend = pgproto3.NewFrontend(connection, connection)
c.init(t)
}
return err
}
// RunWireScripts runs the given collection of scripts.
func RunWireScripts(t *testing.T, scripts []WireScriptTest) {
// First, we'll run through the scripts to check for the Focus variable. If it's true, then append it to the new slice.
focusScripts := make([]WireScriptTest, 0, len(scripts))
for _, script := range scripts {
if script.Focus {
// If this is running in GitHub Actions, then we'll panic, because someone forgot to disable it before committing
if _, ok := os.LookupEnv("GITHUB_ACTION"); ok {
panic(fmt.Sprintf("The wire script `%s` has Focus set to `true`. GitHub Actions requires that "+
"all tests are run, which Focus circumvents, leading to this error. Please disable Focus on "+
"all tests.", script.Name))
}
focusScripts = append(focusScripts, script)
}
if script.ExternalServerPort != 0 {
// Same as with Focus, we want to panic in a GitHub Action since this is only for local debugging
if _, ok := os.LookupEnv("GITHUB_ACTION"); ok {
panic(fmt.Sprintf("The wire script `%s` has ExternalServerPort set to `%d`. GitHub Actions "+
"requires that all tests are run against an in-memory Doltgres server, which ExternalServerPort "+
"circumvents, leading to this error. Please remove ExternalServerPort on all tests.",
script.Name, script.ExternalServerPort))
}
}
}
// If we have scripts with Focus set, then we replace the normal script slice with the new slice.
if len(focusScripts) > 0 {
scripts = focusScripts
}
for _, script := range scripts {
t.Run(script.Name, func(t *testing.T) {
if script.Skip {
t.Skip()
}
var rawConn *RawWireConnection
if script.ExternalServerPort == 0 {
scriptDatabase := script.Database
if len(scriptDatabase) == 0 {
scriptDatabase = "postgres"
}
port, err := sql.GetEmptyPort()
require.NoError(t, err)
ctx, conn, controller := CreateServerWithPort(t, scriptDatabase, port)
defer func() {
controller.Stop()
err := controller.WaitForStop()
require.NoError(t, err)
}()
for _, query := range script.SetUpScript {
_, err = conn.Exec(ctx, query)
require.NoError(t, err, "error running setup query: %s", query)
}
conn.Close(ctx)
rawConn = NewRawWireConnection(t, "localhost", port, "", "", 10*time.Second)
defer rawConn.Close()
} else {
rawConn = NewRawWireConnection(t, "localhost", script.ExternalServerPort, "", "", 10*time.Second)
defer rawConn.Close()
// Some tests create tables in their setup, so we do a very basic check to first drop those tables on
// the external server. While not rigorous, this at least lets us run (and rerun) most tests against an
// external server without explicitly rewriting the setup scripts. We also do this for created types.
var dropTables []string
var dropTypes []string
for _, query := range script.SetUpScript {
if idx := strings.Index(strings.ToLower(query), "create table "); idx != -1 {
dropTables = append(dropTables, query[idx+13:strings.Index(query, "(")])
}
if idx := strings.Index(strings.ToLower(query), "create type "); idx != -1 {
dropTypes = append(dropTypes, query[idx+12:idx+12+strings.Index(query[idx+12:], " ")])
}
}
if len(dropTypes) > 0 {
script.SetUpScript = append([]string{fmt.Sprintf(`DROP TYPE IF EXISTS %s;`, strings.Join(dropTypes, ", "))}, script.SetUpScript...)
}
if len(dropTables) > 0 {
script.SetUpScript = append([]string{fmt.Sprintf(`DROP TABLE IF EXISTS %s;`, strings.Join(dropTables, ", "))}, script.SetUpScript...)
}
for _, query := range script.SetUpScript {
err := rawConn.Send(t, &pgproto3.Query{String: query})
require.NoError(t, err)
ExternalSetupLoop:
for {
postgresMessage, err := rawConn.Receive(t)
require.NoError(t, err)
switch response := postgresMessage.(type) {
case *pgproto3.ErrorResponse:
t.Log(response.Message)
t.FailNow()
case *pgproto3.ReadyForQuery:
break ExternalSetupLoop
}
}
}
}
// With everything set up, we now check for Focus on the assertions
assertions := script.Assertions
// First, we'll run through the scripts to check for the Focus variable. If it's true, then append it to the new slice.
focusAssertions := make([]WireScriptTestAssertion, 0, len(script.Assertions))
for _, assertion := range script.Assertions {
if assertion.Focus {
// If this is running in GitHub Actions, then we'll panic, because someone forgot to disable it before committing
if _, ok := os.LookupEnv("GITHUB_ACTION"); ok {
panic("A wire assertion has Focus set to `true`. GitHub Actions requires that " +
"all non-skipped assertions are run, which Focus circumvents, leading to this error. " +
"Please disable Focus on all wire assertions.")
}
focusAssertions = append(focusAssertions, assertion)
}
}
// If we have assertions with Focus set, then we replace the original slice with the new slice.
if len(focusAssertions) > 0 {
assertions = focusAssertions
}
// Run the assertions
for assertionIdx, assertion := range assertions {
t.Run(fmt.Sprintf("%d", assertionIdx), func(t *testing.T) {
if assertion.Skip {
t.Skip("Skip has been set in the assertion")
}
err := rawConn.Send(t, assertion.Send...)
require.NoError(t, err)
for _, expectedMessage := range assertion.Receive {
actualMessage, err := rawConn.Receive(t)
require.NoError(t, err)
if !assert.Equal(t, IgnoreMessageParameters(expectedMessage), IgnoreMessageParameters(actualMessage)) {
// If the assertion fails, and it's a message that we don't expect, then we sync to the next
// ReadyForQuery message
if reflect.TypeOf(expectedMessage) != reflect.TypeOf(actualMessage) {
if _, ok := actualMessage.(*pgproto3.ReadyForQuery); !ok {
for {
actualMessage, err := rawConn.Receive(t)
require.NoError(t, err)
if _, ok = actualMessage.(*pgproto3.ReadyForQuery); ok {
return
}
}
}
}
}
}
// We then ensure that there are no other messages that were not accounted for by the assertion
// (which we consider an error)
_ = assert.NoError(t, rawConn.EmptyReceiveBuffer())
})
}
})
}
}