]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix oversight in commit 1ec7fca8592178281cd5cdada0f27a340fb813fc.
authorEtsuro Fujita <efujita@postgresql.org>
Mon, 2 Aug 2021 03:45:00 +0000 (12:45 +0900)
committerEtsuro Fujita <efujita@postgresql.org>
Mon, 2 Aug 2021 03:45:00 +0000 (12:45 +0900)
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

contrib/postgres_fdw/postgres_fdw.c
src/backend/executor/nodeAppend.c

index 8dfee2e02c61be2067eeaa9821c0ab4db0864811..3e4a307880fc223d5faf2f7cd89bfcb11650c3c4 100644 (file)
@@ -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)
        {
index a4eef19d7f4f8af9476e989d3f86f3c6ff67b853..6a2daa6e767d7f845a431605d691de5ae5fddc4c 100644 (file)
@@ -1082,16 +1082,18 @@ ExecAppendAsyncEventWait(AppendState *node)
                {
                        AsyncRequest *areq = (AsyncRequest *) w->user_data;
 
-                       /*
-                        * Mark it as no longer needing a callback.  We must do this
-                        * before dispatching the callback in case the callback resets the
-                        * flag.
-                        */
-                       Assert(areq->callback_pending);
-                       areq->callback_pending = false;
-
-                       /* Do the actual work. */
-                       ExecAsyncNotify(areq);
+                       if (areq->callback_pending)
+                       {
+                               /*
+                                * Mark it as no longer needing a callback.  We must do this
+                                * before dispatching the callback in case the callback resets
+                                * the flag.
+                                */
+                               areq->callback_pending = false;
+
+                               /* Do the actual work. */
+                               ExecAsyncNotify(areq);
+                       }
                }
        }
 }