This is an automated email from the ASF dual-hosted git repository.
xiedeyantu 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 763ab1d7fd [CALCITE-7645] AggregateUnionTransposeRule drops aggregate
FILTER when rebuilding child aggregate calls
763ab1d7fd is described below
commit 763ab1d7fd503799634c22e92afb4ab3b1a6fa0d
Author: Zhen Chen <[email protected]>
AuthorDate: Sun Jul 5 20:01:47 2026 +0800
[CALCITE-7645] AggregateUnionTransposeRule drops aggregate FILTER when
rebuilding child aggregate calls
Signed-off-by: xiedeyantu <[email protected]>
---
.../rel/rules/AggregateUnionTransposeRule.java | 5 ++--
.../org/apache/calcite/test/RelOptRulesTest.java | 16 +++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 32 ++++++++++++++++++++++
core/src/test/resources/sql/hep.iq | 19 +++++++++++++
4 files changed, 70 insertions(+), 2 deletions(-)
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 923311a4f5..614c510a4e 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
@@ -166,8 +166,9 @@ public AggregateUnionTransposeRule(Class<? extends
Aggregate> aggregateClass,
AggregateCall newCall =
AggregateCall.create(origCall.getParserPosition(),
origCall.getAggregation(),
origCall.isDistinct(), origCall.isApproximate(),
origCall.ignoreNulls(),
- origCall.rexList, origCall.getArgList(), -1,
origCall.distinctKeys,
- origCall.collation, aggRel.getGroupSet().isEmpty(), input,
null,
+ origCall.rexList, origCall.getArgList(), origCall.filterArg,
+ origCall.distinctKeys, origCall.collation,
+ aggRel.getGroupSet().isEmpty(), input, null,
origCall.getName());
childAggCalls.set(i, newCall);
}
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 d56bde9808..18777b1ad7 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -8641,6 +8641,22 @@ private void checkSemiJoinRuleOnAntiJoin(RelOptRule
rule) {
.check();
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-7645">[CALCITE-7645]
+ * AggregateUnionTransposeRule drops aggregate FILTER when rebuilding
+ * pushed-down aggregate calls</a>. */
+ @Test void testAggregateUnionTransposeWithFilterAndNullableInput() {
+ final String sql = "select min(v) filter (where p)\n"
+ + "from (\n"
+ + " select * from (values (10, false), (100, true)) as t(v, p)\n"
+ + " union all\n"
+ + " select * from (values (cast(null as integer), true), (200, true))
as t(v, p)\n"
+ + ")";
+ 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 cdf6956ae4..2eb42b693c 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -1308,6 +1308,38 @@ 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="testAggregateUnionTransposeWithFilterAndNullableInput">
+ <Resource name="sql">
+ <![CDATA[select min(v) filter (where p)
+from (
+ select * from (values (10, false), (100, true)) as t(v, p)
+ union all
+ select * from (values (cast(null as integer), true), (200, true)) as t(v, p)
+)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[MIN($0) FILTER $1])
+ LogicalUnion(all=[true])
+ LogicalProject(V=[$0], P=[$1])
+ LogicalValues(tuples=[[{ 10, false }, { 100, true }]])
+ LogicalProject(V=[$0], P=[$1])
+ LogicalValues(tuples=[[{ null, true }, { 200, true }]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[MIN($0)])
+ LogicalUnion(all=[true])
+ LogicalAggregate(group=[{}], EXPR$0=[MIN($0) FILTER $1])
+ LogicalProject(V=[$0], P=[$1])
+ LogicalValues(tuples=[[{ 10, false }, { 100, true }]])
+ LogicalAggregate(group=[{}], EXPR$0=[MIN($0) FILTER $1])
+ LogicalProject(V=[$0], P=[$1])
+ LogicalValues(tuples=[[{ null, true }, { 200, true }]])
]]>
</Resource>
</TestCase>
diff --git a/core/src/test/resources/sql/hep.iq
b/core/src/test/resources/sql/hep.iq
index 18cdaf2722..812663177a 100644
--- a/core/src/test/resources/sql/hep.iq
+++ b/core/src/test/resources/sql/hep.iq
@@ -103,6 +103,25 @@ EnumerableSort(sort0=[$1], dir0=[ASC])
EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t3):INTEGER],
expr#9=[7698], expr#10=[=($t8, $t9)], expr#11=[CAST($t6):DECIMAL(12, 2)],
expr#12=[500.00:DECIMAL(12, 2)], expr#13=[=($t11, $t12)], expr#14=[IS NOT
TRUE($t13)], expr#15=[AND($t10, $t14)], MGR=[$t3], COMM=[$t6],
$condition=[$t15])
EnumerableTableScan(table=[[scott, EMP]])
!plan
+
+# [CALCITE-7645] AggregateUnionTransposeRule must preserve aggregate FILTER
when creating pushed-down aggregates
+!set hep-rules "
++AGGREGATE_UNION_TRANSPOSE"
+
+select min(v) filter (where p) as m
+from (
+ select * from (values (10, false), (100, true)) as t(v, p)
+ union all
+ select * from (values (cast(null as integer), true), (200, true)) as t(v, p)
+);
++-----+
+| M |
++-----+
+| 100 |
++-----+
+(1 row)
+
+!ok
!set hep-rules original
# Testing with the planner-rules shows that due to cost-based selection issues,