From 95af485bf11e05d49452601e0673ee3c415176dd Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Wed, 6 Sep 2023 17:53:16 +0900 Subject: [PATCH v47 2/9] Check pointer NULLness before cleanup in ExecEnd* routines Many routines already perform this check, but a few instances remain. Currently, these NULLness checks might seem redundant since ExecEnd* routines operate under the assumption that their matching ExecInit* routine would have fully executed, ensuring pointers are set. However, a forthcoming patch will modify ExecInit* routines to sometimes exit early, potentially leaving some pointers in an undetermined state, so it will become crucial to have these NULLness checks in place. Other than the ExecEnd* routines, this also adds a guard at the begigging of EvalPlanQualEnd() to return early if the EPQState does not appear to have been initialized. While at it, set cleaned up pointers to NULL more consistently across ExecEnd* routines. Also for consistency, change all the NULLness checks to follow the "if (pointer != NULL)" style over "if (pointer)". Reviewed-by: Robert Haas --- contrib/postgres_fdw/postgres_fdw.c | 5 ++- src/backend/executor/execMain.c | 4 ++ src/backend/executor/nodeAgg.c | 27 +++++++++---- src/backend/executor/nodeAppend.c | 3 ++ src/backend/executor/nodeBitmapAnd.c | 4 +- src/backend/executor/nodeBitmapHeapscan.c | 47 +++++++++++++++------- src/backend/executor/nodeBitmapIndexscan.c | 23 +++++------ src/backend/executor/nodeBitmapOr.c | 4 +- src/backend/executor/nodeForeignscan.c | 17 ++++---- src/backend/executor/nodeGather.c | 1 + src/backend/executor/nodeGatherMerge.c | 1 + src/backend/executor/nodeGroup.c | 6 +-- src/backend/executor/nodeHash.c | 6 +-- src/backend/executor/nodeHashjoin.c | 4 +- src/backend/executor/nodeIncrementalSort.c | 13 +++++- src/backend/executor/nodeIndexonlyscan.c | 25 ++++++------ src/backend/executor/nodeIndexscan.c | 23 +++++------ src/backend/executor/nodeLimit.c | 1 + src/backend/executor/nodeLockRows.c | 1 + src/backend/executor/nodeMaterial.c | 5 ++- src/backend/executor/nodeMemoize.c | 8 +++- src/backend/executor/nodeMergeAppend.c | 3 ++ src/backend/executor/nodeMergejoin.c | 2 + src/backend/executor/nodeModifyTable.c | 11 ++++- src/backend/executor/nodeNestloop.c | 2 + src/backend/executor/nodeProjectSet.c | 1 + src/backend/executor/nodeRecursiveunion.c | 24 +++++++++-- src/backend/executor/nodeResult.c | 1 + src/backend/executor/nodeSamplescan.c | 7 +++- src/backend/executor/nodeSeqscan.c | 16 +++----- src/backend/executor/nodeSetOp.c | 6 ++- src/backend/executor/nodeSort.c | 5 ++- src/backend/executor/nodeSubqueryscan.c | 1 + src/backend/executor/nodeTableFuncscan.c | 4 +- src/backend/executor/nodeTidrangescan.c | 12 ++++-- src/backend/executor/nodeTidscan.c | 8 +++- src/backend/executor/nodeUnique.c | 1 + src/backend/executor/nodeWindowAgg.c | 41 ++++++++++++++----- 38 files changed, 252 insertions(+), 121 deletions(-) diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 1393716587..802f76c73e 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -2126,7 +2126,10 @@ postgresEndForeignModify(EState *estate, { PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState; - /* If fmstate is NULL, we are in EXPLAIN; nothing to do */ + /* + * If fmstate is NULL, we are either in EXPLAIN or if BeginForeignModify + * wasn't called; nothing to do in any case. + */ if (fmstate == NULL) return; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 4c5a7bbf62..f7f18d3054 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -3010,6 +3010,10 @@ EvalPlanQualEnd(EPQState *epqstate) MemoryContext oldcontext; ListCell *l; + /* Nothing to do if no EvalPlanQualInit() was done to begin with. */ + if (epqstate->parentestate == NULL) + return; + rtsize = epqstate->parentestate->es_range_table_size; /* diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index f154f28902..af22b1676f 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -4304,7 +4304,6 @@ GetAggInitVal(Datum textInitVal, Oid transtype) void ExecEndAgg(AggState *node) { - PlanState *outerPlan; int transno; int numGroupingSets = Max(node->maxsets, 1); int setno; @@ -4314,7 +4313,7 @@ ExecEndAgg(AggState *node) * worker back into shared memory so that it can be picked up by the main * process to report in EXPLAIN ANALYZE. */ - if (node->shared_info && IsParallelWorker()) + if (node->shared_info != NULL && IsParallelWorker()) { AggregateInstrumentation *si; @@ -4327,10 +4326,16 @@ ExecEndAgg(AggState *node) /* Make sure we have closed any open tuplesorts */ - if (node->sort_in) + if (node->sort_in != NULL) + { tuplesort_end(node->sort_in); - if (node->sort_out) + node->sort_in = NULL; + } + if (node->sort_out != NULL) + { tuplesort_end(node->sort_out); + node->sort_out = NULL; + } hashagg_reset_spill_state(node); @@ -4346,19 +4351,25 @@ ExecEndAgg(AggState *node) for (setno = 0; setno < numGroupingSets; setno++) { - if (pertrans->sortstates[setno]) + if (pertrans->sortstates[setno] != NULL) tuplesort_end(pertrans->sortstates[setno]); } } /* And ensure any agg shutdown callbacks have been called */ for (setno = 0; setno < numGroupingSets; setno++) + { ReScanExprContext(node->aggcontexts[setno]); - if (node->hashcontext) + node->aggcontexts[setno] = NULL; + } + if (node->hashcontext != NULL) + { ReScanExprContext(node->hashcontext); + node->hashcontext = NULL; + } - outerPlan = outerPlanState(node); - ExecEndNode(outerPlan); + ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } void diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 609df6b9e6..a2af221e05 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -399,7 +399,10 @@ ExecEndAppend(AppendState *node) * shut down each of the subscans */ for (i = 0; i < nplans; i++) + { ExecEndNode(appendplans[i]); + appendplans[i] = NULL; + } } void diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c index 4c5eb2b23b..4abb0609a0 100644 --- a/src/backend/executor/nodeBitmapAnd.c +++ b/src/backend/executor/nodeBitmapAnd.c @@ -192,8 +192,8 @@ ExecEndBitmapAnd(BitmapAndState *node) */ for (i = 0; i < nplans; i++) { - if (bitmapplans[i]) - ExecEndNode(bitmapplans[i]); + ExecEndNode(bitmapplans[i]); + bitmapplans[i] = NULL; } } diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 2db0acfc76..d3f58c22f9 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -648,40 +648,59 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node) void ExecEndBitmapHeapScan(BitmapHeapScanState *node) { - TableScanDesc scanDesc; - - /* - * extract information from the node - */ - scanDesc = node->ss.ss_currentScanDesc; - /* * close down subplans */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; /* * release bitmaps and buffers if any */ - if (node->tbmiterator) + if (node->tbmiterator != NULL) + { tbm_end_iterate(node->tbmiterator); - if (node->prefetch_iterator) + node->tbmiterator = NULL; + } + if (node->prefetch_iterator != NULL) + { tbm_end_iterate(node->prefetch_iterator); - if (node->tbm) + node->prefetch_iterator = NULL; + } + if (node->tbm != NULL) + { tbm_free(node->tbm); - if (node->shared_tbmiterator) + node->tbm = NULL; + } + if (node->shared_tbmiterator != NULL) + { tbm_end_shared_iterate(node->shared_tbmiterator); - if (node->shared_prefetch_iterator) + node->shared_tbmiterator = NULL; + } + if (node->shared_prefetch_iterator != NULL) + { tbm_end_shared_iterate(node->shared_prefetch_iterator); + node->shared_prefetch_iterator = NULL; + } if (node->vmbuffer != InvalidBuffer) + { ReleaseBuffer(node->vmbuffer); + node->vmbuffer = InvalidBuffer; + } if (node->pvmbuffer != InvalidBuffer) + { ReleaseBuffer(node->pvmbuffer); + node->pvmbuffer = InvalidBuffer; + } /* - * close heap scan + * close heap scan (no-op if we didn't start it) */ - table_endscan(scanDesc); + if (node->ss.ss_currentScanDesc != NULL) + { + table_endscan(node->ss.ss_currentScanDesc); + node->ss.ss_currentScanDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index 7cf8532bc9..488f11a3ff 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -175,22 +175,21 @@ ExecReScanBitmapIndexScan(BitmapIndexScanState *node) void ExecEndBitmapIndexScan(BitmapIndexScanState *node) { - Relation indexRelationDesc; - IndexScanDesc indexScanDesc; - - /* - * extract information from the node - */ - indexRelationDesc = node->biss_RelationDesc; - indexScanDesc = node->biss_ScanDesc; + /* close the scan (no-op if we didn't start it) */ + if (node->biss_ScanDesc != NULL) + { + index_endscan(node->biss_ScanDesc); + node->biss_ScanDesc = NULL; + } /* * close the index relation (no-op if we didn't open it) */ - if (indexScanDesc) - index_endscan(indexScanDesc); - if (indexRelationDesc) - index_close(indexRelationDesc, NoLock); + if (node->biss_RelationDesc != NULL) + { + index_close(node->biss_RelationDesc, NoLock); + node->biss_RelationDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c index 0bf8af9652..ace18593aa 100644 --- a/src/backend/executor/nodeBitmapOr.c +++ b/src/backend/executor/nodeBitmapOr.c @@ -210,8 +210,8 @@ ExecEndBitmapOr(BitmapOrState *node) */ for (i = 0; i < nplans; i++) { - if (bitmapplans[i]) - ExecEndNode(bitmapplans[i]); + ExecEndNode(bitmapplans[i]); + bitmapplans[i] = NULL; } } diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index 73913ebb18..3aba28285a 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -301,17 +301,20 @@ ExecEndForeignScan(ForeignScanState *node) EState *estate = node->ss.ps.state; /* Let the FDW shut down */ - if (plan->operation != CMD_SELECT) + if (node->fdwroutine != NULL) { - if (estate->es_epq_active == NULL) - node->fdwroutine->EndDirectModify(node); + if (plan->operation != CMD_SELECT) + { + if (estate->es_epq_active == NULL) + node->fdwroutine->EndDirectModify(node); + } + else + node->fdwroutine->EndForeignScan(node); } - else - node->fdwroutine->EndForeignScan(node); /* Shut down any outer plan. */ - if (outerPlanState(node)) - ExecEndNode(outerPlanState(node)); + ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index bb2500a469..1a3c8abdad 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -249,6 +249,7 @@ void ExecEndGather(GatherState *node) { ExecEndNode(outerPlanState(node)); /* let children clean up first */ + outerPlanState(node) = NULL; ExecShutdownGather(node); } diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index 7a71a58509..c6fb45fee0 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -289,6 +289,7 @@ void ExecEndGatherMerge(GatherMergeState *node) { ExecEndNode(outerPlanState(node)); /* let children clean up first */ + outerPlanState(node) = NULL; ExecShutdownGatherMerge(node); } diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index 8c650f0e46..6dfe5a1d23 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -226,10 +226,8 @@ ExecInitGroup(Group *node, EState *estate, int eflags) void ExecEndGroup(GroupState *node) { - PlanState *outerPlan; - - outerPlan = outerPlanState(node); - ExecEndNode(outerPlan); + ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } void diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index e72f0986c2..88ba336882 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -413,13 +413,11 @@ ExecInitHash(Hash *node, EState *estate, int eflags) void ExecEndHash(HashState *node) { - PlanState *outerPlan; - /* * shut down the subplan */ - outerPlan = outerPlanState(node); - ExecEndNode(outerPlan); + ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index aea44a9d56..6dc43b9ff2 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -861,7 +861,7 @@ ExecEndHashJoin(HashJoinState *node) /* * Free hash table */ - if (node->hj_HashTable) + if (node->hj_HashTable != NULL) { ExecHashTableDestroy(node->hj_HashTable); node->hj_HashTable = NULL; @@ -871,7 +871,9 @@ ExecEndHashJoin(HashJoinState *node) * clean up subtrees */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; ExecEndNode(innerPlanState(node)); + innerPlanState(node) = NULL; } /* diff --git a/src/backend/executor/nodeIncrementalSort.c b/src/backend/executor/nodeIncrementalSort.c index cd094a190c..28a0e81cb3 100644 --- a/src/backend/executor/nodeIncrementalSort.c +++ b/src/backend/executor/nodeIncrementalSort.c @@ -1079,8 +1079,16 @@ ExecEndIncrementalSort(IncrementalSortState *node) { SO_printf("ExecEndIncrementalSort: shutting down sort node\n"); - ExecDropSingleTupleTableSlot(node->group_pivot); - ExecDropSingleTupleTableSlot(node->transfer_tuple); + if (node->group_pivot != NULL) + { + ExecDropSingleTupleTableSlot(node->group_pivot); + node->group_pivot = NULL; + } + if (node->transfer_tuple != NULL) + { + ExecDropSingleTupleTableSlot(node->transfer_tuple); + node->transfer_tuple = NULL; + } /* * Release tuplesort resources. @@ -1100,6 +1108,7 @@ ExecEndIncrementalSort(IncrementalSortState *node) * Shut down the subplan. */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; SO_printf("ExecEndIncrementalSort: sort node shutdown\n"); } diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index f1db35665c..1f3843abe9 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -364,15 +364,6 @@ ExecReScanIndexOnlyScan(IndexOnlyScanState *node) void ExecEndIndexOnlyScan(IndexOnlyScanState *node) { - Relation indexRelationDesc; - IndexScanDesc indexScanDesc; - - /* - * extract information from the node - */ - indexRelationDesc = node->ioss_RelationDesc; - indexScanDesc = node->ioss_ScanDesc; - /* Release VM buffer pin, if any. */ if (node->ioss_VMBuffer != InvalidBuffer) { @@ -380,13 +371,21 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node) node->ioss_VMBuffer = InvalidBuffer; } + /* close the scan (no-op if we didn't start it) */ + if (node->ioss_ScanDesc != NULL) + { + index_endscan(node->ioss_ScanDesc); + node->ioss_ScanDesc = NULL; + } + /* * close the index relation (no-op if we didn't open it) */ - if (indexScanDesc) - index_endscan(indexScanDesc); - if (indexRelationDesc) - index_close(indexRelationDesc, NoLock); + if (node->ioss_RelationDesc != NULL) + { + index_close(node->ioss_RelationDesc, NoLock); + node->ioss_RelationDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 14b9c00217..32e1714f15 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -785,22 +785,21 @@ ExecIndexAdvanceArrayKeys(IndexArrayKeyInfo *arrayKeys, int numArrayKeys) void ExecEndIndexScan(IndexScanState *node) { - Relation indexRelationDesc; - IndexScanDesc indexScanDesc; - - /* - * extract information from the node - */ - indexRelationDesc = node->iss_RelationDesc; - indexScanDesc = node->iss_ScanDesc; + /* close the scan (no-op if we didn't start it) */ + if (node->iss_ScanDesc != NULL) + { + index_endscan(node->iss_ScanDesc); + node->iss_ScanDesc = NULL; + } /* * close the index relation (no-op if we didn't open it) */ - if (indexScanDesc) - index_endscan(indexScanDesc); - if (indexRelationDesc) - index_close(indexRelationDesc, NoLock); + if (node->iss_RelationDesc != NULL) + { + index_close(node->iss_RelationDesc, NoLock); + node->iss_RelationDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index 5654158e3e..a97bac9f6d 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -535,6 +535,7 @@ void ExecEndLimit(LimitState *node) { ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index e459971d32..26fbe95c57 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -387,6 +387,7 @@ ExecEndLockRows(LockRowsState *node) /* We may have shut down EPQ already, but no harm in another call */ EvalPlanQualEnd(&node->lr_epqstate); ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 753ea28915..03c514900b 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -243,13 +243,16 @@ ExecEndMaterial(MaterialState *node) * Release tuplestore resources */ if (node->tuplestorestate != NULL) + { tuplestore_end(node->tuplestorestate); - node->tuplestorestate = NULL; + node->tuplestorestate = NULL; + } /* * shut down the subplan */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c index 94bf479287..ee4749c852 100644 --- a/src/backend/executor/nodeMemoize.c +++ b/src/backend/executor/nodeMemoize.c @@ -1043,6 +1043,7 @@ ExecEndMemoize(MemoizeState *node) { #ifdef USE_ASSERT_CHECKING /* Validate the memory accounting code is correct in assert builds. */ + if (node->hashtable != NULL) { int count; uint64 mem = 0; @@ -1089,12 +1090,17 @@ ExecEndMemoize(MemoizeState *node) } /* Remove the cache context */ - MemoryContextDelete(node->tableContext); + if (node->tableContext != NULL) + { + MemoryContextDelete(node->tableContext); + node->tableContext = NULL; + } /* * shut down the subplan */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } void diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index 21b5726e6e..0a42a04b19 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -333,7 +333,10 @@ ExecEndMergeAppend(MergeAppendState *node) * shut down each of the subscans */ for (i = 0; i < nplans; i++) + { ExecEndNode(mergeplans[i]); + mergeplans[i] = NULL; + } } void diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 648fdd9a5f..4d7d73a684 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -1646,7 +1646,9 @@ ExecEndMergeJoin(MergeJoinState *node) * shut down the subplans */ ExecEndNode(innerPlanState(node)); + innerPlanState(node) = NULL; ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; MJ1_printf("ExecEndMergeJoin: %s\n", "node processing ended"); diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index d21a178ad5..ea043c57c1 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -4430,7 +4430,9 @@ ExecEndModifyTable(ModifyTableState *node) for (j = 0; j < resultRelInfo->ri_NumSlotsInitialized; j++) { ExecDropSingleTupleTableSlot(resultRelInfo->ri_Slots[j]); + resultRelInfo->ri_Slots[j] = NULL; ExecDropSingleTupleTableSlot(resultRelInfo->ri_PlanSlots[j]); + resultRelInfo->ri_PlanSlots[j] = NULL; } } @@ -4438,12 +4440,16 @@ ExecEndModifyTable(ModifyTableState *node) * Close all the partitioned tables, leaf partitions, and their indices * and release the slot used for tuple routing, if set. */ - if (node->mt_partition_tuple_routing) + if (node->mt_partition_tuple_routing != NULL) { ExecCleanupTupleRouting(node, node->mt_partition_tuple_routing); + node->mt_partition_tuple_routing = NULL; - if (node->mt_root_tuple_slot) + if (node->mt_root_tuple_slot != NULL) + { ExecDropSingleTupleTableSlot(node->mt_root_tuple_slot); + node->mt_root_tuple_slot = NULL; + } } /* @@ -4455,6 +4461,7 @@ ExecEndModifyTable(ModifyTableState *node) * shut down subplan */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } void diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index fc8f833d8b..76e02449f5 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -367,7 +367,9 @@ ExecEndNestLoop(NestLoopState *node) * close down subplans */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; ExecEndNode(innerPlanState(node)); + innerPlanState(node) = NULL; NL1_printf("ExecEndNestLoop: %s\n", "node processing ended"); diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c index b4bbdc89b1..e9b96416d3 100644 --- a/src/backend/executor/nodeProjectSet.c +++ b/src/backend/executor/nodeProjectSet.c @@ -324,6 +324,7 @@ ExecEndProjectSet(ProjectSetState *node) * shut down subplans */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } void diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c index e781003934..f6d60bcd6c 100644 --- a/src/backend/executor/nodeRecursiveunion.c +++ b/src/backend/executor/nodeRecursiveunion.c @@ -272,20 +272,36 @@ void ExecEndRecursiveUnion(RecursiveUnionState *node) { /* Release tuplestores */ - tuplestore_end(node->working_table); - tuplestore_end(node->intermediate_table); + if (node->working_table != NULL) + { + tuplestore_end(node->working_table); + node->working_table = NULL; + } + if (node->intermediate_table != NULL) + { + tuplestore_end(node->intermediate_table); + node->intermediate_table = NULL; + } /* free subsidiary stuff including hashtable */ - if (node->tempContext) + if (node->tempContext != NULL) + { MemoryContextDelete(node->tempContext); - if (node->tableContext) + node->tempContext = NULL; + } + if (node->tableContext != NULL) + { MemoryContextDelete(node->tableContext); + node->tableContext = NULL; + } /* * close down subplans */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; ExecEndNode(innerPlanState(node)); + innerPlanState(node) = NULL; } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index e9f5732f33..f15902e840 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -244,6 +244,7 @@ ExecEndResult(ResultState *node) * shut down subplans */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } void diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c index 41c1ea37ad..a6813559e6 100644 --- a/src/backend/executor/nodeSamplescan.c +++ b/src/backend/executor/nodeSamplescan.c @@ -185,14 +185,17 @@ ExecEndSampleScan(SampleScanState *node) /* * Tell sampling function that we finished the scan. */ - if (node->tsmroutine->EndSampleScan) + if (node->tsmroutine != NULL && node->tsmroutine->EndSampleScan) node->tsmroutine->EndSampleScan(node); /* - * close heap scan + * close heap scan (no-op if we didn't start it) */ if (node->ss.ss_currentScanDesc) + { table_endscan(node->ss.ss_currentScanDesc); + node->ss.ss_currentScanDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index 49a5933aff..911266da07 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -183,18 +183,14 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) void ExecEndSeqScan(SeqScanState *node) { - TableScanDesc scanDesc; - - /* - * get information from node - */ - scanDesc = node->ss.ss_currentScanDesc; - /* - * close heap scan + * close heap scan (no-op if we didn't start it) */ - if (scanDesc != NULL) - table_endscan(scanDesc); + if (node->ss.ss_currentScanDesc != NULL) + { + table_endscan(node->ss.ss_currentScanDesc); + node->ss.ss_currentScanDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index 98c1b84d43..5c2861d243 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -583,10 +583,14 @@ void ExecEndSetOp(SetOpState *node) { /* free subsidiary stuff including hashtable */ - if (node->tableContext) + if (node->tableContext != NULL) + { MemoryContextDelete(node->tableContext); + node->tableContext = NULL; + } ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index eea7f2ae15..c8a35b64a8 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -307,13 +307,16 @@ ExecEndSort(SortState *node) * Release tuplesort resources */ if (node->tuplesortstate != NULL) + { tuplesort_end((Tuplesortstate *) node->tuplesortstate); - node->tuplesortstate = NULL; + node->tuplesortstate = NULL; + } /* * shut down the subplan */ ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; SO1_printf("ExecEndSort: %s\n", "sort node shutdown"); diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index 1ee6295660..91d7ae82ce 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -171,6 +171,7 @@ ExecEndSubqueryScan(SubqueryScanState *node) * close down subquery */ ExecEndNode(node->subplan); + node->subplan = NULL; } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c index a60dcd4943..80ed4b26a8 100644 --- a/src/backend/executor/nodeTableFuncscan.c +++ b/src/backend/executor/nodeTableFuncscan.c @@ -217,8 +217,10 @@ ExecEndTableFuncScan(TableFuncScanState *node) * Release tuplestore resources */ if (node->tupstore != NULL) + { tuplestore_end(node->tupstore); - node->tupstore = NULL; + node->tupstore = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c index da622d3f5f..9147e4afa8 100644 --- a/src/backend/executor/nodeTidrangescan.c +++ b/src/backend/executor/nodeTidrangescan.c @@ -327,10 +327,14 @@ ExecReScanTidRangeScan(TidRangeScanState *node) void ExecEndTidRangeScan(TidRangeScanState *node) { - TableScanDesc scan = node->ss.ss_currentScanDesc; - - if (scan != NULL) - table_endscan(scan); + /* + * close heap scan (no-op if we didn't start it) + */ + if (node->ss.ss_currentScanDesc != NULL) + { + table_endscan(node->ss.ss_currentScanDesc); + node->ss.ss_currentScanDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 15055077d0..74ec6afdcc 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -470,8 +470,14 @@ ExecReScanTidScan(TidScanState *node) void ExecEndTidScan(TidScanState *node) { - if (node->ss.ss_currentScanDesc) + /* + * close heap scan (no-op if we didn't start it) + */ + if (node->ss.ss_currentScanDesc != NULL) + { table_endscan(node->ss.ss_currentScanDesc); + node->ss.ss_currentScanDesc = NULL; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c index 01f951197c..13c556326a 100644 --- a/src/backend/executor/nodeUnique.c +++ b/src/backend/executor/nodeUnique.c @@ -169,6 +169,7 @@ void ExecEndUnique(UniqueState *node) { ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 77724a6daa..c4c6f009ba 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -1351,11 +1351,14 @@ release_partition(WindowAggState *winstate) * any aggregate temp data). We don't rely on retail pfree because some * aggregates might have allocated data we don't have direct pointers to. */ - MemoryContextResetAndDeleteChildren(winstate->partcontext); - MemoryContextResetAndDeleteChildren(winstate->aggcontext); + if (winstate->partcontext != NULL) + MemoryContextResetAndDeleteChildren(winstate->partcontext); + if (winstate->aggcontext != NULL) + MemoryContextResetAndDeleteChildren(winstate->aggcontext); for (i = 0; i < winstate->numaggs; i++) { - if (winstate->peragg[i].aggcontext != winstate->aggcontext) + if (winstate->peragg[i].aggcontext != NULL && + winstate->peragg[i].aggcontext != winstate->aggcontext) MemoryContextResetAndDeleteChildren(winstate->peragg[i].aggcontext); } @@ -2681,24 +2684,40 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) void ExecEndWindowAgg(WindowAggState *node) { - PlanState *outerPlan; int i; release_partition(node); for (i = 0; i < node->numaggs; i++) { - if (node->peragg[i].aggcontext != node->aggcontext) + if (node->peragg[i].aggcontext != NULL && + node->peragg[i].aggcontext != node->aggcontext) MemoryContextDelete(node->peragg[i].aggcontext); } - MemoryContextDelete(node->partcontext); - MemoryContextDelete(node->aggcontext); + if (node->partcontext != NULL) + { + MemoryContextDelete(node->partcontext); + node->partcontext = NULL; + } + if (node->aggcontext != NULL) + { + MemoryContextDelete(node->aggcontext); + node->aggcontext = NULL; + } - pfree(node->perfunc); - pfree(node->peragg); + if (node->perfunc != NULL) + { + pfree(node->perfunc); + node->perfunc = NULL; + } + if (node->peragg != NULL) + { + pfree(node->peragg); + node->peragg = NULL; + } - outerPlan = outerPlanState(node); - ExecEndNode(outerPlan); + ExecEndNode(outerPlanState(node)); + outerPlanState(node) = NULL; } /* ----------------- -- 2.35.3