diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 0f83f39071..ffb34e4be5 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.166 2004/01/07 18:56:26 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.167 2004/01/18 00:50:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -97,13 +97,13 @@ static HashJoin *make_hashjoin(List *tlist, List *hashclauses, Plan *lefttree, Plan *righttree, JoinType jointype); -static Hash *make_hash(List *tlist, Plan *lefttree); +static Hash *make_hash(Plan *lefttree); static MergeJoin *make_mergejoin(List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Plan *lefttree, Plan *righttree, JoinType jointype); -static Sort *make_sort(Query *root, List *tlist, Plan *lefttree, int numCols, +static Sort *make_sort(Query *root, Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators); static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree, Relids relids, List *pathkeys); @@ -492,7 +492,7 @@ create_material_plan(Query *root, MaterialPath *best_path) /* We don't want any excess columns in the materialized tuples */ disuse_physical_tlist(subplan, best_path->subpath); - plan = make_material(subplan->targetlist, subplan); + plan = make_material(subplan); copy_path_costsize(&plan->plan, (Path *) best_path); @@ -518,7 +518,6 @@ create_unique_plan(Query *root, UniquePath *best_path) List *newtlist; int nextresno; bool newitems; - List *my_tlist; List *l; subplan = create_plan(root, best_path->subpath); @@ -596,11 +595,8 @@ create_unique_plan(Query *root, UniquePath *best_path) /* * If the top plan node can't do projections, we need to add a * Result node to help it along. - * - * Currently, the only non-projection-capable plan type we can see - * here is Append. */ - if (IsA(subplan, Append)) + if (!is_projection_capable_plan(subplan)) subplan = (Plan *) make_result(newtlist, NULL, subplan); else subplan->targetlist = newtlist; @@ -610,9 +606,6 @@ create_unique_plan(Query *root, UniquePath *best_path) if (best_path->umethod == UNIQUE_PATH_NOOP) return subplan; - /* Copy tlist again to make one we can put sorting labels on */ - my_tlist = copyObject(subplan->targetlist); - if (best_path->umethod == UNIQUE_PATH_HASH) { long numGroups; @@ -620,7 +613,7 @@ create_unique_plan(Query *root, UniquePath *best_path) numGroups = (long) Min(best_path->rows, (double) LONG_MAX); plan = (Plan *) make_agg(root, - my_tlist, + copyObject(subplan->targetlist), NIL, AGG_HASHED, numGroupCols, @@ -637,15 +630,15 @@ create_unique_plan(Query *root, UniquePath *best_path) { TargetEntry *tle; - tle = get_tle_by_resno(my_tlist, groupColIdx[groupColPos]); + tle = get_tle_by_resno(subplan->targetlist, + groupColIdx[groupColPos]); Assert(tle != NULL); sortList = addTargetToSortList(NULL, tle, - sortList, my_tlist, + sortList, subplan->targetlist, SORTBY_ASC, NIL, false); } - plan = (Plan *) make_sort_from_sortclauses(root, my_tlist, - subplan, sortList); - plan = (Plan *) make_unique(my_tlist, plan, sortList); + plan = (Plan *) make_sort_from_sortclauses(root, sortList, subplan); + plan = (Plan *) make_unique(plan, sortList); } /* Adjust output size estimate (other fields should be OK already) */ @@ -1145,8 +1138,7 @@ create_hashjoin_plan(Query *root, /* * Build the hash node and hash join node. */ - hash_plan = make_hash(inner_plan->targetlist, - inner_plan); + hash_plan = make_hash(inner_plan); join_plan = make_hashjoin(tlist, joinclauses, otherclauses, @@ -1735,7 +1727,7 @@ make_hashjoin(List *tlist, } static Hash * -make_hash(List *tlist, Plan *lefttree) +make_hash(Plan *lefttree) { Hash *node = makeNode(Hash); Plan *plan = &node->plan; @@ -1747,7 +1739,7 @@ make_hash(List *tlist, Plan *lefttree) * input plan; this only affects EXPLAIN display not decisions. */ plan->startup_cost = plan->total_cost; - plan->targetlist = tlist; + plan->targetlist = copyObject(lefttree->targetlist); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; @@ -1785,7 +1777,7 @@ make_mergejoin(List *tlist, * Caller must have built the sortColIdx and sortOperators arrays already. */ static Sort * -make_sort(Query *root, List *tlist, Plan *lefttree, int numCols, +make_sort(Query *root, Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators) { Sort *node = makeNode(Sort); @@ -1799,7 +1791,7 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int numCols, lefttree->plan_width); plan->startup_cost = sort_path.startup_cost; plan->total_cost = sort_path.total_cost; - plan->targetlist = tlist; + plan->targetlist = copyObject(lefttree->targetlist); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; @@ -1862,7 +1854,6 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, Relids relids, List *pathkeys) { List *tlist = lefttree->targetlist; - List *sort_tlist; List *i; int numsortkeys; AttrNumber *sortColIdx; @@ -1916,11 +1907,8 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, /* * Do we need to insert a Result node? - * - * Currently, the only non-projection-capable plan type we can - * see here is Append. */ - if (IsA(lefttree, Append)) + if (!is_projection_capable_plan(lefttree)) { tlist = copyObject(tlist); lefttree = (Plan *) make_result(tlist, NULL, lefttree); @@ -1952,10 +1940,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, Assert(numsortkeys > 0); - /* Give Sort node its own copy of the tlist (still necessary?) */ - sort_tlist = copyObject(tlist); - - return make_sort(root, sort_tlist, lefttree, numsortkeys, + return make_sort(root, lefttree, numsortkeys, sortColIdx, sortOperators); } @@ -1963,15 +1948,13 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, * make_sort_from_sortclauses * Create sort plan to sort according to given sortclauses * - * 'tlist' is the targetlist - * 'lefttree' is the node which yields input tuples * 'sortcls' is a list of SortClauses + * 'lefttree' is the node which yields input tuples */ Sort * -make_sort_from_sortclauses(Query *root, List *tlist, - Plan *lefttree, List *sortcls) +make_sort_from_sortclauses(Query *root, List *sortcls, Plan *lefttree) { - List *sort_tlist; + List *sub_tlist = lefttree->targetlist; List *i; int numsortkeys; AttrNumber *sortColIdx; @@ -1987,24 +1970,20 @@ make_sort_from_sortclauses(Query *root, List *tlist, foreach(i, sortcls) { SortClause *sortcl = (SortClause *) lfirst(i); - TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist); - Resdom *resdom = tle->resdom; + TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist); /* * Check for the possibility of duplicate order-by clauses --- the * parser should have removed 'em, but no point in sorting * redundantly. */ - numsortkeys = add_sort_column(resdom->resno, sortcl->sortop, + numsortkeys = add_sort_column(tle->resdom->resno, sortcl->sortop, numsortkeys, sortColIdx, sortOperators); } Assert(numsortkeys > 0); - /* Give Sort node its own copy of the tlist (still necessary?) */ - sort_tlist = copyObject(tlist); - - return make_sort(root, sort_tlist, lefttree, numsortkeys, + return make_sort(root, lefttree, numsortkeys, sortColIdx, sortOperators); } @@ -2028,7 +2007,6 @@ make_sort_from_groupcols(Query *root, Plan *lefttree) { List *sub_tlist = lefttree->targetlist; - List *sort_tlist; int grpno = 0; List *i; int numsortkeys; @@ -2046,35 +2024,31 @@ make_sort_from_groupcols(Query *root, { GroupClause *grpcl = (GroupClause *) lfirst(i); TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[grpno]); - Resdom *resdom = tle->resdom; /* * Check for the possibility of duplicate group-by clauses --- the * parser should have removed 'em, but no point in sorting * redundantly. */ - numsortkeys = add_sort_column(resdom->resno, grpcl->sortop, + numsortkeys = add_sort_column(tle->resdom->resno, grpcl->sortop, numsortkeys, sortColIdx, sortOperators); grpno++; } Assert(numsortkeys > 0); - /* Give Sort node its own copy of the tlist (still necessary?) */ - sort_tlist = copyObject(sub_tlist); - - return make_sort(root, sort_tlist, lefttree, numsortkeys, + return make_sort(root, lefttree, numsortkeys, sortColIdx, sortOperators); } Material * -make_material(List *tlist, Plan *lefttree) +make_material(Plan *lefttree) { Material *node = makeNode(Material); Plan *plan = &node->plan; /* cost should be inserted by caller */ - plan->targetlist = tlist; + plan->targetlist = copyObject(lefttree->targetlist); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; @@ -2098,7 +2072,7 @@ materialize_finished_plan(Plan *subplan) Plan *matplan; Path matpath; /* dummy for result of cost_material */ - matplan = (Plan *) make_material(subplan->targetlist, subplan); + matplan = (Plan *) make_material(subplan); /* Set cost data */ cost_material(&matpath, @@ -2239,7 +2213,7 @@ make_group(Query *root, * that should be considered by the Unique filter. */ Unique * -make_unique(List *tlist, Plan *lefttree, List *distinctList) +make_unique(Plan *lefttree, List *distinctList) { Unique *node = makeNode(Unique); Plan *plan = &node->plan; @@ -2263,7 +2237,7 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList) * this if he has a better idea. */ - plan->targetlist = tlist; + plan->targetlist = copyObject(lefttree->targetlist); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; @@ -2278,7 +2252,7 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList) foreach(slitem, distinctList) { SortClause *sortcl = (SortClause *) lfirst(slitem); - TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist); + TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist); uniqColIdx[keyno++] = tle->resdom->resno; } @@ -2295,7 +2269,7 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList) */ SetOp * -make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, +make_setop(SetOpCmd cmd, Plan *lefttree, List *distinctList, AttrNumber flagColIdx) { SetOp *node = makeNode(SetOp); @@ -2321,7 +2295,7 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, if (plan->plan_rows < 1) plan->plan_rows = 1; - plan->targetlist = tlist; + plan->targetlist = copyObject(lefttree->targetlist); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; @@ -2336,7 +2310,7 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, foreach(slitem, distinctList) { SortClause *sortcl = (SortClause *) lfirst(slitem); - TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist); + TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist); dupColIdx[keyno++] = tle->resdom->resno; } @@ -2350,8 +2324,7 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, } Limit * -make_limit(List *tlist, Plan *lefttree, - Node *limitOffset, Node *limitCount) +make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount) { Limit *node = makeNode(Limit); Plan *plan = &node->plan; @@ -2401,7 +2374,7 @@ make_limit(List *tlist, Plan *lefttree, } } - plan->targetlist = tlist; + plan->targetlist = copyObject(lefttree->targetlist); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; @@ -2448,3 +2421,27 @@ make_result(List *tlist, return node; } + +/* + * is_projection_capable_plan + * Check whether a given Plan node is able to do projection. + */ +bool +is_projection_capable_plan(Plan *plan) +{ + /* Most plan types can project, so just list the ones that can't */ + switch (nodeTag(plan)) + { + case T_Hash: + case T_Material: + case T_Sort: + case T_Unique: + case T_SetOp: + case T_Limit: + case T_Append: + return false; + default: + break; + } + return true; +} diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 7af46244bb..00ba58ec8b 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.164 2004/01/12 22:20:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.165 2004/01/18 00:50:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1103,10 +1103,9 @@ grouping_planner(Query *parse, double tuple_fraction) /* * If the top-level plan node is one that cannot do expression * evaluation, we must insert a Result node to project the - * desired tlist. Currently, the only plan node we might see - * here that falls into that category is Append. + * desired tlist. */ - if (IsA(result_plan, Append)) + if (!is_projection_capable_plan(result_plan)) { result_plan = (Plan *) make_result(sub_tlist, NULL, result_plan); @@ -1265,9 +1264,8 @@ grouping_planner(Query *parse, double tuple_fraction) { result_plan = (Plan *) make_sort_from_sortclauses(parse, - tlist, - result_plan, - parse->sortClause); + parse->sortClause, + result_plan); current_pathkeys = sort_pathkeys; } } @@ -1277,8 +1275,7 @@ grouping_planner(Query *parse, double tuple_fraction) */ if (parse->distinctClause) { - result_plan = (Plan *) make_unique(tlist, result_plan, - parse->distinctClause); + result_plan = (Plan *) make_unique(result_plan, parse->distinctClause); /* * If there was grouping or aggregation, leave plan_rows as-is @@ -1303,7 +1300,7 @@ grouping_planner(Query *parse, double tuple_fraction) */ if (parse->limitOffset || parse->limitCount) { - result_plan = (Plan *) make_limit(tlist, result_plan, + result_plan = (Plan *) make_limit(result_plan, parse->limitOffset, parse->limitCount); } diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index d52f2a7341..9424fc7148 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.107 2004/01/04 03:51:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.108 2004/01/18 00:50:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -246,11 +246,9 @@ generate_union_plan(SetOperationStmt *op, Query *parse, { List *sortList; - tlist = copyObject(tlist); sortList = addAllTargetsToSortList(NULL, NIL, tlist, false); - plan = (Plan *) make_sort_from_sortclauses(parse, tlist, - plan, sortList); - plan = (Plan *) make_unique(tlist, plan, sortList); + plan = (Plan *) make_sort_from_sortclauses(parse, sortList, plan); + plan = (Plan *) make_unique(plan, sortList); } return plan; } @@ -300,9 +298,8 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, * Sort the child results, then add a SetOp plan node to generate the * correct output. */ - tlist = copyObject(tlist); sortList = addAllTargetsToSortList(NULL, NIL, tlist, false); - plan = (Plan *) make_sort_from_sortclauses(parse, tlist, plan, sortList); + plan = (Plan *) make_sort_from_sortclauses(parse, sortList, plan); switch (op->op) { case SETOP_INTERSECT: @@ -317,8 +314,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, cmd = SETOPCMD_INTERSECT; /* keep compiler quiet */ break; } - plan = (Plan *) make_setop(cmd, tlist, plan, sortList, - length(op->colTypes) + 1); + plan = (Plan *) make_setop(cmd, plan, sortList, length(op->colTypes) + 1); return plan; } diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 9f1ed28aa1..f9368d525c 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.76 2003/11/29 22:41:07 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.77 2004/01/18 00:50:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,8 +30,8 @@ extern Plan *create_plan(Query *root, Path *best_path); extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual, Index scanrelid, Plan *subplan); extern Append *make_append(List *appendplans, bool isTarget, List *tlist); -extern Sort *make_sort_from_sortclauses(Query *root, List *tlist, - Plan *lefttree, List *sortcls); +extern Sort *make_sort_from_sortclauses(Query *root, List *sortcls, + Plan *lefttree); extern Sort *make_sort_from_groupcols(Query *root, List *groupcls, AttrNumber *grpColIdx, Plan *lefttree); extern Agg *make_agg(Query *root, List *tlist, List *qual, @@ -43,14 +43,14 @@ extern Group *make_group(Query *root, List *tlist, int numGroupCols, AttrNumber *grpColIdx, double numGroups, Plan *lefttree); -extern Material *make_material(List *tlist, Plan *lefttree); +extern Material *make_material(Plan *lefttree); extern Plan *materialize_finished_plan(Plan *subplan); -extern Unique *make_unique(List *tlist, Plan *lefttree, List *distinctList); -extern Limit *make_limit(List *tlist, Plan *lefttree, - Node *limitOffset, Node *limitCount); -extern SetOp *make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, +extern Unique *make_unique(Plan *lefttree, List *distinctList); +extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount); +extern SetOp *make_setop(SetOpCmd cmd, Plan *lefttree, List *distinctList, AttrNumber flagColIdx); extern Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan); +extern bool is_projection_capable_plan(Plan *plan); /* * prototypes for plan/initsplan.c