aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-11-04 12:01:17 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2010-11-04 12:01:17 -0400
commit034967bdcbb0c7be61d0500955226e1234ec5f04 (patch)
tree501a2819d7895cca156d08025cd5de49418c8d69 /src/backend/optimizer/plan/planner.c
parent0abc8fdd4df3dd0524cd9fd8e2d761cf932dd80f (diff)
downloadpostgresql-034967bdcbb0c7be61d0500955226e1234ec5f04.tar.gz
postgresql-034967bdcbb0c7be61d0500955226e1234ec5f04.zip
Reimplement planner's handling of MIN/MAX aggregate optimization.
Per my recent proposal, get rid of all the direct inspection of indexes and manual generation of paths in planagg.c. Instead, set up EquivalenceClasses for the aggregate argument expressions, and let the regular path generation logic deal with creating paths that can satisfy those sort orders. This makes planagg.c a bit more visible to the rest of the planner than it was originally, but the approach is basically a lot cleaner than before. A major advantage of doing it this way is that we get MIN/MAX optimization on inheritance trees (using MergeAppend of indexscans) practically for free, whereas in the old way we'd have had to add a whole lot more duplicative logic. One small disadvantage of this approach is that MIN/MAX aggregates can no longer exploit partial indexes having an "x IS NOT NULL" predicate, unless that restriction or something that implies it is specified in the query. The previous implementation was able to use the added "x IS NOT NULL" condition as an extra predicate proof condition, but in this version we rely entirely on indexes that are considered usable by the main planning process. That seems a fair tradeoff for the simplicity and functionality gained.
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 93daedc7061..07301c77fbf 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1011,6 +1011,30 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
&groupColIdx, &need_tlist_eval);
/*
+ * Do aggregate preprocessing, if the query has any aggs.
+ *
+ * Note: think not that we can turn off hasAggs if we find no aggs. It
+ * is possible for constant-expression simplification to remove all
+ * explicit references to aggs, but we still have to follow the
+ * aggregate semantics (eg, producing only one output row).
+ */
+ if (parse->hasAggs)
+ {
+ /*
+ * Will need actual number of aggregates for estimating costs.
+ * Note: we do not attempt to detect duplicate aggregates here; a
+ * somewhat-overestimated count is okay for our present purposes.
+ */
+ count_agg_clauses((Node *) tlist, &agg_counts);
+ count_agg_clauses(parse->havingQual, &agg_counts);
+
+ /*
+ * Preprocess MIN/MAX aggregates, if any.
+ */
+ preprocess_minmax_aggregates(root, tlist);
+ }
+
+ /*
* Calculate pathkeys that represent grouping/ordering requirements.
* Stash them in PlannerInfo so that query_planner can canonicalize
* them after EquivalenceClasses have been formed. The sortClause is
@@ -1057,23 +1081,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
false);
/*
- * Will need actual number of aggregates for estimating costs.
- *
- * Note: we do not attempt to detect duplicate aggregates here; a
- * somewhat-overestimated count is okay for our present purposes.
- *
- * Note: think not that we can turn off hasAggs if we find no aggs. It
- * is possible for constant-expression simplification to remove all
- * explicit references to aggs, but we still have to follow the
- * aggregate semantics (eg, producing only one output row).
- */
- if (parse->hasAggs)
- {
- count_agg_clauses((Node *) tlist, &agg_counts);
- count_agg_clauses(parse->havingQual, &agg_counts);
- }
-
- /*
* Figure out whether we want a sorted result from query_planner.
*
* If we have a sortable GROUP BY clause, then we want a result sorted