diff --git a/pkg/sql/pgwire/testdata/pgtest/char b/pkg/sql/pgwire/testdata/pgtest/char index ce115601c68c..ad1c6d226a7b 100644 --- a/pkg/sql/pgwire/testdata/pgtest/char +++ b/pkg/sql/pgwire/testdata/pgtest/char @@ -1,3 +1,17 @@ +# Prepare the environment. + +send +Query {"String": "DROP TABLE IF EXISTS a"} +---- + +until +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +# Start of test. + send Query {"String": "CREATE TABLE a (a INT PRIMARY KEY)"} ---- diff --git a/pkg/sql/pgwire/testdata/pgtest/enum b/pkg/sql/pgwire/testdata/pgtest/enum index 0bb4127e8f0b..6fa3886e8f0f 100644 --- a/pkg/sql/pgwire/testdata/pgtest/enum +++ b/pkg/sql/pgwire/testdata/pgtest/enum @@ -1,17 +1,28 @@ # This test verifies some of the pgwire encoding process for ENUMs. -send +# Prepare the environment. +send noncrdb_only +Query {"String": "DROP TYPE IF EXISTS te"} +---- + +until noncrdb_only ignore=NoticeResponse +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"DROP TYPE"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +send crdb_only Query {"String": "SET experimental_enable_enums=true;"} ---- -until +until crdb_only ReadyForQuery ---- {"Type":"CommandComplete","CommandTag":"SET"} {"Type":"ReadyForQuery","TxStatus":"I"} send -Query {"String": "CREATE TYPE t AS ENUM ('hi', 'hello')"} +Query {"String": "CREATE TYPE te AS ENUM ('hi', 'hello')"} ---- until @@ -22,17 +33,27 @@ ReadyForQuery # Use the enum now. send -Query {"String": "SELECT 'hi'::t"} +Query {"String": "SELECT 'hi'::te"} +---- + +# PostgreSQL uses float4 under the hood. +until ignore_type_oids noncrdb_only +RowDescription ---- +{"Type":"RowDescription","Fields":[{"Name":"te","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":0,"DataTypeSize":4,"TypeModifier":-1,"Format":0}]} # Note that this is slightly different than Postgres -- in Postgres the # DataTypeSize for an enum is 4, as floats are used to represent enums # internally (4 bytes). Since our encodings are variable size, we report # the DataTypeSize to be -1, which is the variable length size. +until ignore_type_oids crdb_only +RowDescription +---- +{"Type":"RowDescription","Fields":[{"Name":"te","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":0,"DataTypeSize":-1,"TypeModifier":-1,"Format":0}]} + until ReadyForQuery ---- -{"Type":"RowDescription","Fields":[{"Name":"t","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":100052,"DataTypeSize":-1,"TypeModifier":-1,"Format":0}]} {"Type":"DataRow","Values":[{"text":"hi"}]} {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} diff --git a/pkg/sql/pgwire/testdata/pgtest/int_size b/pkg/sql/pgwire/testdata/pgtest/int_size index dc88200d69ff..b1f4b186b822 100644 --- a/pkg/sql/pgwire/testdata/pgtest/int_size +++ b/pkg/sql/pgwire/testdata/pgtest/int_size @@ -2,12 +2,27 @@ # The output can be a little hard to read but the important part is the DataTypeOIDs. # OID 20 is INT8, OID 23 is INT4. -# By default, int == int8. +# Clean up the environment. send +Query {"String": "DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2"} +---- + +until ignore=NoticeResponse +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +# Start of test. + + +# By default, int == int8. +send crdb_only Query {"String": "SELECT 1::int, 2::int4, 3::int8"} ---- -until +until crdb_only ReadyForQuery ---- {"Type":"RowDescription","Fields":[{"Name":"int8","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"int4","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"int8","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} @@ -16,21 +31,21 @@ ReadyForQuery {"Type":"ReadyForQuery","TxStatus":"I"} # Same results when selecting from a table. -send +send crdb_only Query {"String": "CREATE TABLE t1 (a int, b int4, c int8)"} ---- -until +until crdb_only ReadyForQuery ---- {"Type":"CommandComplete","CommandTag":"CREATE TABLE"} {"Type":"ReadyForQuery","TxStatus":"I"} -send +send crdb_only Query {"String": "SELECT * FROM t1"} ---- -until +until crdb_only ReadyForQuery ---- {"Type":"RowDescription","Fields":[{"Name":"a","TableOID":52,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"b","TableOID":52,"TableAttributeNumber":2,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"c","TableOID":52,"TableAttributeNumber":3,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} @@ -38,22 +53,23 @@ ReadyForQuery {"Type":"ReadyForQuery","TxStatus":"I"} # Now change the default_int_size setting. -send +send crdb_only Query {"String": "SET default_int_size=4"} ---- -until +until crdb_only ReadyForQuery ---- {"Type":"CommandComplete","CommandTag":"SET"} {"Type":"ReadyForQuery","TxStatus":"I"} # The setting doesn't affect explicit casts, only table definitions. -send +# (So in CockroachdB ::int is still ::int8, whereas it's ::int4 in postgres.) +send crdb_only Query {"String": "SELECT 1::int, 2::int4, 3::int8"} ---- -until +until crdb_only ReadyForQuery ---- {"Type":"RowDescription","Fields":[{"Name":"int8","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"int4","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"int8","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} @@ -61,6 +77,10 @@ ReadyForQuery {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} +## Everything after this point should be the same between CockroachDB +## and PostgreSQL. + + # Create a new table with the new setting. send Query {"String": "CREATE TABLE t2 (a integer, b int4, c int8)"} @@ -77,19 +97,19 @@ send Query {"String": "SELECT * FROM t2"} ---- -until +until ignore_table_oids ReadyForQuery ---- -{"Type":"RowDescription","Fields":[{"Name":"a","TableOID":53,"TableAttributeNumber":1,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"b","TableOID":53,"TableAttributeNumber":2,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"c","TableOID":53,"TableAttributeNumber":3,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} +{"Type":"RowDescription","Fields":[{"Name":"a","TableOID":0,"TableAttributeNumber":1,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"b","TableOID":0,"TableAttributeNumber":2,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"c","TableOID":0,"TableAttributeNumber":3,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} {"Type":"CommandComplete","CommandTag":"SELECT 0"} {"Type":"ReadyForQuery","TxStatus":"I"} # t1 is unchanged. It was created under the old configuration so its int column is int8. -send +send crdb_only Query {"String": "SELECT * FROM t1"} ---- -until +until crdb_only ReadyForQuery ---- {"Type":"RowDescription","Fields":[{"Name":"a","TableOID":52,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"b","TableOID":52,"TableAttributeNumber":2,"DataTypeOID":23,"DataTypeSize":4,"TypeModifier":-1,"Format":0},{"Name":"c","TableOID":52,"TableAttributeNumber":3,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} diff --git a/pkg/sql/pgwire/testdata/pgtest/notice b/pkg/sql/pgwire/testdata/pgtest/notice index a52ff5a03ccb..0f9627bfe588 100644 --- a/pkg/sql/pgwire/testdata/pgtest/notice +++ b/pkg/sql/pgwire/testdata/pgtest/notice @@ -1,65 +1,92 @@ # Test notices work as expected by creating a VIEW on a TEMP TABLE. + +# Prepare the environment. + send -Parse {"Query": "CREATE TABLE t(x INT, y INT, INDEX (x), INDEX (y))"} -Bind -Execute -Sync +Query {"String": "DROP TABLE IF EXISTS t CASCADE"} +---- + +until ignore=NoticeResponse +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +# Start of test. + +send +Query {"String": "CREATE TABLE t(x INT, y INT)"} ---- until ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} {"Type":"CommandComplete","CommandTag":"CREATE TABLE"} {"Type":"ReadyForQuery","TxStatus":"I"} +send +Query {"String": "CREATE INDEX t_x_idx ON t(x)"} +---- +until +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"CREATE INDEX"} +{"Type":"ReadyForQuery","TxStatus":"I"} send -Parse {"Query": "DROP INDEX t@t_x_idx"} -Bind -Execute -Sync +Query {"String": "CREATE INDEX t_y_idx ON t(y)"} ---- until ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} +{"Type":"CommandComplete","CommandTag":"CREATE INDEX"} +{"Type":"ReadyForQuery","TxStatus":"I"} + + +# Check that crdb reports a notice upon drop index. + +send +Query {"String": "DROP INDEX t_x_idx"} +---- + +until crdb_only +CommandComplete +---- {"Severity":"NOTICE","Code":"00000","Message":"the data for dropped indexes is reclaimed asynchronously","Detail":"","Hint":"The reclamation delay can be customized in the zone configuration for the table.","Position":0,"InternalPosition":0,"InternalQuery":"","Where":"","SchemaName":"","TableName":"","ColumnName":"","DataTypeName":"","ConstraintName":"","File":"drop_index.go","Line":500,"Routine":"dropIndexByName","UnknownFields":null} {"Type":"CommandComplete","CommandTag":"DROP INDEX"} + +until noncrdb_only +CommandComplete +---- +{"Type":"CommandComplete","CommandTag":"DROP INDEX"} + +until +ReadyForQuery +---- {"Type":"ReadyForQuery","TxStatus":"I"} # Disable notices and assert now it is not sent. -send -Parse {"Query": "SET CLUSTER SETTING sql.notices.enabled = false"} -Bind -Execute -Sync +send crdb_only +Query {"String": "SET CLUSTER SETTING sql.notices.enabled = false"} ---- -until +until crdb_only ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} {"Type":"CommandComplete","CommandTag":"SET CLUSTER SETTING"} {"Type":"ReadyForQuery","TxStatus":"I"} +# Check that the notice is not printed any more. + send -Parse {"Query": "DROP INDEX t@t_y_idx"} -Bind -Execute -Sync +Query {"String": "DROP INDEX t_y_idx"} ---- until ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} {"Type":"CommandComplete","CommandTag":"DROP INDEX"} {"Type":"ReadyForQuery","TxStatus":"I"} diff --git a/pkg/sql/pgwire/testdata/pgtest/param_status b/pkg/sql/pgwire/testdata/pgtest/param_status index c65f0dad05e7..b017a62a24dc 100644 --- a/pkg/sql/pgwire/testdata/pgtest/param_status +++ b/pkg/sql/pgwire/testdata/pgtest/param_status @@ -1,73 +1,70 @@ # Change the application name. send -Parse {"Query": "SET application_name = 'pgtest'"} -Bind -Execute -Sync +Query {"String": "SET application_name = 'pgtest'"} ---- until ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} {"Type":"ParameterStatus","Name":"application_name","Value":"pgtest"} {"Type":"CommandComplete","CommandTag":"SET"} {"Type":"ReadyForQuery","TxStatus":"I"} # Change the time zone using an offset. -# TODO(#42404): postgres has a different output. This is what we have right now -# as code, but we need to dig into what/why we use this format in param status. -# postgres: {"Type":"ParameterStatus","Name":"TimeZone","Value":"\u003c+06\u003e-06"} send -Parse {"Query": "SET TIME ZONE +6"} -Bind -Execute -Sync +Query {"String": "SET TIME ZONE +6"} ---- +until crdb_only +ParameterStatus +---- +{"Type":"ParameterStatus","Name":"TimeZone","Value":"6"} + + +# TODO(#42404): postgres has a different output. This is what we have right now +# as code, but we need to dig into what/why we use this format in param status. +until noncrdb_only +ParameterStatus +---- +{"Type":"ParameterStatus","Name":"TimeZone","Value":"\u003c+06\u003e-06"} + until ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} -{"Type":"ParameterStatus","Name":"TimeZone","Value":"6"} {"Type":"CommandComplete","CommandTag":"SET"} {"Type":"ReadyForQuery","TxStatus":"I"} send -Parse {"Query": "SET TIME ZONE -11.5"} -Bind -Execute -Sync +Query {"String": "SET TIME ZONE -11.5"} +---- + +until crdb_only +ParameterStatus ---- +{"Type":"ParameterStatus","Name":"TimeZone","Value":"-11.5"} + +until noncrdb_only +ParameterStatus +---- +{"Type":"ParameterStatus","Name":"TimeZone","Value":"\u003c-11:30\u003e+11:30"} -# postgres: {"Type":"ParameterStatus","Name":"TimeZone","Value":"\u003c-11:30\u003e+11:30"} until ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} -{"Type":"ParameterStatus","Name":"TimeZone","Value":"-11.5"} {"Type":"CommandComplete","CommandTag":"SET"} {"Type":"ReadyForQuery","TxStatus":"I"} # Change the time zone using a real string. send -Parse {"Query": "SET TIME ZONE 'America/New_York'"} -Bind -Execute -Sync +Query {"String": "SET TIME ZONE 'America/New_York'"} ---- until ReadyForQuery ---- -{"Type":"ParseComplete"} -{"Type":"BindComplete"} {"Type":"ParameterStatus","Name":"TimeZone","Value":"America/New_York"} {"Type":"CommandComplete","CommandTag":"SET"} {"Type":"ReadyForQuery","TxStatus":"I"} diff --git a/pkg/sql/pgwire/testdata/pgtest/portals_crbugs b/pkg/sql/pgwire/testdata/pgtest/portals_crbugs index 0068bdb225f8..245d84045d5e 100644 --- a/pkg/sql/pgwire/testdata/pgtest/portals_crbugs +++ b/pkg/sql/pgwire/testdata/pgtest/portals_crbugs @@ -2,6 +2,9 @@ # handling. That is, the -rewrite flag, when used with Postgres, will # produce different results than Cockroach. +only crdb +---- + # More behavior that differs from postgres. Try executing a new query # when a portal is suspended. Cockroach errors. diff --git a/pkg/sql/pgwire/testdata/pgtest/row_description b/pkg/sql/pgwire/testdata/pgtest/row_description index 355ec47017ce..703ff1031945 100644 --- a/pkg/sql/pgwire/testdata/pgtest/row_description +++ b/pkg/sql/pgwire/testdata/pgtest/row_description @@ -2,8 +2,24 @@ # RowDescription message of the wire protocol. The IDs should remain consistent # even when joining tables or when using views. +# Prepare the environment. send -Query {"String": "CREATE TABLE tab1 (a int primary key, b int)"} +Query {"String": "DROP VIEW IF EXISTS v; DROP TABLE IF EXISTS tab3; DROP TABLE IF EXISTS tab2; DROP TABLE IF EXISTS tab1"} +---- + +until ignore=NoticeResponse +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"DROP VIEW"} +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +# Start of test. + +send +Query {"String": "CREATE TABLE tab1 (a INT8 PRIMARY KEY, b INT8)"} ---- until @@ -13,7 +29,7 @@ ReadyForQuery {"Type":"ReadyForQuery","TxStatus":"I"} send -Query {"String": "CREATE TABLE tab2 (c int primary key, tab1_a int REFERENCES tab1(a))"} +Query {"String": "CREATE TABLE tab2 (c INT8 PRIMARY KEY, tab1_a INT8 REFERENCES tab1(a))"} ---- until @@ -56,10 +72,10 @@ send Query {"String": "SELECT a FROM tab1"} ---- -until +until ignore_table_oids ReadyForQuery ---- -{"Type":"RowDescription","Fields":[{"Name":"a","TableOID":52,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} +{"Type":"RowDescription","Fields":[{"Name":"a","TableOID":0,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} {"Type":"DataRow","Values":[{"text":"1"}]} {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} @@ -68,10 +84,10 @@ send Query {"String": "SELECT tab1.a, tab2.c FROM tab1 JOIN tab2 ON tab1.a = tab2.tab1_a"} ---- -until +until ignore_table_oids ReadyForQuery ---- -{"Type":"RowDescription","Fields":[{"Name":"a","TableOID":52,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"c","TableOID":53,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} +{"Type":"RowDescription","Fields":[{"Name":"a","TableOID":0,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"c","TableOID":0,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} {"Type":"DataRow","Values":[{"text":"1"},{"text":"4"}]} {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} @@ -80,16 +96,16 @@ send Query {"String": "SELECT * FROM v WHERE v1 = 1"} ---- -until +until ignore_table_oids ReadyForQuery ---- -{"Type":"RowDescription","Fields":[{"Name":"v1","TableOID":52,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"v2","TableOID":53,"TableAttributeNumber":2,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} +{"Type":"RowDescription","Fields":[{"Name":"v1","TableOID":0,"TableAttributeNumber":1,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0},{"Name":"v2","TableOID":0,"TableAttributeNumber":2,"DataTypeOID":20,"DataTypeSize":8,"TypeModifier":-1,"Format":0}]} {"Type":"DataRow","Values":[{"text":"1"},{"text":"1"}]} {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} send -Query {"String": "CREATE TABLE tab3 (a int primary key, b char(8))"} +Query {"String": "CREATE TABLE tab3 (a INT8 PRIMARY KEY, b CHAR(8))"} ---- until @@ -112,11 +128,27 @@ send Query {"String": "SELECT b FROM tab3"} ---- +until ignore_table_oids +RowDescription +---- +{"Type":"RowDescription","Fields":[{"Name":"b","TableOID":0,"TableAttributeNumber":2,"DataTypeOID":1042,"DataTypeSize":-1,"TypeModifier":12,"Format":0}]} + +# The following discrepancy is a bug. +# See: https://github.com/cockroachdb/cockroach/issues/49639 + +until noncrdb_only +DataRow +---- +{"Type":"DataRow","Values":[{"text":"hello "}]} + +until crdb_only +DataRow +---- +{"Type":"DataRow","Values":[{"text":"hello"}]} + until ReadyForQuery ---- -{"Type":"RowDescription","Fields":[{"Name":"b","TableOID":55,"TableAttributeNumber":2,"DataTypeOID":1042,"DataTypeSize":-1,"TypeModifier":12,"Format":0}]} -{"Type":"DataRow","Values":[{"text":"hello"}]} {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} @@ -130,11 +162,38 @@ Sync ---- until -ReadyForQuery +BindComplete ---- {"Type":"ParseComplete"} {"Type":"BindComplete"} + +# The following discrepancy is another bug. +# See: https://github.com/cockroachdb/cockroach/issues/49640 +until noncrdb_only ignore_table_oids +RowDescription +---- +{"Type":"RowDescription","Fields":[{"Name":"b","TableOID":0,"TableAttributeNumber":2,"DataTypeOID":1042,"DataTypeSize":-1,"TypeModifier":12,"Format":0}]} + +until crdb_only ignore_table_oids +RowDescription +---- {"Type":"RowDescription","Fields":[{"Name":"b","TableOID":0,"TableAttributeNumber":0,"DataTypeOID":1042,"DataTypeSize":-1,"TypeModifier":12,"Format":0}]} + +# The following discrepancy is the first bug above. +# See: https://github.com/cockroachdb/cockroach/issues/49639 + +until noncrdb_only +DataRow +---- +{"Type":"DataRow","Values":[{"text":"hello "}]} + +until crdb_only +DataRow +---- {"Type":"DataRow","Values":[{"text":"hello"}]} + +until +ReadyForQuery +---- {"Type":"CommandComplete","CommandTag":"SELECT 1"} {"Type":"ReadyForQuery","TxStatus":"I"} diff --git a/pkg/testutils/pgtest/datadriven.go b/pkg/testutils/pgtest/datadriven.go index 0738989750f4..2321dc17428f 100644 --- a/pkg/testutils/pgtest/datadriven.go +++ b/pkg/testutils/pgtest/datadriven.go @@ -58,6 +58,10 @@ func WalkWithNewServer( // // "receive": Like "until", but only output matching messages instead of all // messages. +// +// If the argument crdb_only is given and the server is non-crdb (e.g. +// posrgres), then the exchange is skipped. With noncrdb_only, the inverse +// happens. func RunTest(t *testing.T, path, addr, user string) { p, err := NewPGTest(context.Background(), addr, user) if err != nil { @@ -65,7 +69,20 @@ func RunTest(t *testing.T, path, addr, user string) { } datadriven.RunTest(t, path, func(t *testing.T, d *datadriven.TestData) string { switch d.Cmd { + case "only": + if d.HasArg("crdb") && !p.isCockroachDB { + t.Skip("only crdb") + } + if d.HasArg("noncrdb") && p.isCockroachDB { + t.Skip("only non-crdb") + } + return d.Expected + case "send": + if (d.HasArg("crdb_only") && !p.isCockroachDB) || + (d.HasArg("noncrdb_only") && p.isCockroachDB) { + return d.Expected + } for _, line := range strings.Split(d.Input, "\n") { sp := strings.SplitN(line, " ", 2) msg := toMessage(sp[0]) @@ -80,6 +97,10 @@ func RunTest(t *testing.T, path, addr, user string) { } return "" case "receive": + if (d.HasArg("crdb_only") && !p.isCockroachDB) || + (d.HasArg("noncrdb_only") && p.isCockroachDB) { + return d.Expected + } until := parseMessages(d.Input) msgs, err := p.Receive(hasKeepErrMsg(d), until...) if err != nil { @@ -87,6 +108,10 @@ func RunTest(t *testing.T, path, addr, user string) { } return msgsToJSONWithIgnore(msgs, d) case "until": + if (d.HasArg("crdb_only") && !p.isCockroachDB) || + (d.HasArg("noncrdb_only") && p.isCockroachDB) { + return d.Expected + } until := parseMessages(d.Input) msgs, err := p.Until(hasKeepErrMsg(d), until...) if err != nil { @@ -126,6 +151,24 @@ func msgsToJSONWithIgnore(msgs []pgproto3.BackendMessage, args *datadriven.TestD for _, arg := range args.CmdArgs { switch arg.Key { case "keepErrMessage": + case "crdb_only": + case "noncrdb_only": + case "ignore_table_oids": + for _, msg := range msgs { + if m, ok := msg.(*pgproto3.RowDescription); ok { + for i := range m.Fields { + m.Fields[i].TableOID = 0 + } + } + } + case "ignore_type_oids": + for _, msg := range msgs { + if m, ok := msg.(*pgproto3.RowDescription); ok { + for i := range m.Fields { + m.Fields[i].DataTypeOID = 0 + } + } + } case "ignore": for _, typ := range arg.Vals { ignore[fmt.Sprintf("*pgproto3.%s", typ)] = true @@ -191,6 +234,14 @@ func toMessage(typ string) interface{} { return &pgproto3.ReadyForQuery{} case "Sync": return &pgproto3.Sync{} + case "ParameterStatus": + return &pgproto3.ParameterStatus{} + case "BindComplete": + return &pgproto3.BindComplete{} + case "ParseComplete": + return &pgproto3.ParseComplete{} + case "RowDescription": + return &pgproto3.RowDescription{} default: panic(fmt.Errorf("unknown type %q", typ)) } diff --git a/pkg/testutils/pgtest/pgtest.go b/pkg/testutils/pgtest/pgtest.go index e178c494f289..3de68787d3ab 100644 --- a/pkg/testutils/pgtest/pgtest.go +++ b/pkg/testutils/pgtest/pgtest.go @@ -24,8 +24,9 @@ import ( // PGTest can be used to send and receive arbitrary pgwire messages on // Postgres-compatible servers. type PGTest struct { - fe *pgproto3.Frontend - conn net.Conn + fe *pgproto3.Frontend + conn net.Conn + isCockroachDB bool } // NewPGTest connects to a Postgres server at addr with username user. @@ -62,7 +63,14 @@ func NewPGTest(ctx context.Context, addr, user string) (*PGTest, error) { fe: fe, conn: conn, } - _, err = p.Until(false /* keepErrMsg */, &pgproto3.ReadyForQuery{}) + msgs, err := p.Until(false /* keepErrMsg */, &pgproto3.ReadyForQuery{}) + foundCrdb := false + for _, msg := range msgs { + if s, ok := msg.(*pgproto3.ParameterStatus); ok && s.Name == "crdb_version" { + foundCrdb = true + } + } + p.isCockroachDB = foundCrdb success = err == nil return p, err }