Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6bdbd41

Browse files
committed
nodeAppend tried to deal with multiple result relations, but apparently it never
really worked. Until now.
1 parent 6307b01 commit 6bdbd41

File tree

2 files changed

+76
-59
lines changed

2 files changed

+76
-59
lines changed

src/backend/executor/execMain.c

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*
2828
*
2929
* IDENTIFICATION
30-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.115 2000/05/30 00:49:44 momjian Exp $
30+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.116 2000/06/10 05:16:38 tgl Exp $
3131
*
3232
*-------------------------------------------------------------------------
3333
*/
@@ -50,8 +50,7 @@ static TupleDesc InitPlan(CmdType operation,
5050
Query *parseTree,
5151
Plan *plan,
5252
EState *estate);
53-
static void EndPlan(Plan *plan,
54-
EState *estate);
53+
static void EndPlan(Plan *plan, EState *estate);
5554
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
5655
CmdType operation,
5756
int offsetTuples,
@@ -916,58 +915,43 @@ static void
916915
EndPlan(Plan *plan, EState *estate)
917916
{
918917
RelationInfo *resultRelationInfo;
919-
Relation intoRelationDesc;
920918
List *l;
921919

922-
/*
923-
* get information from state
924-
*/
925-
resultRelationInfo = estate->es_result_relation_info;
926-
intoRelationDesc = estate->es_into_relation_descriptor;
927-
928920
/*
929921
* shut down any PlanQual processing we were doing
930922
*/
931923
if (estate->es_evalPlanQual != NULL)
932924
EndEvalPlanQual(estate);
933925

934926
/*
935-
* shut down the query
927+
* shut down the node-type-specific query processing
936928
*/
937929
ExecEndNode(plan, plan);
938930

939931
/*
940932
* destroy the executor "tuple" table.
941933
*/
942-
{
943-
TupleTable tupleTable = (TupleTable) estate->es_tupleTable;
944-
945-
ExecDropTupleTable(tupleTable, true);
946-
estate->es_tupleTable = NULL;
947-
}
934+
ExecDropTupleTable(estate->es_tupleTable, true);
935+
estate->es_tupleTable = NULL;
948936

949937
/*
950-
* close the result relations if necessary, but hold locks on them
951-
* until xact commit
938+
* close the result relation if necessary, but hold lock on it
939+
* until xact commit. NB: must not do this till after ExecEndNode(),
940+
* see nodeAppend.c ...
952941
*/
942+
resultRelationInfo = estate->es_result_relation_info;
953943
if (resultRelationInfo != NULL)
954944
{
955-
Relation resultRelationDesc;
956-
957-
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
958-
heap_close(resultRelationDesc, NoLock);
959-
960-
/*
961-
* close indices on the result relation
962-
*/
945+
heap_close(resultRelationInfo->ri_RelationDesc, NoLock);
946+
/* close indices on the result relation, too */
963947
ExecCloseIndices(resultRelationInfo);
964948
}
965949

966950
/*
967951
* close the "into" relation if necessary, again keeping lock
968952
*/
969-
if (intoRelationDesc != NULL)
970-
heap_close(intoRelationDesc, NoLock);
953+
if (estate->es_into_relation_descriptor != NULL)
954+
heap_close(estate->es_into_relation_descriptor, NoLock);
971955

972956
/*
973957
* close any relations selected FOR UPDATE, again keeping locks

src/backend/executor/nodeAppend.c

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.31 2000/06/09 01:44:09 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.32 2000/06/10 05:16:38 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -189,6 +189,9 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
189189
Plan *initNode;
190190
List *junkList;
191191
RelationInfo *es_rri = estate->es_result_relation_info;
192+
bool inherited_result_rel = false;
193+
194+
CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
192195

193196
/* ----------------
194197
* assign execution state to node and get information
@@ -201,8 +204,8 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
201204
nplans = length(appendplans);
202205
rtable = node->inheritrtable;
203206

204-
CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
205207
initialized = (bool *) palloc(nplans * sizeof(bool));
208+
MemSet(initialized, 0, nplans * sizeof(bool));
206209

207210
/* ----------------
208211
* create new AppendState for our append node
@@ -231,7 +234,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
231234
#define APPEND_NSLOTS 1
232235
/* ----------------
233236
* append nodes still have Result slots, which hold pointers
234-
* to tuples, so we have to initialize them..
237+
* to tuples, so we have to initialize them.
235238
* ----------------
236239
*/
237240
ExecInitResultTupleSlot(estate, &appendstate->cstate);
@@ -247,34 +250,60 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
247250
(node->inheritrelid == es_rri->ri_RangeTableIndex))
248251
{
249252
List *resultList = NIL;
253+
Oid initial_reloid = RelationGetRelid(es_rri->ri_RelationDesc);
250254
List *rtentryP;
251255

256+
inherited_result_rel = true;
257+
252258
foreach(rtentryP, rtable)
253259
{
254260
RangeTblEntry *rtentry = lfirst(rtentryP);
255-
Oid reloid;
261+
Oid reloid = rtentry->relid;
256262
RelationInfo *rri;
257263

258-
reloid = rtentry->relid;
259-
rri = makeNode(RelationInfo);
260-
rri->ri_RangeTableIndex = es_rri->ri_RangeTableIndex;
261-
rri->ri_RelationDesc = heap_open(reloid, RowExclusiveLock);
262-
rri->ri_NumIndices = 0;
263-
rri->ri_IndexRelationDescs = NULL; /* index descs */
264-
rri->ri_IndexRelationInfo = NULL; /* index key info */
265-
266-
if (rri->ri_RelationDesc->rd_rel->relhasindex)
267-
ExecOpenIndices(reloid, rri);
268-
269-
resultList = lcons(rri, resultList);
264+
/*
265+
* We must recycle the RelationInfo already opened by InitPlan()
266+
* for the parent rel, else we will leak the associated relcache
267+
* refcount.
268+
*/
269+
if (reloid == initial_reloid)
270+
{
271+
Assert(es_rri != NULL); /* check we didn't use it already */
272+
rri = es_rri;
273+
es_rri = NULL;
274+
}
275+
else
276+
{
277+
rri = makeNode(RelationInfo);
278+
rri->ri_RangeTableIndex = node->inheritrelid;
279+
rri->ri_RelationDesc = heap_open(reloid, RowExclusiveLock);
280+
rri->ri_NumIndices = 0;
281+
rri->ri_IndexRelationDescs = NULL; /* index descs */
282+
rri->ri_IndexRelationInfo = NULL; /* index key info */
283+
284+
/*
285+
* XXX if the operation is a DELETE then we need not open
286+
* indices, but how to tell that here?
287+
*/
288+
if (rri->ri_RelationDesc->rd_rel->relhasindex)
289+
ExecOpenIndices(reloid, rri);
290+
}
291+
292+
/*
293+
* NB: the as_result_relation_info_list must be in the same
294+
* order as the rtentry list otherwise update or delete on
295+
* inheritance hierarchies won't work.
296+
*/
297+
resultList = lappend(resultList, rri);
270298
}
271-
/*
272-
The as_result_relation_info_list must be in the same
273-
order as the rtentry list otherwise update or delete on
274-
inheritance hierarchies won't work.
275-
*/
276-
appendstate->as_result_relation_info_list = lreverse(resultList);
299+
300+
appendstate->as_result_relation_info_list = resultList;
301+
/* Check that we recycled InitPlan()'s RelationInfo */
302+
Assert(es_rri == NULL);
303+
/* Just for paranoia's sake, clear link until we set it properly */
304+
estate->es_result_relation_info = NULL;
277305
}
306+
278307
/* ----------------
279308
* call ExecInitNode on each of the plans in our list
280309
* and save the results into the array "initialized"
@@ -304,8 +333,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
304333
* the one that we're looking at the subclasses of
305334
* ---------------
306335
*/
307-
if ((es_rri != (RelationInfo *) NULL) &&
308-
(node->inheritrelid == es_rri->ri_RangeTableIndex))
336+
if (inherited_result_rel)
309337
{
310338
JunkFilter *j = ExecInitJunkFilter(initNode->targetlist,
311339
ExecGetTupType(initNode));
@@ -361,7 +389,6 @@ ExecProcAppend(Append *node)
361389
{
362390
EState *estate;
363391
AppendState *appendstate;
364-
365392
int whichplan;
366393
List *appendplans;
367394
Plan *subnode;
@@ -376,7 +403,6 @@ ExecProcAppend(Append *node)
376403
appendstate = node->appendstate;
377404
estate = node->plan.state;
378405
direction = estate->es_direction;
379-
380406
appendplans = node->appendplans;
381407
whichplan = appendstate->as_whichplan;
382408
result_slot = appendstate->cstate.cs_ResultTupleSlot;
@@ -448,19 +474,20 @@ ExecProcAppend(Append *node)
448474
void
449475
ExecEndAppend(Append *node)
450476
{
477+
EState *estate;
451478
AppendState *appendstate;
452479
int nplans;
453480
List *appendplans;
454481
bool *initialized;
455482
int i;
456483
List *resultRelationInfoList;
457-
RelationInfo *resultRelationInfo;
458484

459485
/* ----------------
460486
* get information from the node
461487
* ----------------
462488
*/
463489
appendstate = node->appendstate;
490+
estate = node->plan.state;
464491
appendplans = node->appendplans;
465492
nplans = appendstate->as_nplans;
466493
initialized = appendstate->as_initialized;
@@ -471,7 +498,7 @@ ExecEndAppend(Append *node)
471498
*/
472499
for (i = 0; i < nplans; i++)
473500
{
474-
if (initialized[i] == TRUE)
501+
if (initialized[i])
475502
ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node);
476503
}
477504

@@ -482,6 +509,7 @@ ExecEndAppend(Append *node)
482509
resultRelationInfoList = appendstate->as_result_relation_info_list;
483510
while (resultRelationInfoList != NIL)
484511
{
512+
RelationInfo *resultRelationInfo;
485513
Relation resultRelationDesc;
486514

487515
resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList);
@@ -490,8 +518,13 @@ ExecEndAppend(Append *node)
490518
pfree(resultRelationInfo);
491519
resultRelationInfoList = lnext(resultRelationInfoList);
492520
}
493-
if (appendstate->as_result_relation_info_list)
494-
pfree(appendstate->as_result_relation_info_list);
521+
appendstate->as_result_relation_info_list = NIL;
522+
/*
523+
* This next step is critical to prevent EndPlan() from trying to close
524+
* an already-closed-and-deleted RelationInfo --- es_result_relation_info
525+
* is pointing at one of the nodes we just zapped above.
526+
*/
527+
estate->es_result_relation_info = NULL;
495528

496529
/*
497530
* XXX should free appendstate->as_rtentries and

0 commit comments

Comments
 (0)