diff --git a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java index ddd91b1bed8..07c0470b937 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java +++ b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java @@ -448,7 +448,7 @@ public AggregateCall rename(@Nullable String name) { } buf.append(")"); } - if (!collation.equals(RelCollations.EMPTY)) { + if (hasCollation()) { buf.append(" WITHIN GROUP ("); buf.append(collation); buf.append(")"); @@ -465,6 +465,11 @@ public boolean hasFilter() { return filterArg >= 0; } + /** Returns true if this AggregateCall has a non-empty collation. Returns false otherwise. */ + public boolean hasCollation() { + return !collation.equals(RelCollations.EMPTY); + } + /** Withs {@link #filterArg}. */ public AggregateCall withFilter(int filterArg) { return filterArg == this.filterArg ? this diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java index a47a68ca93f..111cf0c6b6f 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java @@ -348,10 +348,13 @@ int getCount(int filterArg) { if (c.distinctKeys == null) { RelBuilder.AggCall aggCall = b.aggregateCall(c.getParserPosition(), c.getAggregation(), b.fields(c.getArgList())); - registrar.registerAgg(i, - c.hasFilter() - ? aggCall.filter(b.field(c.filterArg)) - : aggCall); + if (c.hasFilter()) { + aggCall = aggCall.filter(b.field(c.filterArg)); + } + if (c.hasCollation()) { + aggCall = aggCall.sort(b.fields(c.getCollation())); + } + registrar.registerAgg(i, aggCall); } else { for (int inputIdx : c.getArgList()) { registrar.register(inputIdx, c.filterArg); diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java index cb15194c038..bf4071592f3 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -2417,6 +2417,24 @@ private void checkSemiOrAntiJoinProjectTranspose(JoinRelType type) { sql(sql).withProgram(program).check(); } + /** Test case for + * [CALCITE-6595] + * Preserve collation for non-distinct aggregate calls with AggregateExpandWithinDistinctRule. + * + *
Test that AggregateExpandWithinDistinctRule preserves collation on non-distinct aggregates
+ * with a WITHIN GROUP clause in a query that also includes a distinct aggregate. */
+ @Test void testWithinDistinctPreservesNonDistinctCollation() {
+ final String sql = "SELECT SUM(sal) WITHIN DISTINCT (job),\n"
+ + "LISTAGG(ename, '; ') WITHIN GROUP (ORDER BY sal DESC)\n"
+ + " FROM Emp\n"
+ + "GROUP BY deptno";
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(CoreRules.AGGREGATE_REDUCE_FUNCTIONS)
+ .addRuleInstance(CoreRules.AGGREGATE_EXPAND_WITHIN_DISTINCT)
+ .build();
+ sql(sql).withProgram(program).check();
+ }
+
/** Tests {@link AggregateExpandWithinDistinctRule}. Includes multiple
* different filters for the aggregate calls, and all aggregate calls have the
* same distinct keys, so there is no need to filter based on
diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index ec4d69b9c08..b6e04f08812 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -17378,6 +17378,33 @@ LogicalProject(DEPTNO=[$0], EXPR$1=[CASE(=($2, 0), null:INTEGER, $1)], EXPR$2=[$
LogicalAggregate(group=[{0, 3}], groups=[[{0, 3}, {0}]], agg#0=[$SUM0($1) FILTER $2], agg#1=[COUNT() FILTER $2], agg#2=[MIN($1)], agg#3=[MAX($1)], agg#4=[GROUPING($0, $3)])
LogicalProject(DEPTNO=[$7], SAL=[$5], $f2=[>($5, 1000)], JOB=[$2])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+
+
+