This is an automated email from the ASF dual-hosted git repository.
rubenql pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new add1f8b8da [CALCITE-6642] AggregateUnionTransposeRule should account
for changes in nullability of pushed down aggregates
add1f8b8da is described below
commit add1f8b8dac86bfbd8a9de5169baa97347119256
Author: Claude Brisson <[email protected]>
AuthorDate: Fri Oct 25 04:53:33 2024 +0200
[CALCITE-6642] AggregateUnionTransposeRule should account for changes in
nullability of pushed down aggregates
---
.../rel/rules/AggregateUnionTransposeRule.java | 24 ++++++++++++++++-
.../org/apache/calcite/test/RelOptRulesTest.java | 15 +++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 31 ++++++++++++++++++++++
3 files changed, 69 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 4721d6997c..4d3d55e26f 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
@@ -152,10 +152,32 @@ public class AggregateUnionTransposeRule
// create corresponding aggregates on top of each union child
final RelBuilder relBuilder = call.builder();
+ RelDataType origUnionType = union.getRowType();
for (RelNode input : union.getInputs()) {
+ List<AggregateCall> childAggCalls = new
ArrayList<>(aggRel.getAggCallList());
+ // if the nullability of a specific input column differs from the
nullability
+ // of the union'ed column, we need to re-evaluate the nullability of the
aggregate
+ RelDataType inputRowType = input.getRowType();
+ for (int i = 0; i < childAggCalls.size(); ++i) {
+ AggregateCall origCall = aggRel.getAggCallList().get(i);
+ if (origCall.getAggregation() == SqlStdOperatorTable.COUNT) {
+ continue;
+ }
+ assert origCall.getArgList().size() == 1;
+ int field = origCall.getArgList().get(0);
+ if (origUnionType.getFieldList().get(field).getType().isNullable()
+ != inputRowType.getFieldList().get(field).getType().isNullable()) {
+ AggregateCall newCall =
+ AggregateCall.create(origCall.getParserPosition(),
origCall.getAggregation(),
+ origCall.isDistinct(), origCall.isApproximate(),
origCall.ignoreNulls(),
+ origCall.rexList, origCall.getArgList(), -1,
origCall.distinctKeys,
+ origCall.collation, groupCount, input, null,
origCall.getName());
+ childAggCalls.set(i, newCall);
+ }
+ }
relBuilder.push(input);
relBuilder.aggregate(relBuilder.groupKey(aggRel.getGroupSet()),
- aggRel.getAggCallList());
+ childAggCalls);
}
// create a new union whose children are the aggregates created above
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 26571b70bd..cabd12612e 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -7434,6 +7434,21 @@ class RelOptRulesTest extends RelOptTestBase {
.check();
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6642">[CALCITE-6642]
+ * AggregateUnionTransposeRule throws an assertion error when creating
children aggregates
+ * when one input only has a non-nullable column</a>. */
+ @Test void testAggregateUnionTransposeWithOneInputNonNullable() {
+ final String sql = "select deptno, SUM(t) from (\n"
+ + "select deptno, 1 as t from sales.emp e1\n"
+ + "union all\n"
+ + "select deptno, nullif(sal, 0) as t from sales.emp e2)\n"
+ + "group by deptno";
+ sql(sql)
+ .withRule(CoreRules.AGGREGATE_UNION_TRANSPOSE)
+ .check();
+ }
+
/** If all inputs to UNION are already unique, AggregateUnionTransposeRule is
* a no-op. */
@Test void testAggregateUnionTransposeWithAllInputsUnique() {
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 da7c881b22..d5c1bbc4d2 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -1023,6 +1023,37 @@ LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)])
LogicalAggregate(group=[{0, 1}])
LogicalProject(DEPTNO=[$7], T=[2])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testAggregateUnionTransposeWithOneInputNonNullable">
+ <Resource name="sql">
+ <![CDATA[select deptno, SUM(t) from (
+select deptno, 1 as t from sales.emp e1
+union all
+select deptno, nullif(sal, 0) as t from sales.emp e2)
+group by deptno]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)])
+ LogicalUnion(all=[true])
+ LogicalProject(DEPTNO=[$7], T=[1])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalProject(DEPTNO=[$7], T=[CASE(=($5, 0), null:INTEGER, $5)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)])
+ LogicalUnion(all=[true])
+ LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)])
+ LogicalProject(DEPTNO=[$7], T=[1])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalAggregate(group=[{0}], EXPR$1=[SUM($1)])
+ LogicalProject(DEPTNO=[$7], T=[CASE(=($5, 0), null:INTEGER, $5)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>