@@ -93,6 +93,25 @@ typedef struct
9393List * groupClause ;/* overrides parse->groupClause */
9494}standard_qp_extra ;
9595
96+ /*
97+ * Various flags indicating what kinds of grouping are possible.
98+ *
99+ * GROUPING_CAN_USE_SORT should be set if it's possible to perform
100+ * sort-based implementations of grouping. When grouping sets are in use,
101+ * this will be true if sorting is potentially usable for any of the grouping
102+ * sets, even if it's not usable for all of them.
103+ *
104+ * GROUPING_CAN_USE_HASH should be set if it's possible to perform
105+ * hash-based implementations of grouping.
106+ *
107+ * GROUPING_CAN_PARTIAL_AGG should be set if the aggregation is of a type
108+ * for which we support partial aggregation (not, for example, grouping sets).
109+ * It says nothing about parallel-safety or the availability of suitable paths.
110+ */
111+ #define GROUPING_CAN_USE_SORT 0x0001
112+ #define GROUPING_CAN_USE_HASH 0x0002
113+ #define GROUPING_CAN_PARTIAL_AGG 0x0004
114+
96115/*
97116 * Data specific to grouping sets
98117 */
@@ -149,7 +168,7 @@ static void create_ordinary_grouping_paths(PlannerInfo *root,
149168RelOptInfo * input_rel ,
150169PathTarget * target ,RelOptInfo * grouped_rel ,
151170const AggClauseCosts * agg_costs ,
152- grouping_sets_data * gd );
171+ grouping_sets_data * gd , int flags );
153172static void consider_groupingsets_paths (PlannerInfo * root ,
154173RelOptInfo * grouped_rel ,
155174Path * path ,
@@ -215,8 +234,8 @@ static RelOptInfo *create_partial_grouping_paths(PlannerInfo *root,
215234bool can_hash ,
216235AggClauseCosts * agg_final_costs );
217236static void gather_grouping_paths (PlannerInfo * root ,RelOptInfo * rel );
218- static bool can_parallel_agg (PlannerInfo * root , RelOptInfo * input_rel ,
219- RelOptInfo * grouped_rel , const AggClauseCosts * agg_costs );
237+ static bool can_partial_agg (PlannerInfo * root ,
238+ const AggClauseCosts * agg_costs );
220239
221240
222241/*****************************************************************************
@@ -3720,8 +3739,58 @@ create_grouping_paths(PlannerInfo *root,
37203739if (is_degenerate_grouping (root ))
37213740create_degenerate_grouping_paths (root ,input_rel ,target ,grouped_rel );
37223741else
3742+ {
3743+ int flags = 0 ;
3744+
3745+ /*
3746+ * Determine whether it's possible to perform sort-based
3747+ * implementations of grouping. (Note that if groupClause is empty,
3748+ * grouping_is_sortable() is trivially true, and all the
3749+ * pathkeys_contained_in() tests will succeed too, so that we'll
3750+ * consider every surviving input path.)
3751+ *
3752+ * If we have grouping sets, we might be able to sort some but not all
3753+ * of them; in this case, we need can_sort to be true as long as we
3754+ * must consider any sorted-input plan.
3755+ */
3756+ if ((gd && gd -> rollups != NIL )
3757+ || grouping_is_sortable (parse -> groupClause ))
3758+ flags |=GROUPING_CAN_USE_SORT ;
3759+
3760+ /*
3761+ * Determine whether we should consider hash-based implementations of
3762+ * grouping.
3763+ *
3764+ * Hashed aggregation only applies if we're grouping. If we have
3765+ * grouping sets, some groups might be hashable but others not; in
3766+ * this case we set can_hash true as long as there is nothing globally
3767+ * preventing us from hashing (and we should therefore consider plans
3768+ * with hashes).
3769+ *
3770+ * Executor doesn't support hashed aggregation with DISTINCT or ORDER
3771+ * BY aggregates. (Doing so would imply storing *all* the input
3772+ * values in the hash table, and/or running many sorts in parallel,
3773+ * either of which seems like a certain loser.) We similarly don't
3774+ * support ordered-set aggregates in hashed aggregation, but that case
3775+ * is also included in the numOrderedAggs count.
3776+ *
3777+ * Note: grouping_is_hashable() is much more expensive to check than
3778+ * the other gating conditions, so we want to do it last.
3779+ */
3780+ if ((parse -> groupClause != NIL &&
3781+ agg_costs -> numOrderedAggs == 0 &&
3782+ (gd ?gd -> any_hashable :grouping_is_hashable (parse -> groupClause ))))
3783+ flags |=GROUPING_CAN_USE_HASH ;
3784+
3785+ /*
3786+ * Determine whether partial aggregation is possible.
3787+ */
3788+ if (can_partial_agg (root ,agg_costs ))
3789+ flags |=GROUPING_CAN_PARTIAL_AGG ;
3790+
37233791create_ordinary_grouping_paths (root ,input_rel ,target ,grouped_rel ,
3724- agg_costs ,gd );
3792+ agg_costs ,gd ,flags );
3793+ }
37253794
37263795set_cheapest (grouped_rel );
37273796return grouped_rel ;
@@ -3820,15 +3889,15 @@ static void
38203889create_ordinary_grouping_paths (PlannerInfo * root ,RelOptInfo * input_rel ,
38213890PathTarget * target ,RelOptInfo * grouped_rel ,
38223891const AggClauseCosts * agg_costs ,
3823- grouping_sets_data * gd )
3892+ grouping_sets_data * gd , int flags )
38243893{
38253894Query * parse = root -> parse ;
38263895Path * cheapest_path = input_rel -> cheapest_total_path ;
38273896RelOptInfo * partially_grouped_rel = NULL ;
38283897AggClauseCosts agg_final_costs ;/* parallel only */
38293898double dNumGroups ;
3830- bool can_hash ;
3831- bool can_sort ;
3899+ bool can_hash = ( flags & GROUPING_CAN_USE_HASH ) != 0 ;
3900+ bool can_sort = ( flags & GROUPING_CAN_USE_SORT ) != 0 ;
38323901
38333902/*
38343903 * Estimate number of groups.
@@ -3838,50 +3907,14 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
38383907gd ,
38393908parse -> targetList );
38403909
3841- /*
3842- * Determine whether it's possible to perform sort-based implementations
3843- * of grouping. (Note that if groupClause is empty,
3844- * grouping_is_sortable() is trivially true, and all the
3845- * pathkeys_contained_in() tests will succeed too, so that we'll consider
3846- * every surviving input path.)
3847- *
3848- * If we have grouping sets, we might be able to sort some but not all of
3849- * them; in this case, we need can_sort to be true as long as we must
3850- * consider any sorted-input plan.
3851- */
3852- can_sort = (gd && gd -> rollups != NIL )
3853- || grouping_is_sortable (parse -> groupClause );
3854-
3855- /*
3856- * Determine whether we should consider hash-based implementations of
3857- * grouping.
3858- *
3859- * Hashed aggregation only applies if we're grouping. If we have grouping
3860- * sets, some groups might be hashable but others not; in this case we set
3861- * can_hash true as long as there is nothing globally preventing us from
3862- * hashing (and we should therefore consider plans with hashes).
3863- *
3864- * Executor doesn't support hashed aggregation with DISTINCT or ORDER BY
3865- * aggregates. (Doing so would imply storing *all* the input values in
3866- * the hash table, and/or running many sorts in parallel, either of which
3867- * seems like a certain loser.) We similarly don't support ordered-set
3868- * aggregates in hashed aggregation, but that case is also included in the
3869- * numOrderedAggs count.
3870- *
3871- * Note: grouping_is_hashable() is much more expensive to check than the
3872- * other gating conditions, so we want to do it last.
3873- */
3874- can_hash = (parse -> groupClause != NIL &&
3875- agg_costs -> numOrderedAggs == 0 &&
3876- (gd ?gd -> any_hashable :grouping_is_hashable (parse -> groupClause )));
3877-
38783910/*
38793911 * Before generating paths for grouped_rel, we first generate any possible
38803912 * partially grouped paths; that way, later code can easily consider both
38813913 * parallel and non-parallel approaches to grouping.
38823914 */
38833915MemSet (& agg_final_costs ,0 ,sizeof (AggClauseCosts ));
3884- if (can_parallel_agg (root ,input_rel ,grouped_rel ,agg_costs ))
3916+ if (grouped_rel -> consider_parallel && input_rel -> partial_pathlist != NIL
3917+ && (flags & GROUPING_CAN_PARTIAL_AGG )!= 0 )
38853918{
38863919partially_grouped_rel =
38873920create_partial_grouping_paths (root ,
@@ -6490,28 +6523,17 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
64906523}
64916524
64926525/*
6493- *can_parallel_agg
6526+ *can_partial_agg
64946527 *
6495- * Determines whether or notparallel grouping and/or aggregation is possible.
6528+ * Determines whether or notpartial grouping and/or aggregation is possible.
64966529 * Returns true when possible, false otherwise.
64976530 */
64986531static bool
6499- can_parallel_agg (PlannerInfo * root ,RelOptInfo * input_rel ,
6500- RelOptInfo * grouped_rel ,const AggClauseCosts * agg_costs )
6532+ can_partial_agg (PlannerInfo * root ,const AggClauseCosts * agg_costs )
65016533{
65026534Query * parse = root -> parse ;
65036535
6504- if (!grouped_rel -> consider_parallel )
6505- {
6506- /* Not even parallel-safe. */
6507- return false;
6508- }
6509- else if (input_rel -> partial_pathlist == NIL )
6510- {
6511- /* Nothing to use as input for partial aggregate. */
6512- return false;
6513- }
6514- else if (!parse -> hasAggs && parse -> groupClause == NIL )
6536+ if (!parse -> hasAggs && parse -> groupClause == NIL )
65156537{
65166538/*
65176539 * We don't know how to do parallel aggregation unless we have either