1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

Fix parser so that we don't modify the user-written ORDER BY list in order

to represent DISTINCT or DISTINCT ON.  This gets rid of a longstanding
annoyance that a view or rule using SELECT DISTINCT will be dumped out
with an overspecified ORDER BY list, and is one small step along the way
to decoupling DISTINCT and ORDER BY enough so that hash-based implementation
of DISTINCT will be possible.  In passing, improve transformDistinctClause
so that it doesn't reject duplicate DISTINCT ON items, as was reported by
Steve Midgley a couple weeks ago.
This commit is contained in:
Tom Lane
2008-07-31 22:47:56 +00:00
parent b1fb3b2a7f
commit 63247bec28
7 changed files with 174 additions and 125 deletions

View File

@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.106 2008/01/11 04:02:18 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.107 2008/07/31 22:47:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -288,7 +288,7 @@ query_planner(PlannerInfo *root, List *tlist,
* levels of sort --- and, therefore, certainly need to read all the
* tuples --- unless ORDER BY is a subset of GROUP BY.
*/
if (parse->groupClause && parse->sortClause &&
if (root->group_pathkeys && root->sort_pathkeys &&
!pathkeys_contained_in(root->sort_pathkeys, root->group_pathkeys))
tuple_fraction = 0.0;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.234 2008/07/10 02:14:03 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.235 2008/07/31 22:47:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -826,6 +826,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
/*
* Calculate pathkeys that represent result ordering requirements
*/
Assert(parse->distinctClause == NIL);
sort_pathkeys = make_pathkeys_for_sortclauses(root,
parse->sortClause,
tlist,
@ -864,17 +865,29 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* Calculate pathkeys that represent grouping/ordering requirements.
* Stash them in PlannerInfo so that query_planner can canonicalize
* them after EquivalenceClasses have been formed.
*
* Note: for the moment, DISTINCT is always implemented via sort/uniq,
* and we set the sort_pathkeys to be the more rigorous of the
* DISTINCT and ORDER BY requirements. This should be changed
* someday, but DISTINCT ON is a bit of a problem ...
*/
root->group_pathkeys =
make_pathkeys_for_sortclauses(root,
parse->groupClause,
tlist,
false);
root->sort_pathkeys =
make_pathkeys_for_sortclauses(root,
parse->sortClause,
tlist,
false);
if (list_length(parse->distinctClause) > list_length(parse->sortClause))
root->sort_pathkeys =
make_pathkeys_for_sortclauses(root,
parse->distinctClause,
tlist,
false);
else
root->sort_pathkeys =
make_pathkeys_for_sortclauses(root,
parse->sortClause,
tlist,
false);
/*
* Will need actual number of aggregates for estimating costs.
@ -903,9 +916,9 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* by ORDER BY --- but that might just leave us failing to exploit an
* available sort order at all. Needs more thought...)
*/
if (parse->groupClause)
if (root->group_pathkeys)
root->query_pathkeys = root->group_pathkeys;
else if (parse->sortClause)
else if (root->sort_pathkeys)
root->query_pathkeys = root->sort_pathkeys;
else
root->query_pathkeys = NIL;
@ -1172,7 +1185,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* If we were not able to make the plan come out in the right order, add
* an explicit sort step.
*/
if (parse->sortClause)
if (sort_pathkeys)
{
if (!pathkeys_contained_in(sort_pathkeys, current_pathkeys))
{

View File

@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.147 2008/06/19 00:46:04 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.148 2008/07/31 22:47:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -69,6 +69,7 @@ static List *generate_setop_tlist(List *colTypes, int flag,
static List *generate_append_tlist(List *colTypes, bool flag,
List *input_plans,
List *refnames_tlist);
static List *generate_setop_sortlist(List *targetlist);
static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte,
Index rti);
static void make_inh_translation_lists(Relation oldrelation,
@ -319,7 +320,7 @@ generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
{
List *sortList;
sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
sortList = generate_setop_sortlist(tlist);
if (sortList)
{
plan = (Plan *) make_sort_from_sortclauses(root, sortList, plan);
@ -384,7 +385,7 @@ generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
* Sort the child results, then add a SetOp plan node to generate the
* correct output.
*/
sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
sortList = generate_setop_sortlist(tlist);
if (sortList == NIL) /* nothing to sort on? */
{
@ -675,6 +676,31 @@ generate_append_tlist(List *colTypes, bool flag,
return tlist;
}
/*
* generate_setop_sortlist
* Build a SortClause list enumerating all the non-resjunk tlist entries,
* using default ordering properties.
*/
static List *
generate_setop_sortlist(List *targetlist)
{
List *sortlist = NIL;
ListCell *l;
foreach(l, targetlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
if (!tle->resjunk)
sortlist = addTargetToSortList(NULL, tle,
sortlist, targetlist,
SORTBY_DEFAULT,
SORTBY_NULLS_DEFAULT,
NIL, false);
}
return sortlist;
}
/*
* find_all_inheritors -