summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlvaro Herrera2022-10-14 17:06:26 +0000
committerAlvaro Herrera2022-10-14 17:06:26 +0000
commitdb1b931a4ee885ebd27bb5b335c1e461ccc34bbe (patch)
treece4d749a14741125120c921a1ed5b07c64fa4a93 /src
parentf13b2088fa2d4455936e65459b77698a4452f932 (diff)
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 <[email protected]> Discussion: https://postgr.es/m/[email protected]
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/libpq/fe-exec.c12
-rw-r--r--src/test/modules/libpq_pipeline/libpq_pipeline.c45
-rw-r--r--src/test/modules/libpq_pipeline/traces/singlerow.trace20
3 files changed, 70 insertions, 7 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 0274c1b156c..64701b562bf 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -3097,6 +3097,12 @@ pqPipelineProcessQueue(PGconn *conn)
}
/*
+ * Reset single-row processing mode. (Client has to set it up for each
+ * query, if desired.)
+ */
+ conn->singleRowMode = false;
+
+ /*
* If there are no further commands to process in the queue, get us in
* "real idle" mode now.
*/
@@ -3115,12 +3121,6 @@ pqPipelineProcessQueue(PGconn *conn)
/* Initialize async result-accumulation state */
pqClearAsyncResult(conn);
- /*
- * Reset single-row processing mode. (Client has to set it up for each
- * query, if desired.)
- */
- conn->singleRowMode = false;
-
if (conn->pipelineStatus == PQ_PIPELINE_ABORTED &&
conn->cmd_queue_head->queryclass != PGQUERY_SYNC)
{
diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c
index c609f422589..a37e4e25008 100644
--- a/src/test/modules/libpq_pipeline/libpq_pipeline.c
+++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c
@@ -1153,11 +1153,11 @@ test_singlerowmode(PGconn *conn)
int i;
bool pipeline_ended = false;
- /* 1 pipeline, 3 queries in it */
if (PQenterPipelineMode(conn) != 1)
pg_fatal("failed to enter pipeline mode: %s",
PQerrorMessage(conn));
+ /* One series of three commands, using single-row mode for the first two. */
for (i = 0; i < 3; i++)
{
char *param[1];
@@ -1249,6 +1249,49 @@ test_singlerowmode(PGconn *conn)
pg_fatal("didn't get expected terminating TUPLES_OK");
}
+ /*
+ * Now issue one command, get its results in with single-row mode, then
+ * issue another command, and get its results in normal mode; make sure
+ * the single-row mode flag is reset as expected.
+ */
+ if (PQsendQueryParams(conn, "SELECT generate_series(0, 0)",
+ 0, NULL, NULL, NULL, NULL, 0) != 1)
+ pg_fatal("failed to send query: %s",
+ PQerrorMessage(conn));
+ if (PQsendFlushRequest(conn) != 1)
+ pg_fatal("failed to send flush request");
+ if (PQsetSingleRowMode(conn) != 1)
+ pg_fatal("PQsetSingleRowMode() failed");
+ res = PQgetResult(conn);
+ if (res == NULL)
+ pg_fatal("unexpected NULL");
+ if (PQresultStatus(res) != PGRES_SINGLE_TUPLE)
+ pg_fatal("Expected PGRES_SINGLE_TUPLE, got %s",
+ PQresStatus(PQresultStatus(res)));
+ res = PQgetResult(conn);
+ if (res == NULL)
+ pg_fatal("unexpected NULL");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected PGRES_TUPLES_OK, got %s",
+ PQresStatus(PQresultStatus(res)));
+ if (PQgetResult(conn) != NULL)
+ pg_fatal("expected NULL result");
+
+ if (PQsendQueryParams(conn, "SELECT 1",
+ 0, NULL, NULL, NULL, NULL, 0) != 1)
+ pg_fatal("failed to send query: %s",
+ PQerrorMessage(conn));
+ if (PQsendFlushRequest(conn) != 1)
+ pg_fatal("failed to send flush request");
+ res = PQgetResult(conn);
+ if (res == NULL)
+ pg_fatal("unexpected NULL");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected PGRES_TUPLES_OK, got %s",
+ PQresStatus(PQresultStatus(res)));
+ if (PQgetResult(conn) != NULL)
+ pg_fatal("expected NULL result");
+
if (PQexitPipelineMode(conn) != 1)
pg_fatal("failed to end pipeline mode: %s", PQerrorMessage(conn));
diff --git a/src/test/modules/libpq_pipeline/traces/singlerow.trace b/src/test/modules/libpq_pipeline/traces/singlerow.trace
index 9de99befcc1..83043e1407e 100644
--- a/src/test/modules/libpq_pipeline/traces/singlerow.trace
+++ b/src/test/modules/libpq_pipeline/traces/singlerow.trace
@@ -36,4 +36,24 @@ B 12 DataRow 1 2 '45'
B 12 DataRow 1 2 '46'
B 13 CommandComplete "SELECT 5"
B 5 ReadyForQuery I
+F 36 Parse "" "SELECT generate_series(0, 0)" 0
+F 14 Bind "" "" 0 0 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Flush
+B 4 ParseComplete
+B 4 BindComplete
+B 40 RowDescription 1 "generate_series" NNNN 0 NNNN 4 -1 0
+B 11 DataRow 1 1 '0'
+B 13 CommandComplete "SELECT 1"
+F 16 Parse "" "SELECT 1" 0
+F 14 Bind "" "" 0 0 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Flush
+B 4 ParseComplete
+B 4 BindComplete
+B 33 RowDescription 1 "?column?" NNNN 0 NNNN 4 -1 0
+B 11 DataRow 1 1 '1'
+B 13 CommandComplete "SELECT 1"
F 4 Terminate