From f7902c69704598e9dbbc1ee72d42bc9ca6c98a21 Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Thu, 28 Sep 2023 16:56:29 +0900 Subject: [PATCH v49 1/8] Assorted tightening in various ExecEnd()* routines This includes adding NULLness checks on pointers before cleaning them in up. Many ExecEnd*() routines already perform this check, but a few instances remain. These NULLness checks might seem redundant as things stand since the 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. This also adds a guard at the begigging of EvalPlanQualEnd() to return early if the EPQState does not appear to have been initialized. That case can happen if the corresponding ExecInit*() routine returned early without calling EvalPlanQualInit(). While at it, this commit ensures that pointers are consistently set to NULL after cleanup in all ExecEnd*() routines. Finally, for enhanced consistency, the format of NULLness checks has been standardized to "if (pointer != NULL)", replacing the previous "if (pointer)" style. Reviewed-by: Robert Haas Discussion: https://postgr.es/m/CA+HiwqFGkMSge6TgC9KQzde0ohpAycLQuV7ooitEEpbKB0O_mg@mail.gmail.com --- 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 ++++++++++++++----- 37 files changed, 248 insertions(+), 120 deletions(-) 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 25a2d78f15..03dd931527 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 1085b3c79d..9b13e2e552 100644 --- a/src/backend/executor/nodeMemoize.c +++ b/src/backend/executor/nodeMemoize.c @@ -1062,6 +1062,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; @@ -1108,12 +1109,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 3cdab77dfc..4b181621f9 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -1647,7 +1647,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 b16fbe9e22..bc82fb033a 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -4447,7 +4447,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; } } @@ -4455,12 +4457,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; + } } /* @@ -4472,6 +4478,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 ebd1406843..1211d871ea 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -368,7 +368,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 aee26d3813..514669558c 100644 --- a/src/backend/executor/nodeProjectSet.c +++ b/src/backend/executor/nodeProjectSet.c @@ -332,6 +332,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 3207643156..08637a64db 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 5a84969cf8..92bd2da8e0 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 6f97c35daa..d6b4ed2e42 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 3258305f57..0253c47448 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. */ - MemoryContextReset(winstate->partcontext); - MemoryContextReset(winstate->aggcontext); + if (winstate->partcontext != NULL) + MemoryContextReset(winstate->partcontext); + if (winstate->aggcontext != NULL) + MemoryContextReset(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) MemoryContextReset(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