This is an automated email from the ASF dual-hosted git repository. xiong pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new 538016e [CALCITE-4700] AggregateUnionTransposeRule produces wrong group sets for the top Aggregate (Vladimir Ozerov) 538016e is described below commit 538016eec2b174ac159dfc0b8886671670ee555a Author: Vladimir Ozerov <ppoze...@gmail.com> AuthorDate: Mon Jul 26 09:40:49 2021 +0300 [CALCITE-4700] AggregateUnionTransposeRule produces wrong group sets for the top Aggregate (Vladimir Ozerov) --- .../rel/rules/AggregateUnionTransposeRule.java | 29 ++++++++++++++++++- .../org/apache/calcite/test/RelOptRulesTest.java | 11 ++++++++ .../org/apache/calcite/test/RelOptRulesTest.xml | 33 ++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java index e67ef89..215b12a 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionTransposeRule.java @@ -39,6 +39,10 @@ import org.apache.calcite.sql.fun.SqlSumAggFunction; import org.apache.calcite.sql.fun.SqlSumEmptyIsZeroAggFunction; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; +import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.mapping.Mapping; +import org.apache.calcite.util.mapping.MappingType; +import org.apache.calcite.util.mapping.Mappings; import com.google.common.collect.ImmutableList; @@ -156,8 +160,31 @@ public class AggregateUnionTransposeRule // create a new union whose children are the aggregates created above relBuilder.union(true, union.getInputs().size()); + + // Create the top aggregate. We must adjust group key indexes of the + // original aggregate. E.g., if the original tree was: + // + // Aggregate[groupSet=$1, ...] + // Union[...] + // + // Then the new tree should be: + // Aggregate[groupSet=$0, ...] + // Union[...] + // Aggregate[groupSet=$1, ...] + ImmutableBitSet groupSet = aggRel.getGroupSet(); + Mapping topGroupMapping = Mappings.create(MappingType.INVERSE_SURJECTION, + union.getRowType().getFieldCount(), + aggRel.getGroupCount()); + for (int i = 0; i < groupSet.cardinality(); i++) { + topGroupMapping.set(groupSet.nth(i), i); + } + + ImmutableBitSet topGroupSet = Mappings.apply(topGroupMapping, groupSet); + ImmutableList<ImmutableBitSet> topGroupSets = + Mappings.apply2(topGroupMapping, aggRel.getGroupSets()); + relBuilder.aggregate( - relBuilder.groupKey(aggRel.getGroupSet(), aggRel.getGroupSets()), + relBuilder.groupKey(topGroupSet, topGroupSets), transformedAggCalls); call.transformTo(relBuilder.build()); } 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 e2276b5..864cb95 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -5405,6 +5405,17 @@ class RelOptRulesTest extends RelOptTestBase { .checkUnchanged(); } + @Test void testAggregateUnionTransposeWithTopLevelGroupSetRemapping() { + final String sql = "select count(t1), t2 from (\n" + + "select (case when deptno=0 then 1 else null end) as t1, 1 as t2 from sales.emp e1\n" + + "union all\n" + + "select (case when deptno=0 then 1 else null end) as t1, 2 as t2 from sales.emp e2)\n" + + "group by t2"; + sql(sql) + .withPreRule(CoreRules.AGGREGATE_PROJECT_MERGE) + .withRule(CoreRules.AGGREGATE_UNION_TRANSPOSE) + .check(); + } @Test void testSortJoinTranspose1() { final String sql = "select * from sales.emp e left join (\n" 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 8991b55..b81a3be 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -1097,6 +1097,39 @@ LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)]) ]]> </Resource> </TestCase> + <TestCase name="testAggregateUnionTransposeWithTopLevelGroupSetRemapping"> + <Resource name="sql"> + <![CDATA[select count(t1), t2 from ( +select (case when deptno=0 then 1 else null end) as t1, 1 as t2 from sales.emp e1 +union all +select (case when deptno=0 then 1 else null end) as t1, 2 as t2 from sales.emp e2) +group by t2]]> + </Resource> + <Resource name="planBefore"> + <![CDATA[ +LogicalProject(EXPR$0=[$1], T2=[$0]) + LogicalAggregate(group=[{1}], EXPR$0=[COUNT($0)]) + LogicalUnion(all=[true]) + LogicalProject(T1=[CASE(=($7, 0), 1, null:INTEGER)], T2=[1]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) + LogicalProject(T1=[CASE(=($7, 0), 1, null:INTEGER)], T2=[2]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + <Resource name="planAfter"> + <![CDATA[ +LogicalProject(EXPR$0=[$1], T2=[$0]) + LogicalAggregate(group=[{0}], EXPR$0=[$SUM0($1)]) + LogicalUnion(all=[true]) + LogicalAggregate(group=[{1}], EXPR$0=[COUNT($0)]) + LogicalProject(T1=[CASE(=($7, 0), 1, null:INTEGER)], T2=[1]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) + LogicalAggregate(group=[{1}], EXPR$0=[COUNT($0)]) + LogicalProject(T1=[CASE(=($7, 0), 1, null:INTEGER)], T2=[2]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + </TestCase> <TestCase name="testAggregateWithDynamicParam"> <Resource name="sql"> <![CDATA[SELECT sal, COUNT(1) AS count_val