652 lines
18 KiB
Go
652 lines
18 KiB
Go
// Copyright 2023 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 (
|
|
"testing"
|
|
|
|
"github.com/dolthub/go-mysql-server/sql"
|
|
"github.com/jackc/pgx/v5/pgproto3"
|
|
|
|
"github.com/dolthub/doltgresql/core/id"
|
|
pgtypes "github.com/dolthub/doltgresql/server/types"
|
|
)
|
|
|
|
func TestIssues(t *testing.T) {
|
|
RunScripts(t, []ScriptTest{
|
|
{
|
|
Name: "Issue #25",
|
|
SetUpScript: []string{
|
|
"create table tbl (pk int);",
|
|
"insert into tbl values (1);",
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: `select dolt_add(".");`,
|
|
ExpectedErr: "could not be found in any table in scope",
|
|
},
|
|
{
|
|
Query: `select dolt_add('.');`,
|
|
Expected: []sql.Row{{"{0}"}},
|
|
},
|
|
{
|
|
Query: `select dolt_commit("-m", "look ma");`,
|
|
ExpectedErr: "could not be found in any table in scope",
|
|
},
|
|
{
|
|
Query: `select length(dolt_commit('-m', 'look ma')::text);`,
|
|
Expected: []sql.Row{{34}},
|
|
},
|
|
{
|
|
Query: `select dolt_branch("br1");`,
|
|
ExpectedErr: "could not be found in any table in scope",
|
|
},
|
|
{
|
|
Query: `select dolt_branch('br1');`,
|
|
Expected: []sql.Row{{"{0}"}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2030",
|
|
SetUpScript: []string{
|
|
`CREATE TABLE sub_entities (
|
|
project_id VARCHAR(256) NOT NULL,
|
|
entity_id VARCHAR(256) NOT NULL,
|
|
id VARCHAR(256) NOT NULL,
|
|
name VARCHAR(256) NOT NULL,
|
|
PRIMARY KEY (project_id, entity_id, id)
|
|
);
|
|
`,
|
|
`
|
|
CREATE TABLE entities (
|
|
project_id VARCHAR(256) NOT NULL,
|
|
id VARCHAR(256) NOT NULL,
|
|
name VARCHAR(256) NOT NULL,
|
|
default_sub_entity_id VARCHAR(256),
|
|
PRIMARY KEY (project_id, id)
|
|
);
|
|
`,
|
|
`
|
|
CREATE TABLE conversations (
|
|
id VARCHAR(256) NOT NULL,
|
|
tenant_id VARCHAR(256) NOT NULL,
|
|
project_id VARCHAR(256) NOT NULL,
|
|
active_sub_agent_id VARCHAR(256) NOT NULL,
|
|
PRIMARY KEY (tenant_id, project_id, id)
|
|
);
|
|
`,
|
|
`INSERT INTO sub_entities (project_id, entity_id, id, name) VALUES
|
|
('projectA', 'entityA', 'subA1', 'Sub-Entity A1'),
|
|
('projectA', 'entityB', 'subB1', 'Sub-Entity B1');
|
|
`,
|
|
`INSERT INTO entities (project_id, id, name, default_sub_entity_id) VALUES
|
|
('projectA', 'entityA', 'Entity A', 'subA1'),
|
|
('projectA', 'entityB', 'Entity B', 'subB1');
|
|
`,
|
|
`INSERT INTO conversations (tenant_id, project_id, id, active_sub_agent_id) VALUES
|
|
('tenant1', 'projectA', 'conv1', 'subA1'),
|
|
('tenant1', 'projectA', 'conv2', 'subB1');
|
|
`,
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: `select
|
|
"entities"."project_id",
|
|
"entities"."id",
|
|
"entities"."name",
|
|
"entities"."default_sub_entity_id",
|
|
"entities_defaultSubEntity"."data" as "defaultSubEntity"
|
|
from "entities" "entities"
|
|
left join lateral (
|
|
select json_build_array(
|
|
"entities_defaultSubEntity"."project_id",
|
|
"entities_defaultSubEntity"."entity_id",
|
|
"entities_defaultSubEntity"."id",
|
|
"entities_defaultSubEntity"."name"
|
|
) as "data"
|
|
from (
|
|
select * from "sub_entities" "entities_defaultSubEntity"
|
|
where "entities_defaultSubEntity"."id" = "entities"."default_sub_entity_id"
|
|
limit $1
|
|
) "entities_defaultSubEntity"
|
|
) "entities_defaultSubEntity" on true
|
|
where ("entities"."project_id" = $2 and "entities"."id" = $3)
|
|
limit $4`,
|
|
BindVars: []any{
|
|
int64(1),
|
|
"projectA",
|
|
"entityA",
|
|
int64(1),
|
|
},
|
|
Expected: []sql.Row{
|
|
{
|
|
"projectA",
|
|
"entityA",
|
|
"Entity A",
|
|
"subA1",
|
|
`["projectA", "entityA", "subA1", "Sub-Entity A1"]`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Query: `select
|
|
"entities"."project_id",
|
|
"entities"."id",
|
|
"entities"."name",
|
|
"entities"."default_sub_entity_id",
|
|
"entities_defaultSubEntity"."data" as "defaultSubEntity"
|
|
from "entities" "entities"
|
|
left join lateral (
|
|
select json_build_array(
|
|
"entities_defaultSubEntity"."project_id",
|
|
"entities_defaultSubEntity"."entity_id",
|
|
"entities_defaultSubEntity"."id",
|
|
"entities_defaultSubEntity"."name"
|
|
) as "data"
|
|
from (
|
|
select * from "sub_entities" "entities_defaultSubEntity"
|
|
where "entities_defaultSubEntity"."id" = "entities"."default_sub_entity_id"
|
|
limit 1
|
|
) "entities_defaultSubEntity"
|
|
) "entities_defaultSubEntity" on true
|
|
where ("entities"."project_id" = 'projectA' and "entities"."id" = 'entityA')
|
|
limit 1`,
|
|
Expected: []sql.Row{
|
|
{
|
|
"projectA",
|
|
"entityA",
|
|
"Entity A",
|
|
"subA1",
|
|
`["projectA", "entityA", "subA1", "Sub-Entity A1"]`,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2049",
|
|
SetUpScript: []string{
|
|
`CREATE TABLE jsonb_test (id VARCHAR(256) NOT NULL PRIMARY KEY, "jsonbColumn" JSONB);`,
|
|
`INSERT INTO jsonb_test VALUES ('test', '{"test": "value\n"}');`,
|
|
`INSERT INTO jsonb_test VALUES ('test2', '{"test": "value\t"}');`,
|
|
`INSERT INTO jsonb_test VALUES ('test3', '{"test": "value\r"}');`,
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: "SELECT * FROM jsonb_test;",
|
|
// The pgx library incorrectly reinterprets our JSON value by replacing the individual newline
|
|
// characters (ASCII 92,110) with the actual newline character (ASCII 10), which is incorrect for us.
|
|
// Therefore, we have to use the raw returned values. To make it more clear, we aren't using a raw
|
|
// string literal and instead escaping the characters in the byte slice. We also test other escape
|
|
// characters that are replaced.
|
|
ExpectedRaw: [][][]byte{
|
|
{[]byte("test"), []byte("{\"test\": \"value\\n\"}")},
|
|
{[]byte("test2"), []byte("{\"test\": \"value\\t\"}")},
|
|
{[]byte("test3"), []byte("{\"test\": \"value\\r\"}")},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2197 Part 1",
|
|
SetUpScript: []string{
|
|
`CREATE TABLE t1 (a INT, b VARCHAR(3));`,
|
|
`CREATE TABLE t2(id SERIAL, t1 t1);`,
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: `INSERT INTO t2(t1) VALUES (ROW(1, 'abc'));`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT * FROM t2;`,
|
|
Expected: []sql.Row{{1, "(1,abc)"}},
|
|
},
|
|
{
|
|
Query: `INSERT INTO t2(t1) VALUES (ROW('a', 'def'));`,
|
|
ExpectedErr: "invalid input syntax for type",
|
|
},
|
|
{
|
|
Query: `INSERT INTO t2(t1) VALUES (ROW(true, 'def'));`,
|
|
ExpectedErr: "Cannot cast type",
|
|
},
|
|
{
|
|
Query: `INSERT INTO t2(t1) VALUES (ROW(2, 'def', 'ghi'));`,
|
|
ExpectedErr: "cannot cast type",
|
|
},
|
|
{
|
|
Query: `INSERT INTO t2(t1) VALUES (ROW(2));`,
|
|
ExpectedErr: "cannot cast type",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2197 Part 2",
|
|
SetUpScript: []string{
|
|
`CREATE TABLE t1a (a INT4, b VARCHAR(3));`,
|
|
`CREATE TABLE t1b (a INT4 NOT NULL, b VARCHAR(3) NOT NULL);`,
|
|
`CREATE TABLE t2 (id SERIAL, t1a t1a, t1b t1b);`,
|
|
`INSERT INTO t2 (t1a) VALUES (ROW(1, 'abc'));`,
|
|
`INSERT INTO t2 (t1b) VALUES (ROW(1, 'abc'));`,
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: `SELECT * FROM t2;`,
|
|
Expected: []sql.Row{
|
|
{1, "(1,abc)", nil},
|
|
{2, nil, "(1,abc)"},
|
|
},
|
|
},
|
|
{
|
|
Query: `ALTER TABLE t1a ADD COLUMN c VARCHAR(10);`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `ALTER TABLE t1b ADD COLUMN c VARCHAR(10) NOT NULL;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT * FROM t2 ORDER BY id;`,
|
|
Expected: []sql.Row{
|
|
{1, "(1,abc,)", nil},
|
|
{2, nil, "(1,abc,)"},
|
|
},
|
|
},
|
|
{
|
|
Query: `ALTER TABLE t1a DROP COLUMN b;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `ALTER TABLE t1b DROP COLUMN b;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT * FROM t2 ORDER BY id;`,
|
|
Expected: []sql.Row{
|
|
{1, "(1,)", nil},
|
|
{2, nil, "(1,)"},
|
|
},
|
|
},
|
|
{
|
|
Query: `INSERT INTO t1a VALUES (2, 'def');`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `INSERT INTO t1b VALUES (3, 'xyzzy');`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `INSERT INTO t2 (t1a) SELECT ROW(a,c)::t1a FROM t1a;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `INSERT INTO t2 (t1b) SELECT ROW(a,c)::t1b FROM t1b;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT * FROM t2 ORDER BY id;`,
|
|
Expected: []sql.Row{
|
|
{1, "(1,)", nil},
|
|
{2, nil, "(1,)"},
|
|
{3, "(2,def)", nil},
|
|
{4, nil, "(3,xyzzy)"},
|
|
},
|
|
},
|
|
{
|
|
Query: `SELECT ((t1a).@1), ((t1b).@2) FROM t2 ORDER BY id;`,
|
|
Expected: []sql.Row{
|
|
{1, nil},
|
|
{nil, nil},
|
|
{2, nil},
|
|
{nil, "xyzzy"},
|
|
},
|
|
},
|
|
{
|
|
Query: `UPDATE t2 SET t1a=ROW((t1a).a+100, (t1a).c)::t1a WHERE length(t1a::text) > 0;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `UPDATE t2 SET t1b=ROW((t1b).@1+100, (t1b).@2)::t1b WHERE length(t1b::text) > 0;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT * FROM t2 ORDER BY id;`,
|
|
Expected: []sql.Row{
|
|
{1, "(101,)", nil},
|
|
{2, nil, "(101,)"},
|
|
{3, "(102,def)", nil},
|
|
{4, nil, "(103,xyzzy)"},
|
|
},
|
|
},
|
|
{
|
|
Query: `SELECT (id).a FROM t2;`,
|
|
ExpectedErr: "column notation .a applied to type",
|
|
},
|
|
{
|
|
Query: `SELECT (t1a).g FROM t2;`,
|
|
ExpectedErr: `column "g" not found in data type`,
|
|
},
|
|
{
|
|
Query: `SELECT (t1a).@0 FROM t2;`,
|
|
ExpectedErr: "out of bounds",
|
|
},
|
|
{
|
|
Query: `SELECT (t1a).@3 FROM t2;`,
|
|
ExpectedErr: "out of bounds",
|
|
},
|
|
{
|
|
Query: `ALTER TABLE t1a ADD COLUMN d VARCHAR(10) DEFAULT 'abc';`,
|
|
ExpectedErr: `cannot alter table "t1a" because column "t2.t1a" uses its row type`,
|
|
},
|
|
{
|
|
Query: `ALTER TABLE t1a ADD COLUMN d VARCHAR(10);`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `ALTER TABLE t1a DROP COLUMN c;`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT * FROM t2 ORDER BY id;`,
|
|
Expected: []sql.Row{
|
|
{1, "(101,)", nil},
|
|
{2, nil, "(101,)"},
|
|
{3, "(102,)", nil},
|
|
{4, nil, "(103,xyzzy)"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2299",
|
|
SetUpScript: []string{
|
|
"CREATE TYPE team_role AS ENUM ('admin', 'editor', 'member');",
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: `CREATE TABLE users (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), role team_role NOT NULL DEFAULT 'member');`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `INSERT INTO users (role) VALUES (DEFAULT);`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT role FROM users;`,
|
|
Expected: []sql.Row{{"member"}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2307",
|
|
SetUpScript: []string{
|
|
"CREATE TABLE test (pk INT4);",
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: `SELECT EXISTS(SELECT 1 FROM pg_catalog.pg_tables WHERE tablename = 'test');`,
|
|
ExpectedColTypes: []id.Type{pgtypes.Bool.ID},
|
|
Expected: []sql.Row{{"t"}},
|
|
},
|
|
{
|
|
Query: `SELECT NOT EXISTS(SELECT 1 FROM pg_catalog.pg_tables WHERE tablename = 'test');`,
|
|
ExpectedColTypes: []id.Type{pgtypes.Bool.ID},
|
|
Expected: []sql.Row{{"f"}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2548",
|
|
SetUpScript: []string{
|
|
"CREATE TABLE test (pk INT4 PRIMARY KEY, v1 TIMESTAMP WITH TIME ZONE);",
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: `SET TimeZone = 'UTC-01:00';`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `INSERT INTO test VALUES (1, '2026-04-15 10:11:12');`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SET TimeZone = 'UTC-03:00';`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `INSERT INTO test VALUES (2, '2026-04-15 10:11:12');`,
|
|
Expected: []sql.Row{},
|
|
},
|
|
{
|
|
Query: `SELECT (SELECT v1 FROM test WHERE pk = 2) - (SELECT v1 FROM test WHERE pk = 1);`,
|
|
Expected: []sql.Row{{"-02:00:00"}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2604",
|
|
SetUpScript: []string{
|
|
"CREATE TABLE t (id INT PRIMARY KEY, a TEXT, b TEXT DEFAULT 'x');",
|
|
"CREATE UNIQUE INDEX idx_t_a ON t(a);",
|
|
"SELECT dolt_add('-A');",
|
|
"SELECT dolt_commit('-m', 'schema');",
|
|
"SELECT dolt_branch('f', 'main');",
|
|
"SELECT dolt_checkout('f');",
|
|
"INSERT INTO t (id, a) VALUES (1, 'feat');",
|
|
"SELECT dolt_add('-A');",
|
|
"SELECT dolt_commit('-m', 'feat');",
|
|
"SELECT dolt_checkout('main');",
|
|
"INSERT INTO t (id, a) VALUES (2, 'main');",
|
|
"SELECT dolt_add('-A');",
|
|
"SELECT dolt_commit('-m', 'main');",
|
|
"SELECT dolt_checkout('f');",
|
|
},
|
|
Assertions: []ScriptTestAssertion{
|
|
{
|
|
Query: "SELECT length(dolt_merge('main')::text) = 57;",
|
|
Expected: []sql.Row{{"t"}},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestIssuesWire(t *testing.T) {
|
|
RunWireScripts(t, []WireScriptTest{
|
|
{
|
|
Name: "Issue #2546",
|
|
Assertions: []WireScriptTestAssertion{
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Query{String: "SELECT 'foo';"},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.RowDescription{
|
|
Fields: []pgproto3.FieldDescription{
|
|
{
|
|
Name: []byte("?column?"),
|
|
TableOID: 0,
|
|
TableAttributeNumber: 0,
|
|
DataTypeOID: 25,
|
|
DataTypeSize: -1,
|
|
TypeModifier: -1,
|
|
Format: 0,
|
|
},
|
|
},
|
|
},
|
|
&pgproto3.DataRow{Values: [][]byte{[]byte("foo")}},
|
|
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "Issue #2557",
|
|
Assertions: []WireScriptTestAssertion{
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Parse{
|
|
Name: "stmt_name1",
|
|
Query: `SELECT '{"v":"a\\nb"}'::jsonb;`,
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.ParseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Bind{
|
|
PreparedStatement: "stmt_name1",
|
|
ResultFormatCodes: []int16{0},
|
|
},
|
|
&pgproto3.Execute{},
|
|
&pgproto3.Close{
|
|
ObjectType: 'P',
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.BindComplete{},
|
|
&pgproto3.DataRow{
|
|
Values: [][]byte{
|
|
[]byte(`{"v": "a\\nb"}`),
|
|
},
|
|
},
|
|
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
|
|
&pgproto3.CloseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Parse{
|
|
Name: "stmt_name2",
|
|
Query: `SELECT $${"v":"a\\nb"}$$::jsonb;`,
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.ParseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Bind{
|
|
PreparedStatement: "stmt_name2",
|
|
ResultFormatCodes: []int16{0},
|
|
},
|
|
&pgproto3.Execute{},
|
|
&pgproto3.Close{
|
|
ObjectType: 'P',
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.BindComplete{},
|
|
&pgproto3.DataRow{
|
|
Values: [][]byte{
|
|
[]byte(`{"v": "a\\nb"}`),
|
|
},
|
|
},
|
|
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
|
|
&pgproto3.CloseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Parse{
|
|
Name: "stmt_name3",
|
|
Query: `SELECT $${"v":"a\\\nb"}$$::jsonb;`,
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.ParseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Bind{
|
|
PreparedStatement: "stmt_name3",
|
|
ResultFormatCodes: []int16{0},
|
|
},
|
|
&pgproto3.Execute{},
|
|
&pgproto3.Close{
|
|
ObjectType: 'P',
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.BindComplete{},
|
|
&pgproto3.DataRow{
|
|
Values: [][]byte{
|
|
[]byte(`{"v": "a\\\nb"}`),
|
|
},
|
|
},
|
|
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
|
|
&pgproto3.CloseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Parse{
|
|
Name: "stmt_name4",
|
|
Query: `select json '{ "a": "dollar \\u0024 character" }' ->> 'a' as not_an_escape;`,
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.ParseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
{
|
|
Send: []pgproto3.FrontendMessage{
|
|
&pgproto3.Bind{
|
|
PreparedStatement: "stmt_name4",
|
|
ResultFormatCodes: []int16{0},
|
|
},
|
|
&pgproto3.Execute{},
|
|
&pgproto3.Close{
|
|
ObjectType: 'P',
|
|
},
|
|
&pgproto3.Sync{},
|
|
},
|
|
Receive: []pgproto3.BackendMessage{
|
|
&pgproto3.BindComplete{},
|
|
&pgproto3.DataRow{
|
|
Values: [][]byte{
|
|
[]byte(`dollar \u0024 character`),
|
|
},
|
|
},
|
|
&pgproto3.CommandComplete{CommandTag: []byte("SELECT 1")},
|
|
&pgproto3.CloseComplete{},
|
|
&pgproto3.ReadyForQuery{TxStatus: 'I'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
}
|