Skip to content
Snippets Groups Projects
Commit 6bdbd41f authored by Tom Lane's avatar Tom Lane
Browse files

nodeAppend tried to deal with multiple result relations, but apparently it never

really worked.  Until now.
parent 6307b01b
Branches
Tags
No related merge requests found
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.115 2000/05/30 00:49:44 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.116 2000/06/10 05:16:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -50,8 +50,7 @@ static TupleDesc InitPlan(CmdType operation, ...@@ -50,8 +50,7 @@ static TupleDesc InitPlan(CmdType operation,
Query *parseTree, Query *parseTree,
Plan *plan, Plan *plan,
EState *estate); EState *estate);
static void EndPlan(Plan *plan, static void EndPlan(Plan *plan, EState *estate);
EState *estate);
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan, static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
CmdType operation, CmdType operation,
int offsetTuples, int offsetTuples,
...@@ -916,15 +915,8 @@ static void ...@@ -916,15 +915,8 @@ static void
EndPlan(Plan *plan, EState *estate) EndPlan(Plan *plan, EState *estate)
{ {
RelationInfo *resultRelationInfo; RelationInfo *resultRelationInfo;
Relation intoRelationDesc;
List *l; List *l;
/*
* get information from state
*/
resultRelationInfo = estate->es_result_relation_info;
intoRelationDesc = estate->es_into_relation_descriptor;
/* /*
* shut down any PlanQual processing we were doing * shut down any PlanQual processing we were doing
*/ */
...@@ -932,42 +924,34 @@ EndPlan(Plan *plan, EState *estate) ...@@ -932,42 +924,34 @@ EndPlan(Plan *plan, EState *estate)
EndEvalPlanQual(estate); EndEvalPlanQual(estate);
/* /*
* shut down the query * shut down the node-type-specific query processing
*/ */
ExecEndNode(plan, plan); ExecEndNode(plan, plan);
/* /*
* destroy the executor "tuple" table. * destroy the executor "tuple" table.
*/ */
{ ExecDropTupleTable(estate->es_tupleTable, true);
TupleTable tupleTable = (TupleTable) estate->es_tupleTable; estate->es_tupleTable = NULL;
ExecDropTupleTable(tupleTable, true);
estate->es_tupleTable = NULL;
}
/* /*
* close the result relations if necessary, but hold locks on them * close the result relation if necessary, but hold lock on it
* until xact commit * until xact commit. NB: must not do this till after ExecEndNode(),
* see nodeAppend.c ...
*/ */
resultRelationInfo = estate->es_result_relation_info;
if (resultRelationInfo != NULL) if (resultRelationInfo != NULL)
{ {
Relation resultRelationDesc; heap_close(resultRelationInfo->ri_RelationDesc, NoLock);
/* close indices on the result relation, too */
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
heap_close(resultRelationDesc, NoLock);
/*
* close indices on the result relation
*/
ExecCloseIndices(resultRelationInfo); ExecCloseIndices(resultRelationInfo);
} }
/* /*
* close the "into" relation if necessary, again keeping lock * close the "into" relation if necessary, again keeping lock
*/ */
if (intoRelationDesc != NULL) if (estate->es_into_relation_descriptor != NULL)
heap_close(intoRelationDesc, NoLock); heap_close(estate->es_into_relation_descriptor, NoLock);
/* /*
* close any relations selected FOR UPDATE, again keeping locks * close any relations selected FOR UPDATE, again keeping locks
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.31 2000/06/09 01:44:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.32 2000/06/10 05:16:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -189,6 +189,9 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) ...@@ -189,6 +189,9 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
Plan *initNode; Plan *initNode;
List *junkList; List *junkList;
RelationInfo *es_rri = estate->es_result_relation_info; RelationInfo *es_rri = estate->es_result_relation_info;
bool inherited_result_rel = false;
CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
/* ---------------- /* ----------------
* assign execution state to node and get information * assign execution state to node and get information
...@@ -201,8 +204,8 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) ...@@ -201,8 +204,8 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
nplans = length(appendplans); nplans = length(appendplans);
rtable = node->inheritrtable; rtable = node->inheritrtable;
CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
initialized = (bool *) palloc(nplans * sizeof(bool)); initialized = (bool *) palloc(nplans * sizeof(bool));
MemSet(initialized, 0, nplans * sizeof(bool));
/* ---------------- /* ----------------
* create new AppendState for our append node * create new AppendState for our append node
...@@ -231,7 +234,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) ...@@ -231,7 +234,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
#define APPEND_NSLOTS 1 #define APPEND_NSLOTS 1
/* ---------------- /* ----------------
* append nodes still have Result slots, which hold pointers * append nodes still have Result slots, which hold pointers
* to tuples, so we have to initialize them.. * to tuples, so we have to initialize them.
* ---------------- * ----------------
*/ */
ExecInitResultTupleSlot(estate, &appendstate->cstate); ExecInitResultTupleSlot(estate, &appendstate->cstate);
...@@ -247,34 +250,60 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) ...@@ -247,34 +250,60 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
(node->inheritrelid == es_rri->ri_RangeTableIndex)) (node->inheritrelid == es_rri->ri_RangeTableIndex))
{ {
List *resultList = NIL; List *resultList = NIL;
Oid initial_reloid = RelationGetRelid(es_rri->ri_RelationDesc);
List *rtentryP; List *rtentryP;
inherited_result_rel = true;
foreach(rtentryP, rtable) foreach(rtentryP, rtable)
{ {
RangeTblEntry *rtentry = lfirst(rtentryP); RangeTblEntry *rtentry = lfirst(rtentryP);
Oid reloid; Oid reloid = rtentry->relid;
RelationInfo *rri; RelationInfo *rri;
reloid = rtentry->relid; /*
rri = makeNode(RelationInfo); * We must recycle the RelationInfo already opened by InitPlan()
rri->ri_RangeTableIndex = es_rri->ri_RangeTableIndex; * for the parent rel, else we will leak the associated relcache
rri->ri_RelationDesc = heap_open(reloid, RowExclusiveLock); * refcount.
rri->ri_NumIndices = 0; */
rri->ri_IndexRelationDescs = NULL; /* index descs */ if (reloid == initial_reloid)
rri->ri_IndexRelationInfo = NULL; /* index key info */ {
Assert(es_rri != NULL); /* check we didn't use it already */
if (rri->ri_RelationDesc->rd_rel->relhasindex) rri = es_rri;
ExecOpenIndices(reloid, rri); es_rri = NULL;
}
resultList = lcons(rri, resultList); else
{
rri = makeNode(RelationInfo);
rri->ri_RangeTableIndex = node->inheritrelid;
rri->ri_RelationDesc = heap_open(reloid, RowExclusiveLock);
rri->ri_NumIndices = 0;
rri->ri_IndexRelationDescs = NULL; /* index descs */
rri->ri_IndexRelationInfo = NULL; /* index key info */
/*
* XXX if the operation is a DELETE then we need not open
* indices, but how to tell that here?
*/
if (rri->ri_RelationDesc->rd_rel->relhasindex)
ExecOpenIndices(reloid, rri);
}
/*
* NB: the as_result_relation_info_list must be in the same
* order as the rtentry list otherwise update or delete on
* inheritance hierarchies won't work.
*/
resultList = lappend(resultList, rri);
} }
/*
The as_result_relation_info_list must be in the same appendstate->as_result_relation_info_list = resultList;
order as the rtentry list otherwise update or delete on /* Check that we recycled InitPlan()'s RelationInfo */
inheritance hierarchies won't work. Assert(es_rri == NULL);
*/ /* Just for paranoia's sake, clear link until we set it properly */
appendstate->as_result_relation_info_list = lreverse(resultList); estate->es_result_relation_info = NULL;
} }
/* ---------------- /* ----------------
* call ExecInitNode on each of the plans in our list * call ExecInitNode on each of the plans in our list
* and save the results into the array "initialized" * and save the results into the array "initialized"
...@@ -304,8 +333,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) ...@@ -304,8 +333,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
* the one that we're looking at the subclasses of * the one that we're looking at the subclasses of
* --------------- * ---------------
*/ */
if ((es_rri != (RelationInfo *) NULL) && if (inherited_result_rel)
(node->inheritrelid == es_rri->ri_RangeTableIndex))
{ {
JunkFilter *j = ExecInitJunkFilter(initNode->targetlist, JunkFilter *j = ExecInitJunkFilter(initNode->targetlist,
ExecGetTupType(initNode)); ExecGetTupType(initNode));
...@@ -361,7 +389,6 @@ ExecProcAppend(Append *node) ...@@ -361,7 +389,6 @@ ExecProcAppend(Append *node)
{ {
EState *estate; EState *estate;
AppendState *appendstate; AppendState *appendstate;
int whichplan; int whichplan;
List *appendplans; List *appendplans;
Plan *subnode; Plan *subnode;
...@@ -376,7 +403,6 @@ ExecProcAppend(Append *node) ...@@ -376,7 +403,6 @@ ExecProcAppend(Append *node)
appendstate = node->appendstate; appendstate = node->appendstate;
estate = node->plan.state; estate = node->plan.state;
direction = estate->es_direction; direction = estate->es_direction;
appendplans = node->appendplans; appendplans = node->appendplans;
whichplan = appendstate->as_whichplan; whichplan = appendstate->as_whichplan;
result_slot = appendstate->cstate.cs_ResultTupleSlot; result_slot = appendstate->cstate.cs_ResultTupleSlot;
...@@ -448,19 +474,20 @@ ExecProcAppend(Append *node) ...@@ -448,19 +474,20 @@ ExecProcAppend(Append *node)
void void
ExecEndAppend(Append *node) ExecEndAppend(Append *node)
{ {
EState *estate;
AppendState *appendstate; AppendState *appendstate;
int nplans; int nplans;
List *appendplans; List *appendplans;
bool *initialized; bool *initialized;
int i; int i;
List *resultRelationInfoList; List *resultRelationInfoList;
RelationInfo *resultRelationInfo;
/* ---------------- /* ----------------
* get information from the node * get information from the node
* ---------------- * ----------------
*/ */
appendstate = node->appendstate; appendstate = node->appendstate;
estate = node->plan.state;
appendplans = node->appendplans; appendplans = node->appendplans;
nplans = appendstate->as_nplans; nplans = appendstate->as_nplans;
initialized = appendstate->as_initialized; initialized = appendstate->as_initialized;
...@@ -471,7 +498,7 @@ ExecEndAppend(Append *node) ...@@ -471,7 +498,7 @@ ExecEndAppend(Append *node)
*/ */
for (i = 0; i < nplans; i++) for (i = 0; i < nplans; i++)
{ {
if (initialized[i] == TRUE) if (initialized[i])
ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node); ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node);
} }
...@@ -482,6 +509,7 @@ ExecEndAppend(Append *node) ...@@ -482,6 +509,7 @@ ExecEndAppend(Append *node)
resultRelationInfoList = appendstate->as_result_relation_info_list; resultRelationInfoList = appendstate->as_result_relation_info_list;
while (resultRelationInfoList != NIL) while (resultRelationInfoList != NIL)
{ {
RelationInfo *resultRelationInfo;
Relation resultRelationDesc; Relation resultRelationDesc;
resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList); resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList);
...@@ -490,8 +518,13 @@ ExecEndAppend(Append *node) ...@@ -490,8 +518,13 @@ ExecEndAppend(Append *node)
pfree(resultRelationInfo); pfree(resultRelationInfo);
resultRelationInfoList = lnext(resultRelationInfoList); resultRelationInfoList = lnext(resultRelationInfoList);
} }
if (appendstate->as_result_relation_info_list) appendstate->as_result_relation_info_list = NIL;
pfree(appendstate->as_result_relation_info_list); /*
* This next step is critical to prevent EndPlan() from trying to close
* an already-closed-and-deleted RelationInfo --- es_result_relation_info
* is pointing at one of the nodes we just zapped above.
*/
estate->es_result_relation_info = NULL;
/* /*
* XXX should free appendstate->as_rtentries and * XXX should free appendstate->as_rtentries and
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment