Prohibit shutting down resources if there is a possibility of back up.
authorAmit Kapila
Mon, 13 Aug 2018 03:26:37 +0000 (08:56 +0530)
committerAmit Kapila
Mon, 13 Aug 2018 03:26:37 +0000 (08:56 +0530)
Currently, we release the asynchronous resources as soon as it is evident
that no more rows will be needed e.g. when a Limit is filled.  This can be
problematic especially for custom and foreign scans where we can scan
backward.  Fix that by disallowing the shutting down of resources in such
cases.

Reported-by: Robert Haas
Analysed-by: Robert Haas and Amit Kapila
Author: Amit Kapila
Reviewed-by: Robert Haas
Backpatch-through: 9.6 where this code was introduced
Discussion: https://postgr.es/m/86137f17-1dfb-42f9-7421-82fd786b04a1@anayrat.info

src/backend/executor/execMain.c
src/backend/executor/nodeLimit.c

index 10ccf59b79435055ed5e30f1cd63a77d9c9868e1..9c70cb7c17464282b2fa47fff2b4f95e31f59fe7 100644 (file)
@@ -1571,8 +1571,12 @@ ExecutePlan(EState *estate,
         */
        if (TupIsNull(slot))
        {
-           /* Allow nodes to release or shut down resources. */
-           (void) ExecShutdownNode(planstate);
+           /*
+            * If we know we won't need to back up, we can release
+            * resources at this point.
+            */
+           if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))
+               (void) ExecShutdownNode(planstate);
            break;
        }
 
index 4ff8982cd5b1577f579bcc37ca4318d685b0873c..9d78b827520f29792fc05da96d4818e8cd0f57cc 100644 (file)
@@ -130,8 +130,14 @@ ExecLimit(LimitState *node)
                    node->position - node->offset >= node->count)
                {
                    node->lstate = LIMIT_WINDOWEND;
-                   /* Allow nodes to release or shut down resources. */
-                   (void) ExecShutdownNode(outerPlan);
+
+                   /*
+                    * If we know we won't need to back up, we can release
+                    * resources at this point.
+                    */
+                   if (!(node->ps.state->es_top_eflags & EXEC_FLAG_BACKWARD))
+                       (void) ExecShutdownNode(outerPlan);
+
                    return NULL;
                }