diff options
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 0f423e96847..3e3f0d486a2 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -4094,9 +4094,10 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, * If this is the topmost relation or if the parent relation is doing * full partitionwise aggregation, then we can do full partitionwise * aggregation provided that the GROUP BY clause contains all of the - * partitioning columns at this level. Otherwise, we can do at most - * partial partitionwise aggregation. But if partial aggregation is - * not supported in general then we can't use it for partitionwise + * partitioning columns at this level and the collation used by GROUP + * BY matches the partitioning collation. Otherwise, we can do at + * most partial partitionwise aggregation. But if partial aggregation + * is not supported in general then we can't use it for partitionwise * aggregation either. * * Check parse->groupClause not processed_groupClause, because it's @@ -8105,8 +8106,8 @@ create_partitionwise_grouping_paths(PlannerInfo *root, /* * group_by_has_partkey * - * Returns true, if all the partition keys of the given relation are part of - * the GROUP BY clauses, false otherwise. + * Returns true if all the partition keys of the given relation are part of + * the GROUP BY clauses, including having matching collation, false otherwise. */ static bool group_by_has_partkey(RelOptInfo *input_rel, @@ -8134,13 +8135,40 @@ group_by_has_partkey(RelOptInfo *input_rel, foreach(lc, partexprs) { + ListCell *lg; Expr *partexpr = lfirst(lc); + Oid partcoll = input_rel->part_scheme->partcollation[cnt]; - if (list_member(groupexprs, partexpr)) + foreach(lg, groupexprs) { - found = true; - break; + Expr *groupexpr = lfirst(lg); + Oid groupcoll = exprCollation((Node *) groupexpr); + + /* + * Note: we can assume there is at most one RelabelType node; + * eval_const_expressions() will have simplified if more than + * one. + */ + if (IsA(groupexpr, RelabelType)) + groupexpr = ((RelabelType *) groupexpr)->arg; + + if (equal(groupexpr, partexpr)) + { + /* + * Reject a match if the grouping collation does not match + * the partitioning collation. + */ + if (OidIsValid(partcoll) && OidIsValid(groupcoll) && + partcoll != groupcoll) + return false; + + found = true; + break; + } } + + if (found) + break; } /* |