Skip to content

Commit fa9b440

Browse files
alvherrereshke
authored andcommitted
libpq: Reset singlerow flag correctly in pipeline mode
When a query whose results were requested in single-row mode is the last in the queue by the time those results are being read, the single-row flag was not being reset, because we were returning early from pqPipelineProcessQueue. Move that stanza up so that the flag is always reset at the end of sending that query's results. Add a test for the situation. Backpatch to 14. Author: Denis Laxalde <denis.laxalde@dalibo.com> Discussion: https://postgr.es/m/01af18c5-dacc-a8c8-07ee-aecc7650c3e8@dalibo.com
1 parent 2d19ca7 commit fa9b440

3 files changed

Lines changed: 70 additions & 7 deletions

File tree

src/interfaces/libpq/fe-exec.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,6 +3123,12 @@ pqPipelineProcessQueue(PGconn *conn)
31233123
break;
31243124
}
31253125

3126+
/*
3127+
* Reset single-row processing mode. (Client has to set it up for each
3128+
* query, if desired.)
3129+
*/
3130+
conn->singleRowMode = false;
3131+
31263132
/*
31273133
* If there are no further commands to process in the queue, get us in
31283134
* "real idle" mode now.
@@ -3136,12 +3142,6 @@ pqPipelineProcessQueue(PGconn *conn)
31363142
/* Initialize async result-accumulation state */
31373143
pqClearAsyncResult(conn);
31383144

3139-
/*
3140-
* Reset single-row processing mode. (Client has to set it up for each
3141-
* query, if desired.)
3142-
*/
3143-
conn->singleRowMode = false;
3144-
31453145
if (conn->pipelineStatus == PQ_PIPELINE_ABORTED &&
31463146
conn->cmd_queue_head->queryclass != PGQUERY_SYNC)
31473147
{

src/test/modules/libpq_pipeline/libpq_pipeline.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1143,11 +1143,11 @@ test_singlerowmode(PGconn *conn)
11431143
int i;
11441144
bool pipeline_ended = false;
11451145

1146-
/* 1 pipeline, 3 queries in it */
11471146
if (PQenterPipelineMode(conn) != 1)
11481147
pg_fatal("failed to enter pipeline mode: %s",
11491148
PQerrorMessage(conn));
11501149

1150+
/* One series of three commands, using single-row mode for the first two. */
11511151
for (i = 0; i < 3; i++)
11521152
{
11531153
char *param[1];
@@ -1239,6 +1239,49 @@ test_singlerowmode(PGconn *conn)
12391239
pg_fatal("didn't get expected terminating TUPLES_OK");
12401240
}
12411241

1242+
/*
1243+
* Now issue one command, get its results in with single-row mode, then
1244+
* issue another command, and get its results in normal mode; make sure
1245+
* the single-row mode flag is reset as expected.
1246+
*/
1247+
if (PQsendQueryParams(conn, "SELECT generate_series(0, 0)",
1248+
0, NULL, NULL, NULL, NULL, 0) != 1)
1249+
pg_fatal("failed to send query: %s",
1250+
PQerrorMessage(conn));
1251+
if (PQsendFlushRequest(conn) != 1)
1252+
pg_fatal("failed to send flush request");
1253+
if (PQsetSingleRowMode(conn) != 1)
1254+
pg_fatal("PQsetSingleRowMode() failed");
1255+
res = PQgetResult(conn);
1256+
if (res == NULL)
1257+
pg_fatal("unexpected NULL");
1258+
if (PQresultStatus(res) != PGRES_SINGLE_TUPLE)
1259+
pg_fatal("Expected PGRES_SINGLE_TUPLE, got %s",
1260+
PQresStatus(PQresultStatus(res)));
1261+
res = PQgetResult(conn);
1262+
if (res == NULL)
1263+
pg_fatal("unexpected NULL");
1264+
if (PQresultStatus(res) != PGRES_TUPLES_OK)
1265+
pg_fatal("Expected PGRES_TUPLES_OK, got %s",
1266+
PQresStatus(PQresultStatus(res)));
1267+
if (PQgetResult(conn) != NULL)
1268+
pg_fatal("expected NULL result");
1269+
1270+
if (PQsendQueryParams(conn, "SELECT 1",
1271+
0, NULL, NULL, NULL, NULL, 0) != 1)
1272+
pg_fatal("failed to send query: %s",
1273+
PQerrorMessage(conn));
1274+
if (PQsendFlushRequest(conn) != 1)
1275+
pg_fatal("failed to send flush request");
1276+
res = PQgetResult(conn);
1277+
if (res == NULL)
1278+
pg_fatal("unexpected NULL");
1279+
if (PQresultStatus(res) != PGRES_TUPLES_OK)
1280+
pg_fatal("Expected PGRES_TUPLES_OK, got %s",
1281+
PQresStatus(PQresultStatus(res)));
1282+
if (PQgetResult(conn) != NULL)
1283+
pg_fatal("expected NULL result");
1284+
12421285
if (PQexitPipelineMode(conn) != 1)
12431286
pg_fatal("failed to end pipeline mode: %s", PQerrorMessage(conn));
12441287

src/test/modules/libpq_pipeline/traces/singlerow.trace

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,24 @@ B 12 DataRow 1 2 '45'
3636
B 12 DataRow 1 2 '46'
3737
B 13 CommandComplete "SELECT 5"
3838
B 5 ReadyForQuery I
39+
F 36 Parse "" "SELECT generate_series(0, 0)" 0
40+
F 14 Bind "" "" 0 0 1 0
41+
F 6 Describe P ""
42+
F 9 Execute "" 0
43+
F 4 Flush
44+
B 4 ParseComplete
45+
B 4 BindComplete
46+
B 40 RowDescription 1 "generate_series" NNNN 0 NNNN 4 -1 0
47+
B 11 DataRow 1 1 '0'
48+
B 13 CommandComplete "SELECT 1"
49+
F 16 Parse "" "SELECT 1" 0
50+
F 14 Bind "" "" 0 0 1 0
51+
F 6 Describe P ""
52+
F 9 Execute "" 0
53+
F 4 Flush
54+
B 4 ParseComplete
55+
B 4 BindComplete
56+
B 33 RowDescription 1 "?column?" NNNN 0 NNNN 4 -1 0
57+
B 11 DataRow 1 1 '1'
58+
B 13 CommandComplete "SELECT 1"
3959
F 4 Terminate

0 commit comments

Comments
 (0)