diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-12 00:37:02 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-12 00:37:02 +0000 |
commit | 6543d81d659f4176c6530fb09eef83deede264a0 (patch) | |
tree | c1dd2a57ee5e640214978ae72e8e7b2f624f8972 /src/backend/executor | |
parent | 609f9199af2411a52bb9731d8aa1f13885c439b5 (diff) | |
download | postgresql-6543d81d659f4176c6530fb09eef83deede264a0.tar.gz postgresql-6543d81d659f4176c6530fb09eef83deede264a0.zip |
Restructure handling of inheritance queries so that they work with outer
joins, and clean things up a good deal at the same time. Append plan node
no longer hacks on rangetable at runtime --- instead, all child tables are
given their own RT entries during planning. Concept of multiple target
tables pushed up into execMain, replacing bug-prone implementation within
nodeAppend. Planner now supports generating Append plans for inheritance
sets either at the top of the plan (the old way) or at the bottom. Expanding
at the bottom is appropriate for tables used as sources, since they may
appear inside an outer join; but we must still expand at the top when the
target of an UPDATE or DELETE is an inheritance set, because we actually need
a different targetlist and junkfilter for each target table in that case.
Fortunately a target table can't be inside an outer join... Bizarre mutual
recursion between union_planner and prepunion.c is gone --- in fact,
union_planner doesn't really have much to do with union queries anymore,
so I renamed it grouping_planner.
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 376 | ||||
-rw-r--r-- | src/backend/executor/execQual.c | 3 | ||||
-rw-r--r-- | src/backend/executor/execTuples.c | 20 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 40 | ||||
-rw-r--r-- | src/backend/executor/functions.c | 3 | ||||
-rw-r--r-- | src/backend/executor/nodeAppend.c | 194 | ||||
-rw-r--r-- | src/backend/executor/nodeSeqscan.c | 4 |
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 */ |