diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 33 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 24 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepkeyset.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 32 | ||||
-rw-r--r-- | src/backend/optimizer/util/tlist.c | 31 |
5 files changed, 77 insertions, 47 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index ab69742482a..70a73821641 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.81 2000/01/26 05:56:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.82 2000/01/27 18:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1342,16 +1342,19 @@ make_group(List *tlist, } /* - * The uniqueAttr argument must be a null-terminated string, - * either the name of the attribute to select unique on - * or "*" + * distinctList is a list of SortClauses, identifying the targetlist items + * that should be considered by the Unique filter. */ Unique * -make_unique(List *tlist, Plan *lefttree, char *uniqueAttr) +make_unique(List *tlist, Plan *lefttree, List *distinctList) { Unique *node = makeNode(Unique); Plan *plan = &node->plan; + int numCols = length(distinctList); + int keyno = 0; + AttrNumber *uniqColIdx; + List *slitem; copy_plan_costsize(plan, lefttree); plan->state = (EState *) NULL; @@ -1361,10 +1364,22 @@ make_unique(List *tlist, Plan *lefttree, char *uniqueAttr) plan->righttree = NULL; node->nonameid = _NONAME_RELATION_ID_; node->keycount = 0; - if (strcmp(uniqueAttr, "*") == 0) - node->uniqueAttr = NULL; - else - node->uniqueAttr = pstrdup(uniqueAttr); + + /* convert SortClause list into array of attr indexes, as wanted by exec */ + Assert(numCols > 0); + uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols); + + foreach(slitem, distinctList) + { + SortClause *sortcl = (SortClause *) lfirst(slitem); + TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist); + + uniqColIdx[keyno++] = tle->resdom->resno; + } + + node->numCols = numCols; + node->uniqColIdx = uniqColIdx; + return node; } diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 0b711f32099..28483fd4734 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.73 2000/01/26 05:56:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.74 2000/01/27 18:11:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -381,12 +381,12 @@ union_planner(Query *parse) } /* - * Finally, if there is a UNIQUE clause, add the UNIQUE node. + * Finally, if there is a DISTINCT clause, add the UNIQUE node. */ - if (parse->uniqueFlag) + if (parse->distinctClause) { result_plan = (Plan *) make_unique(tlist, result_plan, - parse->uniqueFlag); + parse->distinctClause); } return result_plan; @@ -583,20 +583,8 @@ make_sortplan(List *tlist, List *sortcls, Plan *plannode) foreach(i, sortcls) { SortClause *sortcl = (SortClause *) lfirst(i); - Index refnumber = sortcl->tleSortGroupRef; - TargetEntry *tle = NULL; - Resdom *resdom; - List *l; - - foreach(l, temp_tlist) - { - tle = (TargetEntry *) lfirst(l); - if (tle->resdom->ressortgroupref == refnumber) - break; - } - if (l == NIL) - elog(ERROR, "make_sortplan: ORDER BY expression not found in targetlist"); - resdom = tle->resdom; + TargetEntry *tle = get_sortgroupclause_tle(sortcl, temp_tlist); + Resdom *resdom = tle->resdom; /* * Check for the possibility of duplicate order-by clauses --- the diff --git a/src/backend/optimizer/prep/prepkeyset.c b/src/backend/optimizer/prep/prepkeyset.c index 127505597a4..fc192e6f28b 100644 --- a/src/backend/optimizer/prep/prepkeyset.c +++ b/src/backend/optimizer/prep/prepkeyset.c @@ -104,9 +104,7 @@ transformKeySetQuery(Query *origNode) unionNode->isPortal = origNode->isPortal; unionNode->isBinary = origNode->isBinary; - if (origNode->uniqueFlag) - unionNode->uniqueFlag = pstrdup(origNode->uniqueFlag); - + Node_Copy(origNode, unionNode, distinctClause); Node_Copy(origNode, unionNode, sortClause); Node_Copy(origNode, unionNode, rtable); Node_Copy(origNode, unionNode, targetList); diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index a27305ef3e8..4323b652e8d 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.41 2000/01/26 05:56:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.42 2000/01/27 18:11:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "optimizer/planmain.h" #include "optimizer/planner.h" #include "optimizer/prep.h" +#include "optimizer/tlist.h" #include "parser/parse_clause.h" #include "parser/parsetree.h" #include "utils/lsyscache.h" @@ -131,7 +132,7 @@ plan_union_queries(Query *parse) !last_union_all_flag) { parse->sortClause = NIL; - parse->uniqueFlag = NULL; + parse->distinctClause = NIL; } parse->unionClause = NIL; /* prevent recursion */ @@ -183,17 +184,28 @@ plan_union_queries(Query *parse) if (!last_union_all_flag) { /* Need SELECT DISTINCT behavior to implement UNION. - * Set uniqueFlag properly, put back the held sortClause, - * and add any missing columns to the sort clause. + * Put back the held sortClause, add any missing columns to the + * sort clause, and set distinctClause properly. */ - parse->uniqueFlag = "*"; + List *slitem; + parse->sortClause = addAllTargetsToSortList(hold_sortClause, parse->targetList); + parse->distinctClause = NIL; + foreach(slitem, parse->sortClause) + { + SortClause *scl = (SortClause *) lfirst(slitem); + TargetEntry *tle = get_sortgroupclause_tle(scl, parse->targetList); + + if (! tle->resdom->resjunk) + parse->distinctClause = lappend(parse->distinctClause, + copyObject(scl)); + } } else { - /* needed so we don't take the flag from the first query */ - parse->uniqueFlag = NULL; + /* needed so we don't take SELECT DISTINCT from the first query */ + parse->distinctClause = NIL; } /* Make sure we don't try to apply the first query's grouping stuff @@ -314,9 +326,9 @@ plan_inherit_query(Relids relids, * Clear the sorting and grouping qualifications in the subquery, * so that sorting will only be done once after append */ - new_root->uniqueFlag = NULL; - new_root->sortClause = NULL; - new_root->groupClause = NULL; + new_root->distinctClause = NIL; + new_root->sortClause = NIL; + new_root->groupClause = NIL; new_root->havingQual = NULL; new_root->hasAggs = false; /* shouldn't be any left ... */ diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index 8edf44190a4..b4c745b25f3 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.42 2000/01/26 05:56:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.43 2000/01/27 18:11:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -217,15 +217,16 @@ get_expr(TargetEntry *tle) } /* - * get_sortgroupclause_expr + * get_sortgroupclause_tle * Find the targetlist entry matching the given SortClause - * (or GroupClause) by ressortgroupref, and return its expression. + * (or GroupClause) by ressortgroupref, and return it. * * Because GroupClause is typedef'd as SortClause, either kind of * node can be passed without casting. */ -Node * -get_sortgroupclause_expr(SortClause *sortClause, List *targetList) +TargetEntry * +get_sortgroupclause_tle(SortClause *sortClause, + List *targetList) { Index refnumber = sortClause->tleSortGroupRef; List *l; @@ -235,9 +236,25 @@ get_sortgroupclause_expr(SortClause *sortClause, List *targetList) TargetEntry *tle = (TargetEntry *) lfirst(l); if (tle->resdom->ressortgroupref == refnumber) - return tle->expr; + return tle; } - elog(ERROR, "get_sortgroupclause_expr: ORDER/GROUP BY expression not found in targetlist"); + elog(ERROR, "get_sortgroupclause_tle: ORDER/GROUP BY expression not found in targetlist"); return NULL; /* keep compiler quiet */ } + +/* + * get_sortgroupclause_expr + * Find the targetlist entry matching the given SortClause + * (or GroupClause) by ressortgroupref, and return its expression. + * + * Because GroupClause is typedef'd as SortClause, either kind of + * node can be passed without casting. + */ +Node * +get_sortgroupclause_expr(SortClause *sortClause, List *targetList) +{ + TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList); + + return tle->expr; +} |