|
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; |
|