aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/postgres_fdw.c
diff options
context:
space:
mode:
authorEtsuro Fujita <efujita@postgresql.org>2021-08-02 12:45:00 +0900
committerEtsuro Fujita <efujita@postgresql.org>2021-08-02 12:45:00 +0900
commita8ed9bd59d48c13da50ed2358911721b2baf1de3 (patch)
tree1f9469ec35097d0d16cb4e23e807cd2768796123 /contrib/postgres_fdw/postgres_fdw.c
parenteaf5321c352478266cebe2aa50ea4c34a8fdd2c7 (diff)
downloadpostgresql-a8ed9bd59d48c13da50ed2358911721b2baf1de3.tar.gz
postgresql-a8ed9bd59d48c13da50ed2358911721b2baf1de3.zip
Fix oversight in commit 1ec7fca8592178281cd5cdada0f27a340fb813fc.
I failed to account for the possibility that when ExecAppendAsyncEventWait() notifies multiple async-capable nodes using postgres_fdw, a preceding node might invoke process_pending_request() to process a pending asynchronous request made by a succeeding node. In that case the succeeding node should produce a tuple to return to the parent Append node from tuples fetched by process_pending_request() when notified. Repair. Per buildfarm via Michael Paquier. Back-patch to v14, like the previous commit. Thanks to Tom Lane for testing. Discussion: https://postgr.es/m/YQP0UPT8KmPiHTMs%40paquier.xyz
Diffstat (limited to 'contrib/postgres_fdw/postgres_fdw.c')
-rw-r--r--contrib/postgres_fdw/postgres_fdw.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 8dfee2e02c6..3e4a307880f 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -6896,12 +6896,26 @@ postgresForeignAsyncNotify(AsyncRequest *areq)
ForeignScanState *node = (ForeignScanState *) areq->requestee;
PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
- /* The request should be currently in-process */
- Assert(fsstate->conn_state->pendingAreq == areq);
-
/* The core code would have initialized the callback_pending flag */
Assert(!areq->callback_pending);
+ /*
+ * If process_pending_request() has been invoked on the given request
+ * before we get here, we might have some tuples already; in which case
+ * produce the next tuple
+ */
+ if (fsstate->next_tuple < fsstate->num_tuples)
+ {
+ produce_tuple_asynchronously(areq, true);
+ return;
+ }
+
+ /* We must have run out of tuples */
+ Assert(fsstate->next_tuple >= fsstate->num_tuples);
+
+ /* The request should be currently in-process */
+ Assert(fsstate->conn_state->pendingAreq == areq);
+
/* On error, report the original query, not the FETCH. */
if (!PQconsumeInput(fsstate->conn))
pgfdw_report_error(ERROR, NULL, fsstate->conn, false, fsstate->query);
@@ -7027,7 +7041,7 @@ process_pending_request(AsyncRequest *areq)
/*
* If we didn't get any tuples, must be end of data; complete the request
* now. Otherwise, we postpone completing the request until we are called
- * from postgresForeignAsyncConfigureWait().
+ * from postgresForeignAsyncConfigureWait()/postgresForeignAsyncNotify().
*/
if (fsstate->next_tuple >= fsstate->num_tuples)
{