aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execMain.c376
-rw-r--r--src/backend/executor/execQual.c3
-rw-r--r--src/backend/executor/execTuples.c20
-rw-r--r--src/backend/executor/execUtils.c40
-rw-r--r--src/backend/executor/functions.c3
-rw-r--r--src/backend/executor/nodeAppend.c194
-rw-r--r--src/backend/executor/nodeSeqscan.c4
7 files changed, 258 insertions, 382 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index a26acc9a763..d9d02654970 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.131 2000/10/26 21:35:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.132 2000/11/12 00:36:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -50,6 +50,10 @@ static TupleDesc InitPlan(CmdType operation,
Query *parseTree,
Plan *plan,
EState *estate);
+static void initResultRelInfo(ResultRelInfo *resultRelInfo,
+ Index resultRelationIndex,
+ List *rangeTable,
+ CmdType operation);
static void EndPlan(Plan *plan, EState *estate);
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
CmdType operation,
@@ -310,10 +314,6 @@ ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan)
* ExecCheckPlanPerms
* Recursively scan the plan tree to check access permissions in
* subplans.
- *
- * We also need to look at the local rangetables in Append plan nodes,
- * which is pretty bogus --- most likely, those tables should be mentioned
- * in the query's main rangetable. But at the moment, they're not.
*/
static void
ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation)
@@ -365,27 +365,11 @@ ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation)
Append *app = (Append *) plan;
List *appendplans;
- if (app->inheritrelid > 0)
+ foreach(appendplans, app->appendplans)
{
- /* Append implements expansion of inheritance */
- ExecCheckRTPerms(app->inheritrtable, operation);
-
- foreach(appendplans, app->appendplans)
- {
- ExecCheckPlanPerms((Plan *) lfirst(appendplans),
- rangeTable,
- operation);
- }
- }
- else
- {
- /* Append implements UNION, which must be a SELECT */
- foreach(appendplans, app->appendplans)
- {
- ExecCheckPlanPerms((Plan *) lfirst(appendplans),
- rangeTable,
- CMD_SELECT);
- }
+ ExecCheckPlanPerms((Plan *) lfirst(appendplans),
+ rangeTable,
+ operation);
}
break;
}
@@ -518,10 +502,8 @@ static TupleDesc
InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
{
List *rangeTable;
- int resultRelation;
Relation intoRelationDesc;
TupleDesc tupType;
- List *targetList;
/*
* Do permissions checks.
@@ -532,7 +514,6 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
* get information from query descriptor
*/
rangeTable = parseTree->rtable;
- resultRelation = parseTree->resultRelation;
/*
* initialize the node's execution state
@@ -540,63 +521,61 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
estate->es_range_table = rangeTable;
/*
- * initialize result relation stuff
+ * if there is a result relation, initialize result relation stuff
*/
-
- if (resultRelation != 0 && operation != CMD_SELECT)
+ if (parseTree->resultRelation != 0 && operation != CMD_SELECT)
{
+ List *resultRelations = parseTree->resultRelations;
+ int numResultRelations;
+ ResultRelInfo *resultRelInfos;
- /*
- * if we have a result relation, open it and initialize the result
- * relation info stuff.
- */
- RelationInfo *resultRelationInfo;
- Index resultRelationIndex;
- Oid resultRelationOid;
- Relation resultRelationDesc;
-
- resultRelationIndex = resultRelation;
- resultRelationOid = getrelid(resultRelationIndex, rangeTable);
- resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
-
- if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
- elog(ERROR, "You can't change sequence relation %s",
- RelationGetRelationName(resultRelationDesc));
-
- if (resultRelationDesc->rd_rel->relkind == RELKIND_TOASTVALUE)
- elog(ERROR, "You can't change toast relation %s",
- RelationGetRelationName(resultRelationDesc));
-
- if (resultRelationDesc->rd_rel->relkind == RELKIND_VIEW)
- elog(ERROR, "You can't change view relation %s",
- RelationGetRelationName(resultRelationDesc));
-
- resultRelationInfo = makeNode(RelationInfo);
- resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
- resultRelationInfo->ri_RelationDesc = resultRelationDesc;
- resultRelationInfo->ri_NumIndices = 0;
- resultRelationInfo->ri_IndexRelationDescs = NULL;
- resultRelationInfo->ri_IndexRelationInfo = NULL;
+ if (resultRelations != NIL)
+ {
+ /*
+ * Multiple result relations (due to inheritance)
+ * parseTree->resultRelations identifies them all
+ */
+ ResultRelInfo *resultRelInfo;
- /*
- * If there are indices on the result relation, open them and save
- * descriptors in the result relation info, so that we can add new
- * index entries for the tuples we add/update. We need not do
- * this for a DELETE, however, since deletion doesn't affect
- * indexes.
- */
- if (resultRelationDesc->rd_rel->relhasindex &&
- operation != CMD_DELETE)
- ExecOpenIndices(resultRelationInfo);
+ numResultRelations = length(resultRelations);
+ resultRelInfos = (ResultRelInfo *)
+ palloc(numResultRelations * sizeof(ResultRelInfo));
+ resultRelInfo = resultRelInfos;
+ while (resultRelations != NIL)
+ {
+ initResultRelInfo(resultRelInfo,
+ lfirsti(resultRelations),
+ rangeTable,
+ operation);
+ resultRelInfo++;
+ resultRelations = lnext(resultRelations);
+ }
+ }
+ else
+ {
+ /*
+ * Single result relation identified by parseTree->resultRelation
+ */
+ numResultRelations = 1;
+ resultRelInfos = (ResultRelInfo *) palloc(sizeof(ResultRelInfo));
+ initResultRelInfo(resultRelInfos,
+ parseTree->resultRelation,
+ rangeTable,
+ operation);
+ }
- estate->es_result_relation_info = resultRelationInfo;
+ estate->es_result_relations = resultRelInfos;
+ estate->es_num_result_relations = numResultRelations;
+ /* Initialize to first or only result rel */
+ estate->es_result_relation_info = resultRelInfos;
}
else
{
-
/*
* if no result relation, then set state appropriately
*/
+ estate->es_result_relations = NULL;
+ estate->es_num_result_relations = 0;
estate->es_result_relation_info = NULL;
}
@@ -642,19 +621,17 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
ExecInitNode(plan, estate, NULL);
/*
- * get the tuple descriptor describing the type of tuples to return..
+ * Get the tuple descriptor describing the type of tuples to return.
* (this is especially important if we are creating a relation with
* "retrieve into")
*/
tupType = ExecGetTupType(plan); /* tuple descriptor */
- targetList = plan->targetlist;
/*
- * Now that we have the target list, initialize the junk filter if
- * needed. SELECT and INSERT queries need a filter if there are any
- * junk attrs in the tlist. UPDATE and DELETE always need one, since
- * there's always a junk 'ctid' attribute present --- no need to look
- * first.
+ * Initialize the junk filter if needed. SELECT and INSERT queries need
+ * a filter if there are any junk attrs in the tlist. UPDATE and
+ * DELETE always need one, since there's always a junk 'ctid' attribute
+ * present --- no need to look first.
*/
{
bool junk_filter_needed = false;
@@ -664,7 +641,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
{
case CMD_SELECT:
case CMD_INSERT:
- foreach(tlist, targetList)
+ foreach(tlist, plan->targetlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tlist);
@@ -685,12 +662,55 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
if (junk_filter_needed)
{
- JunkFilter *j = ExecInitJunkFilter(targetList, tupType);
+ /*
+ * If there are multiple result relations, each one needs
+ * its own junk filter. Note this is only possible for
+ * UPDATE/DELETE, so we can't be fooled by some needing
+ * a filter and some not.
+ */
+ if (parseTree->resultRelations != NIL)
+ {
+ List *subplans;
+ ResultRelInfo *resultRelInfo;
+
+ /* Top plan had better be an Append here. */
+ Assert(IsA(plan, Append));
+ Assert(((Append *) plan)->isTarget);
+ subplans = ((Append *) plan)->appendplans;
+ Assert(length(subplans) == estate->es_num_result_relations);
+ resultRelInfo = estate->es_result_relations;
+ while (subplans != NIL)
+ {
+ Plan *subplan = (Plan *) lfirst(subplans);
+ JunkFilter *j;
+
+ j = ExecInitJunkFilter(subplan->targetlist,
+ ExecGetTupType(subplan));
+ resultRelInfo->ri_junkFilter = j;
+ resultRelInfo++;
+ subplans = lnext(subplans);
+ }
+ /*
+ * Set active junkfilter too; at this point ExecInitAppend
+ * has already selected an active result relation...
+ */
+ estate->es_junkFilter =
+ estate->es_result_relation_info->ri_junkFilter;
+ }
+ else
+ {
+ /* Normal case with just one JunkFilter */
+ JunkFilter *j = ExecInitJunkFilter(plan->targetlist,
+ tupType);
- estate->es_junkFilter = j;
+ estate->es_junkFilter = j;
+ if (estate->es_result_relation_info)
+ estate->es_result_relation_info->ri_junkFilter = j;
- if (operation == CMD_SELECT)
- tupType = j->jf_cleanTupType;
+ /* For SELECT, want to return the cleaned tuple type */
+ if (operation == CMD_SELECT)
+ tupType = j->jf_cleanTupType;
+ }
}
else
estate->es_junkFilter = NULL;
@@ -762,6 +782,59 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
return tupType;
}
+/*
+ * Initialize ResultRelInfo data for one result relation
+ */
+static void
+initResultRelInfo(ResultRelInfo *resultRelInfo,
+ Index resultRelationIndex,
+ List *rangeTable,
+ CmdType operation)
+{
+ Oid resultRelationOid;
+ Relation resultRelationDesc;
+
+ resultRelationOid = getrelid(resultRelationIndex, rangeTable);
+ resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
+
+ switch (resultRelationDesc->rd_rel->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ elog(ERROR, "You can't change sequence relation %s",
+ RelationGetRelationName(resultRelationDesc));
+ break;
+ case RELKIND_TOASTVALUE:
+ elog(ERROR, "You can't change toast relation %s",
+ RelationGetRelationName(resultRelationDesc));
+ break;
+ case RELKIND_VIEW:
+ elog(ERROR, "You can't change view relation %s",
+ RelationGetRelationName(resultRelationDesc));
+ break;
+ }
+
+ MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
+ resultRelInfo->type = T_ResultRelInfo;
+ resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
+ resultRelInfo->ri_RelationDesc = resultRelationDesc;
+ resultRelInfo->ri_NumIndices = 0;
+ resultRelInfo->ri_IndexRelationDescs = NULL;
+ resultRelInfo->ri_IndexRelationInfo = NULL;
+ resultRelInfo->ri_ConstraintExprs = NULL;
+ resultRelInfo->ri_junkFilter = NULL;
+
+ /*
+ * If there are indices on the result relation, open them and save
+ * descriptors in the result relation info, so that we can add new
+ * index entries for the tuples we add/update. We need not do
+ * this for a DELETE, however, since deletion doesn't affect
+ * indexes.
+ */
+ if (resultRelationDesc->rd_rel->relhasindex &&
+ operation != CMD_DELETE)
+ ExecOpenIndices(resultRelInfo);
+}
+
/* ----------------------------------------------------------------
* EndPlan
*
@@ -771,7 +844,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
static void
EndPlan(Plan *plan, EState *estate)
{
- RelationInfo *resultRelationInfo;
+ ResultRelInfo *resultRelInfo;
+ int i;
List *l;
/*
@@ -792,16 +866,16 @@ EndPlan(Plan *plan, EState *estate)
estate->es_tupleTable = NULL;
/*
- * 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 ...
+ * close the result relation(s) if any, but hold locks
+ * until xact commit.
*/
- resultRelationInfo = estate->es_result_relation_info;
- if (resultRelationInfo != NULL)
+ resultRelInfo = estate->es_result_relations;
+ for (i = estate->es_num_result_relations; i > 0; i--)
{
- heap_close(resultRelationInfo->ri_RelationDesc, NoLock);
- /* close indices on the result relation, too */
- ExecCloseIndices(resultRelationInfo);
+ /* Close indices and then the relation itself */
+ ExecCloseIndices(resultRelInfo);
+ heap_close(resultRelInfo->ri_RelationDesc, NoLock);
+ resultRelInfo++;
}
/*
@@ -1116,7 +1190,7 @@ ExecAppend(TupleTableSlot *slot,
EState *estate)
{
HeapTuple tuple;
- RelationInfo *resultRelationInfo;
+ ResultRelInfo *resultRelInfo;
Relation resultRelationDesc;
int numIndices;
Oid newId;
@@ -1127,10 +1201,10 @@ ExecAppend(TupleTableSlot *slot,
tuple = slot->val;
/*
- * get information on the result relation
+ * get information on the (current) result relation
*/
- resultRelationInfo = estate->es_result_relation_info;
- resultRelationDesc = resultRelationInfo->ri_RelationDesc;
+ resultRelInfo = estate->es_result_relation_info;
+ resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW INSERT Triggers */
if (resultRelationDesc->trigdesc &&
@@ -1154,9 +1228,8 @@ ExecAppend(TupleTableSlot *slot,
/*
* Check the constraints of the tuple
*/
-
if (resultRelationDesc->rd_att->constr)
- ExecConstraints("ExecAppend", resultRelationDesc, slot, estate);
+ ExecConstraints("ExecAppend", resultRelInfo, slot, estate);
/*
* insert the tuple
@@ -1174,7 +1247,7 @@ ExecAppend(TupleTableSlot *slot,
* the tupleid of the new tuple is placed in the new tuple's t_ctid
* field.
*/
- numIndices = resultRelationInfo->ri_NumIndices;
+ numIndices = resultRelInfo->ri_NumIndices;
if (numIndices > 0)
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
@@ -1195,16 +1268,16 @@ ExecDelete(TupleTableSlot *slot,
ItemPointer tupleid,
EState *estate)
{
- RelationInfo *resultRelationInfo;
+ ResultRelInfo *resultRelInfo;
Relation resultRelationDesc;
ItemPointerData ctid;
int result;
/*
- * get the result relation information
+ * get information on the (current) result relation
*/
- resultRelationInfo = estate->es_result_relation_info;
- resultRelationDesc = resultRelationInfo->ri_RelationDesc;
+ resultRelInfo = estate->es_result_relation_info;
+ resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW DELETE Triggers */
if (resultRelationDesc->trigdesc &&
@@ -1237,7 +1310,7 @@ ldelete:;
else if (!(ItemPointerEquals(tupleid, &ctid)))
{
TupleTableSlot *epqslot = EvalPlanQual(estate,
- resultRelationInfo->ri_RangeTableIndex, &ctid);
+ resultRelInfo->ri_RangeTableIndex, &ctid);
if (!TupIsNull(epqslot))
{
@@ -1287,7 +1360,7 @@ ExecReplace(TupleTableSlot *slot,
EState *estate)
{
HeapTuple tuple;
- RelationInfo *resultRelationInfo;
+ ResultRelInfo *resultRelInfo;
Relation resultRelationDesc;
ItemPointerData ctid;
int result;
@@ -1308,10 +1381,10 @@ ExecReplace(TupleTableSlot *slot,
tuple = slot->val;
/*
- * get the result relation information
+ * get information on the (current) result relation
*/
- resultRelationInfo = estate->es_result_relation_info;
- resultRelationDesc = resultRelationInfo->ri_RelationDesc;
+ resultRelInfo = estate->es_result_relation_info;
+ resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW UPDATE Triggers */
if (resultRelationDesc->trigdesc &&
@@ -1335,9 +1408,8 @@ ExecReplace(TupleTableSlot *slot,
/*
* Check the constraints of the tuple
*/
-
if (resultRelationDesc->rd_att->constr)
- ExecConstraints("ExecReplace", resultRelationDesc, slot, estate);
+ ExecConstraints("ExecReplace", resultRelInfo, slot, estate);
/*
* replace the heap tuple
@@ -1358,7 +1430,7 @@ lreplace:;
else if (!(ItemPointerEquals(tupleid, &ctid)))
{
TupleTableSlot *epqslot = EvalPlanQual(estate,
- resultRelationInfo->ri_RangeTableIndex, &ctid);
+ resultRelInfo->ri_RangeTableIndex, &ctid);
if (!TupIsNull(epqslot))
{
@@ -1396,7 +1468,7 @@ lreplace:;
* there.
*/
- numIndices = resultRelationInfo->ri_NumIndices;
+ numIndices = resultRelInfo->ri_NumIndices;
if (numIndices > 0)
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
@@ -1406,8 +1478,10 @@ lreplace:;
}
static char *
-ExecRelCheck(Relation rel, TupleTableSlot *slot, EState *estate)
+ExecRelCheck(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate)
{
+ Relation rel = resultRelInfo->ri_RelationDesc;
int ncheck = rel->rd_att->constr->num_check;
ConstrCheck *check = rel->rd_att->constr->check;
ExprContext *econtext;
@@ -1416,6 +1490,24 @@ ExecRelCheck(Relation rel, TupleTableSlot *slot, EState *estate)
int i;
/*
+ * If first time through for this result relation, build expression
+ * nodetrees for rel's constraint expressions. Keep them in the
+ * per-query memory context so they'll survive throughout the query.
+ */
+ if (resultRelInfo->ri_ConstraintExprs == NULL)
+ {
+ oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
+ resultRelInfo->ri_ConstraintExprs =
+ (List **) palloc(ncheck * sizeof(List *));
+ for (i = 0; i < ncheck; i++)
+ {
+ qual = (List *) stringToNode(check[i].ccbin);
+ resultRelInfo->ri_ConstraintExprs[i] = qual;
+ }
+ MemoryContextSwitchTo(oldContext);
+ }
+
+ /*
* We will use the EState's per-tuple context for evaluating constraint
* expressions. Create it if it's not already there; if it is, reset it
* to free previously-used storage.
@@ -1431,58 +1523,13 @@ ExecRelCheck(Relation rel, TupleTableSlot *slot, EState *estate)
else
ResetExprContext(econtext);
- /*
- * If first time through for current result relation, set up econtext's
- * range table to refer to result rel, and build expression nodetrees
- * for rel's constraint expressions. All this stuff is kept in the
- * per-query memory context so it will still be here next time through.
- *
- * NOTE: if there are multiple result relations (eg, due to inheritance)
- * then we leak storage for prior rel's expressions and rangetable.
- * This should not be a big problem as long as result rels are processed
- * sequentially within a command.
- */
- if (econtext->ecxt_range_table == NIL ||
- getrelid(1, econtext->ecxt_range_table) != RelationGetRelid(rel))
- {
- RangeTblEntry *rte;
-
- /*
- * Make sure expressions, etc are placed in appropriate context.
- */
- oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
-
- rte = makeNode(RangeTblEntry);
-
- rte->relname = RelationGetRelationName(rel);
- rte->relid = RelationGetRelid(rel);
- rte->eref = makeNode(Attr);
- rte->eref->relname = rte->relname;
- /* other fields won't be used, leave them zero */
-
- /* Set up single-entry range table */
- econtext->ecxt_range_table = makeList1(rte);
-
- estate->es_result_relation_constraints =
- (List **) palloc(ncheck * sizeof(List *));
-
- for (i = 0; i < ncheck; i++)
- {
- qual = (List *) stringToNode(check[i].ccbin);
- estate->es_result_relation_constraints[i] = qual;
- }
-
- /* Done with building long-lived items */
- MemoryContextSwitchTo(oldContext);
- }
-
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext->ecxt_scantuple = slot;
/* And evaluate the constraints */
for (i = 0; i < ncheck; i++)
{
- qual = estate->es_result_relation_constraints[i];
+ qual = resultRelInfo->ri_ConstraintExprs[i];
/*
* NOTE: SQL92 specifies that a NULL result from a constraint
@@ -1498,9 +1545,10 @@ ExecRelCheck(Relation rel, TupleTableSlot *slot, EState *estate)
}
void
-ExecConstraints(char *caller, Relation rel,
+ExecConstraints(char *caller, ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, EState *estate)
{
+ Relation rel = resultRelInfo->ri_RelationDesc;
HeapTuple tuple = slot->val;
TupleConstr *constr = rel->rd_att->constr;
@@ -1524,7 +1572,7 @@ ExecConstraints(char *caller, Relation rel,
{
char *failed;
- if ((failed = ExecRelCheck(rel, slot, estate)) != NULL)
+ if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
elog(ERROR, "%s: rejected due to CHECK constraint %s",
caller, failed);
}
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 622ea2ef82c..beeff0db331 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.80 2000/08/24 23:34:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.81 2000/11/12 00:36:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -341,7 +341,6 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
tempSlot->ttc_descIsNew = true;
tempSlot->ttc_tupleDescriptor = (TupleDesc) NULL;
tempSlot->ttc_buffer = InvalidBuffer;
- tempSlot->ttc_whichplan = -1;
tup = heap_copytuple(heapTuple);
td = CreateTupleDescCopy(tuple_type);
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 408716abf83..65eef4141f4 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.42 2000/10/26 21:35:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.43 2000/11/12 00:36:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -303,7 +303,6 @@ ExecAllocTableSlot(TupleTable table)
slot->ttc_descIsNew = true;
slot->ttc_tupleDescriptor = (TupleDesc) NULL;
slot->ttc_buffer = InvalidBuffer;
- slot->ttc_whichplan = -1;
return slot;
}
@@ -675,20 +674,11 @@ NodeGetResultTupleSlot(Plan *node)
case T_Append:
{
- Append *n = (Append *) node;
- AppendState *appendstate;
- List *appendplans;
- int whichplan;
- Plan *subplan;
-
- appendstate = n->appendstate;
- appendplans = n->appendplans;
- whichplan = appendstate->as_whichplan;
-
- subplan = (Plan *) nth(whichplan, appendplans);
- slot = NodeGetResultTupleSlot(subplan);
- break;
+ AppendState *appendstate = ((Append *) node)->appendstate;
+
+ slot = appendstate->cstate.cs_ResultTupleSlot;
}
+ break;
case T_IndexScan:
{
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 4eff4a07bb2..ecdda594188 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.67 2000/10/05 19:48:25 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.68 2000/11/12 00:36:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -172,7 +172,6 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate)
econtext->ecxt_param_list_info = estate->es_param_list_info;
econtext->ecxt_aggvalues = NULL;
econtext->ecxt_aggnulls = NULL;
- econtext->ecxt_range_table = estate->es_range_table;
commonstate->cs_ExprContext = econtext;
}
@@ -215,7 +214,6 @@ MakeExprContext(TupleTableSlot *slot,
econtext->ecxt_param_list_info = NULL;
econtext->ecxt_aggvalues = NULL;
econtext->ecxt_aggnulls = NULL;
- econtext->ecxt_range_table = NIL;
return econtext;
}
@@ -649,10 +647,10 @@ QueryDescGetTypeInfo(QueryDesc *queryDesc)
* ExecOpenIndices
*
* Find the indices associated with a result relation, open them,
- * and save information about them in the result RelationInfo.
+ * and save information about them in the result ResultRelInfo.
*
* At entry, caller has already opened and locked
- * resultRelationInfo->ri_RelationDesc.
+ * resultRelInfo->ri_RelationDesc.
*
* This used to be horribly ugly code, and slow too because it
* did a sequential scan of pg_index. Now we rely on the relcache
@@ -662,9 +660,9 @@ QueryDescGetTypeInfo(QueryDesc *queryDesc)
* ----------------------------------------------------------------
*/
void
-ExecOpenIndices(RelationInfo *resultRelationInfo)
+ExecOpenIndices(ResultRelInfo *resultRelInfo)
{
- Relation resultRelation = resultRelationInfo->ri_RelationDesc;
+ Relation resultRelation = resultRelInfo->ri_RelationDesc;
List *indexoidlist,
*indexoidscan;
int len,
@@ -672,7 +670,7 @@ ExecOpenIndices(RelationInfo *resultRelationInfo)
RelationPtr relationDescs;
IndexInfo **indexInfoArray;
- resultRelationInfo->ri_NumIndices = 0;
+ resultRelInfo->ri_NumIndices = 0;
/* checks for disabled indexes */
if (! RelationGetForm(resultRelation)->relhasindex)
@@ -697,9 +695,9 @@ ExecOpenIndices(RelationInfo *resultRelationInfo)
relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
- resultRelationInfo->ri_NumIndices = len;
- resultRelationInfo->ri_IndexRelationDescs = relationDescs;
- resultRelationInfo->ri_IndexRelationInfo = indexInfoArray;
+ resultRelInfo->ri_NumIndices = len;
+ resultRelInfo->ri_IndexRelationDescs = relationDescs;
+ resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
/* ----------------
* For each index, open the index relation and save pg_index info.
@@ -765,18 +763,18 @@ ExecOpenIndices(RelationInfo *resultRelationInfo)
/* ----------------------------------------------------------------
* ExecCloseIndices
*
- * Close the index relations stored in resultRelationInfo
+ * Close the index relations stored in resultRelInfo
* ----------------------------------------------------------------
*/
void
-ExecCloseIndices(RelationInfo *resultRelationInfo)
+ExecCloseIndices(ResultRelInfo *resultRelInfo)
{
int i;
int numIndices;
RelationPtr relationDescs;
- numIndices = resultRelationInfo->ri_NumIndices;
- relationDescs = resultRelationInfo->ri_IndexRelationDescs;
+ numIndices = resultRelInfo->ri_NumIndices;
+ relationDescs = resultRelInfo->ri_IndexRelationDescs;
for (i = 0; i < numIndices; i++)
{
@@ -817,7 +815,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
bool is_update)
{
HeapTuple heapTuple;
- RelationInfo *resultRelationInfo;
+ ResultRelInfo *resultRelInfo;
int i;
int numIndices;
RelationPtr relationDescs;
@@ -833,11 +831,11 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
/*
* Get information from the result relation info structure.
*/
- resultRelationInfo = estate->es_result_relation_info;
- numIndices = resultRelationInfo->ri_NumIndices;
- relationDescs = resultRelationInfo->ri_IndexRelationDescs;
- indexInfoArray = resultRelationInfo->ri_IndexRelationInfo;
- heapRelation = resultRelationInfo->ri_RelationDesc;
+ resultRelInfo = estate->es_result_relation_info;
+ numIndices = resultRelInfo->ri_NumIndices;
+ relationDescs = resultRelInfo->ri_IndexRelationDescs;
+ indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
+ heapRelation = resultRelInfo->ri_RelationDesc;
heapDescriptor = RelationGetDescr(heapRelation);
/*
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index e5a5e55ef8d..ca9c48e294d 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.39 2000/10/26 21:35:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.40 2000/11/12 00:36:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -253,7 +253,6 @@ init_sql_fcache(FmgrInfo *finfo)
slot->ttc_descIsNew = true;
slot->ttc_tupleDescriptor = (TupleDesc) NULL;
slot->ttc_buffer = InvalidBuffer;
- slot->ttc_whichplan = -1;
fcache->funcSlot = slot;
}
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 81eeb1e8b0b..e47ec5756cb 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.37 2000/11/09 18:12:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.38 2000/11/12 00:36:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,8 +36,8 @@
* nil nil ... ... ...
* subplans
*
- * Append nodes are currently used for unions, and to support inheritance
- * queries, where several relations need to be scanned.
+ * Append nodes are currently used for unions, and to support
+ * inheritance queries, where several relations need to be scanned.
* For example, in our standard person/student/employee/student-emp
* example, where student and employee inherit from person
* and student-emp inherits from student and employee, the
@@ -54,8 +54,8 @@
* | | | |
* person employee student student-emp
*/
-#include "postgres.h"
+#include "postgres.h"
#include "access/heapam.h"
#include "executor/execdebug.h"
@@ -78,12 +78,8 @@ exec_append_initialize_next(Append *node)
{
EState *estate;
AppendState *appendstate;
- TupleTableSlot *result_slot;
- List *rangeTable;
int whichplan;
int nplans;
- List *inheritrtable;
- RangeTblEntry *rtentry;
/* ----------------
* get information from the append node
@@ -91,12 +87,8 @@ exec_append_initialize_next(Append *node)
*/
estate = node->plan.state;
appendstate = node->appendstate;
- result_slot = appendstate->cstate.cs_ResultTupleSlot;
- rangeTable = estate->es_range_table;
-
whichplan = appendstate->as_whichplan;
nplans = appendstate->as_nplans;
- inheritrtable = node->inheritrtable;
if (whichplan < 0)
{
@@ -110,7 +102,6 @@ exec_append_initialize_next(Append *node)
*/
appendstate->as_whichplan = 0;
return FALSE;
-
}
else if (whichplan >= nplans)
{
@@ -121,37 +112,25 @@ exec_append_initialize_next(Append *node)
*/
appendstate->as_whichplan = nplans - 1;
return FALSE;
-
}
else
{
/* ----------------
* initialize the scan
- * (and update the range table appropriately)
*
- * (doesn't this leave the range table hosed for anybody upstream
- * of the Append node??? - jolly )
+ * If we are controlling the target relation, select the proper
+ * active ResultRelInfo and junk filter for this target.
* ----------------
*/
- if (node->inheritrelid > 0)
+ if (node->isTarget)
{
- rtentry = nth(whichplan, inheritrtable);
- Assert(rtentry != NULL);
- rt_store(node->inheritrelid, rangeTable, rtentry);
+ Assert(whichplan < estate->es_num_result_relations);
+ estate->es_result_relation_info =
+ estate->es_result_relations + whichplan;
+ estate->es_junkFilter =
+ estate->es_result_relation_info->ri_junkFilter;
}
- if (appendstate->as_junkFilter_list)
- {
- estate->es_junkFilter = (JunkFilter *) nth(whichplan,
- appendstate->as_junkFilter_list);
- }
- if (appendstate->as_result_relation_info_list)
- {
- estate->es_result_relation_info = (RelationInfo *) nth(whichplan,
- appendstate->as_result_relation_info_list);
- }
- result_slot->ttc_whichplan = whichplan;
-
return TRUE;
}
}
@@ -176,14 +155,10 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
{
AppendState *appendstate;
int nplans;
- List *inheritrtable;
List *appendplans;
bool *initialized;
int i;
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);
@@ -196,7 +171,6 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
appendplans = node->appendplans;
nplans = length(appendplans);
- inheritrtable = node->inheritrtable;
initialized = (bool *) palloc(nplans * sizeof(bool));
MemSet(initialized, 0, nplans * sizeof(bool));
@@ -228,119 +202,25 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
*/
ExecInitResultTupleSlot(estate, &appendstate->cstate);
- /*
- * If the inherits rtentry is the result relation, we have to make a
- * result relation info list for all inheritors so we can update their
- * indices and put the result tuples in the right place etc.
- *
- * e.g. replace p (age = p.age + 1) from p in person*
- */
- if ((es_rri != (RelationInfo *) NULL) &&
- (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, inheritrtable)
- {
- RangeTblEntry *rtentry = lfirst(rtentryP);
- Oid reloid = rtentry->relid;
- RelationInfo *rri;
-
- /*
- * 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(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);
- }
-
- 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"
* ----------------
*/
- junkList = NIL;
-
for (i = 0; i < nplans; i++)
{
- /* ----------------
- * NOTE: we first modify range table in
- * exec_append_initialize_next() and
- * then initialize the subnode,
- * since it may use the range table.
- * ----------------
- */
appendstate->as_whichplan = i;
exec_append_initialize_next(node);
initNode = (Plan *) nth(i, appendplans);
initialized[i] = ExecInitNode(initNode, estate, (Plan *) node);
-
- /* ---------------
- * Each targetlist in the subplan may need its own junk filter
- *
- * This is true only when the reln being replaced/deleted is
- * the one that we're looking at the subclasses of
- * ---------------
- */
- if (inherited_result_rel)
- {
- JunkFilter *j = ExecInitJunkFilter(initNode->targetlist,
- ExecGetTupType(initNode));
-
- junkList = lappend(junkList, j);
- }
-
}
- appendstate->as_junkFilter_list = junkList;
- if (junkList != NIL)
- estate->es_junkFilter = (JunkFilter *) lfirst(junkList);
/* ----------------
- * initialize the return type from the appropriate subplan.
+ * initialize tuple type
* ----------------
*/
- initNode = (Plan *) nth(0, appendplans);
- ExecAssignResultType(&appendstate->cstate, ExecGetTupType(initNode));
+ ExecAssignResultTypeFromTL((Plan *) node, &appendstate->cstate);
appendstate->cstate.cs_ProjInfo = NULL;
/* ----------------
@@ -357,10 +237,9 @@ int
ExecCountSlotsAppend(Append *node)
{
List *plan;
- List *appendplans = node->appendplans;
int nSlots = 0;
- foreach(plan, appendplans)
+ foreach(plan, node->appendplans)
nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
return nSlots + APPEND_NSLOTS;
}
@@ -430,16 +309,14 @@ ExecProcAppend(Append *node)
* direction and try processing again (recursively)
* ----------------
*/
- whichplan = appendstate->as_whichplan;
-
if (ScanDirectionIsForward(direction))
- appendstate->as_whichplan = whichplan + 1;
+ appendstate->as_whichplan++;
else
- appendstate->as_whichplan = whichplan - 1;
+ appendstate->as_whichplan--;
/* ----------------
* return something from next node or an empty slot
- * all of our subplans have been exhausted.
+ * if all of our subplans have been exhausted.
* ----------------
*/
if (exec_append_initialize_next(node))
@@ -469,7 +346,6 @@ ExecEndAppend(Append *node)
List *appendplans;
bool *initialized;
int i;
- List *resultRelationInfoList;
/* ----------------
* get information from the node
@@ -490,40 +366,8 @@ ExecEndAppend(Append *node)
if (initialized[i])
ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node);
}
-
- /* ----------------
- * close out the different result relations
- *
- * NB: this must agree with what EndPlan() does to close a result rel
- * ----------------
- */
- resultRelationInfoList = appendstate->as_result_relation_info_list;
- while (resultRelationInfoList != NIL)
- {
- RelationInfo *resultRelationInfo;
-
- resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList);
-
- heap_close(resultRelationInfo->ri_RelationDesc, NoLock);
- /* close indices on the result relation, too */
- ExecCloseIndices(resultRelationInfo);
-
- /*
- * estate may (or may not) be pointing at one of my result relations.
- * If so, make sure EndPlan() doesn't try to close it again!
- */
- if (estate->es_result_relation_info == resultRelationInfo)
- estate->es_result_relation_info = NULL;
-
- pfree(resultRelationInfo);
- resultRelationInfoList = lnext(resultRelationInfoList);
- }
- appendstate->as_result_relation_info_list = NIL;
-
- /*
- * XXX should free appendstate->as_junkfilter_list here
- */
}
+
void
ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent)
{
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index b953dcd3697..56ba1375feb 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.24 2000/07/12 02:37:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.25 2000/11/12 00:36:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -156,7 +156,6 @@ InitScanRelation(SeqScan *node, EState *estate,
ScanDirection direction;
Relation currentRelation;
HeapScanDesc currentScanDesc;
- RelationInfo *resultRelationInfo;
/* ----------------
* get the relation object id from the relid'th entry
@@ -169,7 +168,6 @@ InitScanRelation(SeqScan *node, EState *estate,
rtentry = rt_fetch(relid, rangeTable);
reloid = rtentry->relid;
direction = estate->es_direction;
- resultRelationInfo = estate->es_result_relation_info;
ExecOpenScanR(reloid, /* relation */
0, /* nkeys */