|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.238 2008/08/0502:43:17 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.239 2008/08/0516:03:10 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -1304,11 +1304,24 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
1304 | 1304 | /*
|
1305 | 1305 | * Use a Unique node to implement DISTINCT. Add an explicit sort
|
1306 | 1306 | * if we couldn't make the path come out the way the Unique node
|
1307 |
| - * needs it. If we do have to sort, sort by the more rigorous |
1308 |
| - * of DISTINCT and ORDER BY, to avoid a second sort below. |
| 1307 | + * needs it. If we do have to sort, always sort by the more |
| 1308 | + * rigorous of DISTINCT and ORDER BY, to avoid a second sort |
| 1309 | + * below. However, for regular DISTINCT, don't sort now if we |
| 1310 | + * don't have to --- sorting afterwards will likely be cheaper, |
| 1311 | + * and also has the possibility of optimizing via LIMIT. But |
| 1312 | + * for DISTINCT ON, we *must* force the final sort now, else |
| 1313 | + * it won't have the desired behavior. |
1309 | 1314 | */
|
1310 |
| -if (!pathkeys_contained_in(root->distinct_pathkeys, |
1311 |
| -current_pathkeys)) |
| 1315 | +List*needed_pathkeys; |
| 1316 | + |
| 1317 | +if (parse->hasDistinctOn&& |
| 1318 | +list_length(root->distinct_pathkeys)< |
| 1319 | +list_length(root->sort_pathkeys)) |
| 1320 | +needed_pathkeys=root->sort_pathkeys; |
| 1321 | +else |
| 1322 | +needed_pathkeys=root->distinct_pathkeys; |
| 1323 | + |
| 1324 | +if (!pathkeys_contained_in(needed_pathkeys,current_pathkeys)) |
1312 | 1325 | {
|
1313 | 1326 | if (list_length(root->distinct_pathkeys) >=
|
1314 | 1327 | list_length(root->sort_pathkeys))
|
@@ -1961,6 +1974,7 @@ choose_hashed_distinct(PlannerInfo *root,
|
1961 | 1974 | intnumDistinctCols=list_length(root->parse->distinctClause);
|
1962 | 1975 | Sizehashentrysize;
|
1963 | 1976 | List*current_pathkeys;
|
| 1977 | +List*needed_pathkeys; |
1964 | 1978 | Pathhashed_p;
|
1965 | 1979 | Pathsorted_p;
|
1966 | 1980 |
|
@@ -2002,13 +2016,21 @@ choose_hashed_distinct(PlannerInfo *root,
|
2002 | 2016 | cost_sort(&hashed_p,root,root->sort_pathkeys,hashed_p.total_cost,
|
2003 | 2017 | dNumDistinctRows,input_plan->plan_width,limit_tuples);
|
2004 | 2018 |
|
2005 |
| -/* Now for the GROUP case ... */ |
| 2019 | +/* |
| 2020 | + * Now for the GROUP case. See comments in grouping_planner about the |
| 2021 | + * sorting choices here --- this code should match that code. |
| 2022 | + */ |
2006 | 2023 | sorted_p.startup_cost=input_plan->startup_cost;
|
2007 | 2024 | sorted_p.total_cost=input_plan->total_cost;
|
2008 | 2025 | current_pathkeys=input_pathkeys;
|
2009 |
| -if (!pathkeys_contained_in(root->distinct_pathkeys,current_pathkeys)) |
| 2026 | +if (root->parse->hasDistinctOn&& |
| 2027 | +list_length(root->distinct_pathkeys)< |
| 2028 | +list_length(root->sort_pathkeys)) |
| 2029 | +needed_pathkeys=root->sort_pathkeys; |
| 2030 | +else |
| 2031 | +needed_pathkeys=root->distinct_pathkeys; |
| 2032 | +if (!pathkeys_contained_in(needed_pathkeys,current_pathkeys)) |
2010 | 2033 | {
|
2011 |
| -/* We don't want to sort twice */ |
2012 | 2034 | if (list_length(root->distinct_pathkeys) >=
|
2013 | 2035 | list_length(root->sort_pathkeys))
|
2014 | 2036 | current_pathkeys=root->distinct_pathkeys;
|
|