1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-25 21:42:33 +03:00

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

really worked.  Until now.
This commit is contained in:
Tom Lane 2000-06-10 05:16:38 +00:00
parent 6307b01b53
commit 6bdbd41f2d
2 changed files with 74 additions and 57 deletions

View File

@ -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,
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
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)
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

View File

@ -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)
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)
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)
#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)
(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 */
rri = es_rri;
es_rri = NULL;
}
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 */
if (rri->ri_RelationDesc->rd_rel->relhasindex) /*
ExecOpenIndices(reloid, rri); * 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);
}
resultList = lcons(rri, resultList); /*
* 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)
* 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)
{ {
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)
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)
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)
*/ */
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)
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)
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