aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-06-10 05:16:38 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-06-10 05:16:38 +0000
commit6bdbd41f2dbbf7d2a00e35de9c823e5569e4c9a8 (patch)
tree3f47fcd2241993482cf5709185682a9057744349
parent6307b01b53b56fd155bc2ce8ff7dc424822288d5 (diff)
downloadpostgresql-6bdbd41f2dbbf7d2a00e35de9c823e5569e4c9a8.tar.gz
postgresql-6bdbd41f2dbbf7d2a00e35de9c823e5569e4c9a8.zip
nodeAppend tried to deal with multiple result relations, but apparently it never
really worked. Until now.
-rw-r--r--src/backend/executor/execMain.c42
-rw-r--r--src/backend/executor/nodeAppend.c93
2 files changed, 76 insertions, 59 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 7b17efc0b8f..78b006de421 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
*
*
* 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,
Plan *plan,
EState *estate);
-static void EndPlan(Plan *plan,
- EState *estate);
+static void EndPlan(Plan *plan, EState *estate);
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
CmdType operation,
int offsetTuples,
@@ -916,58 +915,43 @@ static void
EndPlan(Plan *plan, EState *estate)
{
RelationInfo *resultRelationInfo;
- Relation intoRelationDesc;
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
*/
if (estate->es_evalPlanQual != NULL)
EndEvalPlanQual(estate);
/*
- * shut down the query
+ * shut down the node-type-specific query processing
*/
ExecEndNode(plan, plan);
/*
* destroy the executor "tuple" table.
*/
- {
- TupleTable tupleTable = (TupleTable) estate->es_tupleTable;
-
- ExecDropTupleTable(tupleTable, true);
- estate->es_tupleTable = NULL;
- }
+ ExecDropTupleTable(estate->es_tupleTable, true);
+ estate->es_tupleTable = NULL;
/*
- * close the result relations if necessary, but hold locks on them
- * until xact commit
+ * close the result relation if necessary, but hold lock on it
+ * until xact commit. NB: must not do this till after ExecEndNode(),
+ * see nodeAppend.c ...
*/
+ resultRelationInfo = estate->es_result_relation_info;
if (resultRelationInfo != NULL)
{
- Relation resultRelationDesc;
-
- resultRelationDesc = resultRelationInfo->ri_RelationDesc;
- heap_close(resultRelationDesc, NoLock);
-
- /*
- * close indices on the result relation
- */
+ heap_close(resultRelationInfo->ri_RelationDesc, NoLock);
+ /* close indices on the result relation, too */
ExecCloseIndices(resultRelationInfo);
}
/*
* close the "into" relation if necessary, again keeping lock
*/
- if (intoRelationDesc != NULL)
- heap_close(intoRelationDesc, NoLock);
+ if (estate->es_into_relation_descriptor != NULL)
+ heap_close(estate->es_into_relation_descriptor, NoLock);
/*
* close any relations selected FOR UPDATE, again keeping locks
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 07759293a28..32cf75df3e1 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -8,7 +8,7 @@
*
*
* 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;
List *junkList;
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
@@ -201,8 +204,8 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
nplans = length(appendplans);
rtable = node->inheritrtable;
- CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
initialized = (bool *) palloc(nplans * sizeof(bool));
+ MemSet(initialized, 0, nplans * sizeof(bool));
/* ----------------
* create new AppendState for our append node
@@ -231,7 +234,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
#define APPEND_NSLOTS 1
/* ----------------
* 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);
@@ -247,34 +250,60 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
(node->inheritrelid == es_rri->ri_RangeTableIndex))
{
List *resultList = NIL;
+ Oid initial_reloid = RelationGetRelid(es_rri->ri_RelationDesc);
List *rtentryP;
+ inherited_result_rel = true;
+
foreach(rtentryP, rtable)
{
RangeTblEntry *rtentry = lfirst(rtentryP);
- Oid reloid;
+ Oid reloid = rtentry->relid;
RelationInfo *rri;
- reloid = rtentry->relid;
- rri = makeNode(RelationInfo);
- rri->ri_RangeTableIndex = es_rri->ri_RangeTableIndex;
- 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);
-
- resultList = lcons(rri, resultList);
+ /*
+ * We must recycle the RelationInfo already opened by InitPlan()
+ * for the parent rel, else we will leak the associated relcache
+ * refcount.
+ */
+ if (reloid == initial_reloid)
+ {
+ 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 */
+
+ /*
+ * 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
- order as the rtentry list otherwise update or delete on
- inheritance hierarchies won't work.
- */
- appendstate->as_result_relation_info_list = lreverse(resultList);
+
+ appendstate->as_result_relation_info_list = resultList;
+ /* Check that we recycled InitPlan()'s RelationInfo */
+ Assert(es_rri == NULL);
+ /* Just for paranoia's sake, clear link until we set it properly */
+ estate->es_result_relation_info = NULL;
}
+
/* ----------------
* call ExecInitNode on each of the plans in our list
* 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
* ---------------
*/
- if ((es_rri != (RelationInfo *) NULL) &&
- (node->inheritrelid == es_rri->ri_RangeTableIndex))
+ if (inherited_result_rel)
{
JunkFilter *j = ExecInitJunkFilter(initNode->targetlist,
ExecGetTupType(initNode));
@@ -361,7 +389,6 @@ ExecProcAppend(Append *node)
{
EState *estate;
AppendState *appendstate;
-
int whichplan;
List *appendplans;
Plan *subnode;
@@ -376,7 +403,6 @@ ExecProcAppend(Append *node)
appendstate = node->appendstate;
estate = node->plan.state;
direction = estate->es_direction;
-
appendplans = node->appendplans;
whichplan = appendstate->as_whichplan;
result_slot = appendstate->cstate.cs_ResultTupleSlot;
@@ -448,19 +474,20 @@ ExecProcAppend(Append *node)
void
ExecEndAppend(Append *node)
{
+ EState *estate;
AppendState *appendstate;
int nplans;
List *appendplans;
bool *initialized;
int i;
List *resultRelationInfoList;
- RelationInfo *resultRelationInfo;
/* ----------------
* get information from the node
* ----------------
*/
appendstate = node->appendstate;
+ estate = node->plan.state;
appendplans = node->appendplans;
nplans = appendstate->as_nplans;
initialized = appendstate->as_initialized;
@@ -471,7 +498,7 @@ ExecEndAppend(Append *node)
*/
for (i = 0; i < nplans; i++)
{
- if (initialized[i] == TRUE)
+ if (initialized[i])
ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node);
}
@@ -482,6 +509,7 @@ ExecEndAppend(Append *node)
resultRelationInfoList = appendstate->as_result_relation_info_list;
while (resultRelationInfoList != NIL)
{
+ RelationInfo *resultRelationInfo;
Relation resultRelationDesc;
resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList);
@@ -490,8 +518,13 @@ ExecEndAppend(Append *node)
pfree(resultRelationInfo);
resultRelationInfoList = lnext(resultRelationInfoList);
}
- if (appendstate->as_result_relation_info_list)
- pfree(appendstate->as_result_relation_info_list);
+ appendstate->as_result_relation_info_list = NIL;
+ /*
+ * 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