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:
@ -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;
|
||||
}
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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 -
|
||||
|
Reference in New Issue
Block a user