diff options
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
| -rw-r--r-- | src/backend/optimizer/plan/createplan.c | 145 |
1 files changed, 144 insertions, 1 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index f6e51d0d52..b7b1204e76 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.131 2003/01/15 23:10:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.132 2003/01/20 18:54:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,6 +26,7 @@ #include "optimizer/restrictinfo.h" #include "optimizer/tlist.h" #include "optimizer/var.h" +#include "parser/parse_clause.h" #include "parser/parse_expr.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -36,6 +37,7 @@ static Join *create_join_plan(Query *root, JoinPath *best_path); static Append *create_append_plan(Query *root, AppendPath *best_path); static Result *create_result_plan(Query *root, ResultPath *best_path); static Material *create_material_plan(Query *root, MaterialPath *best_path); +static Plan *create_unique_plan(Query *root, UniquePath *best_path); static SeqScan *create_seqscan_plan(Path *best_path, List *tlist, List *scan_clauses); static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path, @@ -146,6 +148,10 @@ create_plan(Query *root, Path *best_path) plan = (Plan *) create_material_plan(root, (MaterialPath *) best_path); break; + case T_Unique: + plan = (Plan *) create_unique_plan(root, + (UniquePath *) best_path); + break; default: elog(ERROR, "create_plan: unknown pathtype %d", best_path->pathtype); @@ -399,6 +405,97 @@ create_material_plan(Query *root, MaterialPath *best_path) return plan; } +/* + * create_unique_plan + * Create a Unique plan for 'best_path' and (recursively) plans + * for its subpaths. + * + * Returns a Plan node. + */ +static Plan * +create_unique_plan(Query *root, UniquePath *best_path) +{ + Plan *plan; + Plan *subplan; + List *sub_targetlist; + List *l; + + subplan = create_plan(root, best_path->subpath); + + /* + * If the subplan came from an IN subselect (currently always the case), + * we need to instantiate the correct output targetlist for the subselect, + * rather than using the flattened tlist. + */ + sub_targetlist = NIL; + foreach(l, root->in_info_list) + { + InClauseInfo *ininfo = (InClauseInfo *) lfirst(l); + + if (sameseti(ininfo->righthand, best_path->path.parent->relids)) + { + sub_targetlist = ininfo->sub_targetlist; + break; + } + } + + if (sub_targetlist) + { + /* + * Transform list of plain Vars into targetlist + */ + List *newtlist = NIL; + int resno = 1; + + foreach(l, sub_targetlist) + { + Node *tlexpr = lfirst(l); + TargetEntry *tle; + + tle = makeTargetEntry(makeResdom(resno, + exprType(tlexpr), + exprTypmod(tlexpr), + NULL, + false), + (Expr *) tlexpr); + newtlist = lappend(newtlist, tle); + resno++; + } + /* + * 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)) + subplan = (Plan *) make_result(newtlist, NULL, subplan); + else + subplan->targetlist = newtlist; + } + + if (best_path->use_hash) + { + elog(ERROR, "create_unique_plan: hash case not implemented yet"); + plan = NULL; + } + else + { + List *sort_tlist; + List *sortList; + + sort_tlist = new_unsorted_tlist(subplan->targetlist); + sortList = addAllTargetsToSortList(NIL, sort_tlist); + plan = (Plan *) make_sort_from_sortclauses(root, sort_tlist, + subplan, sortList); + plan = (Plan *) make_unique(sort_tlist, plan, sortList); + } + + plan->plan_rows = best_path->rows; + + return plan; +} + /***************************************************************************** * @@ -1548,6 +1645,52 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, return make_sort(root, sort_tlist, lefttree, numsortkeys); } +/* + * 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 + */ +Sort * +make_sort_from_sortclauses(Query *root, List *tlist, + Plan *lefttree, List *sortcls) +{ + List *sort_tlist; + List *i; + int keyno = 0; + + /* + * First make a copy of the tlist so that we don't corrupt the + * original. + */ + sort_tlist = new_unsorted_tlist(tlist); + + foreach(i, sortcls) + { + SortClause *sortcl = (SortClause *) lfirst(i); + TargetEntry *tle = get_sortgroupclause_tle(sortcl, sort_tlist); + Resdom *resdom = tle->resdom; + + /* + * Check for the possibility of duplicate order-by clauses --- the + * parser should have removed 'em, but the executor will get + * terribly confused if any get through! + */ + if (resdom->reskey == 0) + { + /* OK, insert the ordering info needed by the executor. */ + resdom->reskey = ++keyno; + resdom->reskeyop = sortcl->sortop; + } + } + + Assert(keyno > 0); + + return make_sort(root, sort_tlist, lefttree, keyno); +} + Material * make_material(List *tlist, Plan *lefttree) { |
