From ba10eaef509bf47de743589a232e83f071acf8dc Mon Sep 17 00:00:00 2001 From: Amit Kapila Date: Mon, 13 Aug 2018 08:43:33 +0530 Subject: [PATCH] Prohibit shutting down resources if there is a possibility of back up. 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 | 16 ++++++++++++---- src/backend/executor/nodeLimit.c | 10 ++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 878e8e9ea13..6f467c65c10 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1727,8 +1727,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; } @@ -1774,8 +1778,12 @@ ExecutePlan(EState *estate, current_tuple_count++; if (numberTuples && numberTuples == current_tuple_count) { - /* 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; } } diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index cf1851e235f..6e74bb23d06 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -134,8 +134,14 @@ ExecLimit(PlanState *pstate) 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; }