From 0a06f55c3f57272181c6947986b62343af9a0b85 Mon Sep 17 00:00:00 2001 From: Stamatis Zampetakis Date: Fri, 13 Mar 2026 15:59:21 +0100 Subject: [PATCH] [CALCITE-7441] AggregateFilterToFilteredAggregateRule fails when WHERE condition is nullable --- ...ggregateFilterToFilteredAggregateRule.java | 4 ++++ ...gateFilterToFilteredAggregateRuleTest.java | 6 ++++++ ...egateFilterToFilteredAggregateRuleTest.xml | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterToFilteredAggregateRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterToFilteredAggregateRule.java index dd82f697622..f814b6b9b8b 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterToFilteredAggregateRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateFilterToFilteredAggregateRule.java @@ -22,6 +22,7 @@ import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.tools.RelBuilder; import org.immutables.value.Value; @@ -76,6 +77,9 @@ private AggregateFilterToFilteredAggregateRule(Config config) { return; } RexNode condition = filter.getCondition(); + if (condition.getType().isNullable()) { + condition = builder.call(SqlStdOperatorTable.IS_TRUE, condition); + } // If the aggregate call has its own filter, combine it with the filter condition. if (aggCall.hasFilter()) { condition = builder.and(condition, builder.field(aggCall.filterArg)); diff --git a/core/src/test/java/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.java b/core/src/test/java/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.java index 9e6cd3ea339..326524e7474 100644 --- a/core/src/test/java/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.java +++ b/core/src/test/java/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.java @@ -58,6 +58,12 @@ private static RelOptFixture sql(String sql) { .withRule(AGGREGATE_FILTER_TO_FILTERED_AGGREGATE).check(); } + @Test void testSingleColumnAggregateWithFilterOnNullableColumn() { + String sql = "select sum(sal) from emp where mgr = 10"; + sql(sql).withPreRule(AGGREGATE_PROJECT_MERGE) + .withRule(AGGREGATE_FILTER_TO_FILTERED_AGGREGATE).check(); + } + @Test void testSingleStarAggregate() { String sql = "select count(*) from emp where deptno = 10"; sql(sql).withPreRule(AGGREGATE_PROJECT_MERGE) diff --git a/core/src/test/resources/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.xml b/core/src/test/resources/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.xml index b31112c3f33..47ca7c9bd13 100644 --- a/core/src/test/resources/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/AggregateFilterToFilteredAggregateRuleTest.xml @@ -101,6 +101,25 @@ LogicalAggregate(group=[{}], EXPR$0=[SUM($5)]) LogicalAggregate(group=[{}], EXPR$0=[SUM($0) FILTER $1]) LogicalProject(SAL=[$5], $f9=[=($7, 10)]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + + + + + + + + + + +