Skip to content

Commit 3ce6d75

Browse files
committed
Add failing test: batch scan corrupted in cache_statement mode
sendBatchExtendedWithDescription passes eqb.ResultFormats to SendQueryStatement by reference. The next Build call reuses the backing array (reset sets len=0, append overwrites), corrupting the stored format codes for earlier queries. The server sends binary data (Bind was encoded correctly), but the local scan plan uses the corrupted text format code. Introduced in v5.9.0 by c3a1750 ("pgx batch uses SendQueryStatement"), part of "Skip Describe Portal for cached prepared statements reducing network round trips". The previous SendQueryPrepared path sent Describe Portal, so the server's RowDescription provided correct format codes regardless of the stored slice contents. Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
1 parent b4d8e62 commit 3ce6d75

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

batch_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,3 +1267,35 @@ func ExampleConn_SendBatch() {
12671267
// 3
12681268
// 5
12691269
}
1270+
1271+
// TestSendBatchPreservesResultFormats verifies that each batched query retains
1272+
// its own result format codes. When the first query has a binary-preferred
1273+
// column (int4) and the second has all text columns, scanning the first
1274+
// query's int4 column must still work correctly.
1275+
func TestSendBatchPreservesResultFormats(t *testing.T) {
1276+
t.Parallel()
1277+
1278+
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
1279+
defer cancel()
1280+
1281+
pgxtest.RunWithQueryExecModes(ctx, t, defaultConnTestRunner, nil, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
1282+
batch := &pgx.Batch{}
1283+
batch.Queue("SELECT 1::int4")
1284+
batch.Queue("SELECT 'hello'::text")
1285+
1286+
br := conn.SendBatch(ctx, batch)
1287+
1288+
var n int32
1289+
err := br.QueryRow().Scan(&n)
1290+
require.NoError(t, err)
1291+
assert.Equal(t, int32(1), n)
1292+
1293+
var s string
1294+
err = br.QueryRow().Scan(&s)
1295+
require.NoError(t, err)
1296+
assert.Equal(t, "hello", s)
1297+
1298+
err = br.Close()
1299+
require.NoError(t, err)
1300+
})
1301+
}

0 commit comments

Comments
 (0)