This is an automated email from the ASF dual-hosted git repository.
mbudiu 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 ea08b43db6 [CALCITE-7391] FILTER_REDUCE_EXPRESSIONS crashes on
expression where 123 in (SELECT NULL FROM emps)
ea08b43db6 is described below
commit ea08b43db6bc83ea76678bd77873e110083c0edc
Author: Dongsheng He <[email protected]>
AuthorDate: Thu Jan 22 10:43:50 2026 +0800
[CALCITE-7391] FILTER_REDUCE_EXPRESSIONS crashes on expression where 123 in
(SELECT NULL FROM emps)
---
.../rel/rules/FilterProjectTransposeRule.java | 9 +++++++
.../org/apache/calcite/test/RelOptRulesTest.java | 11 +++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 28 ++++++++++++++++++++++
3 files changed, 48 insertions(+)
diff --git
a/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
b/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
index 3e3cf46a11..3c365222cd 100644
---
a/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
+++
b/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
@@ -28,6 +28,7 @@
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.RelFactories;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexSimplify;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.tools.RelBuilder;
import org.apache.calcite.tools.RelBuilderFactory;
@@ -35,7 +36,9 @@
import org.immutables.value.Value;
import java.util.Collections;
+import java.util.List;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
/**
* Planner rule that pushes
@@ -170,6 +173,12 @@ protected FilterProjectTransposeRule(
}
final RelBuilder relBuilder = call.builder();
+ List<RexNode> conjuncts = RelOptUtil.conjunctions(newCondition);
+ List<RexNode> simplified = conjuncts.stream()
+ .map(e -> RexSimplify.simplifyComparisonWithNull(e,
relBuilder.getRexBuilder()))
+ .collect(Collectors.toList());
+ newCondition = RexUtil.composeConjunction(relBuilder.getRexBuilder(),
simplified);
+
RelNode newFilterRel;
if (config.isCopyFilter()) {
final RelNode input = project.getInput();
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 2c8c5eab43..94bb87651f 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -9593,6 +9593,17 @@ private void checkSemiJoinRuleOnAntiJoin(RelOptRule
rule) {
sql(sql).withRule(subQueryFilterRule).withLateDecorrelate(true).check();
}
+ /** Test case for <a
href="https://issues.apache.org/jira/browse/CALCITE-7391">[CALCITE-7391]
+ * FILTER_REDUCE_EXPRESSIONS crashes on expression where 123 in (SELECT NULL
FROM emps)</a>. */
+ @Test void testNullSelect2() {
+ final String sql = "SELECT * from emp where 123 in (select null from
dept)";
+ sql(sql)
+ .withRule(CoreRules.FILTER_SUB_QUERY_TO_CORRELATE,
+ CoreRules.FILTER_PROJECT_TRANSPOSE,
+ CoreRules.PROJECT_REDUCE_EXPRESSIONS)
+ .check();
+ }
+
/** Test case for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-6652">[CALCITE-6652]
* RelDecorrelator can't decorrelate query with limit 1</a>.
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 5fa2ddc3eb..67e86d45b6 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -11062,6 +11062,34 @@ LogicalProject(EXPR$0=[1])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
LogicalProject(cs=[true])
LogicalValues(tuples=[[]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testNullSelect2">
+ <Resource name="sql">
+ <![CDATA[SELECT * from emp where 123 in (select null from dept)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
+ LogicalFilter(condition=[IN(123, {
+LogicalProject(EXPR$0=[null:INTEGER])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+})])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
+ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
+ LogicalJoin(condition=[true], joinType=[inner])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalAggregate(group=[{0}])
+ LogicalProject(cs=[true])
+ LogicalProject(EXPR$0=[null:INTEGER])
+ LogicalFilter(condition=[false])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
]]>
</Resource>
</TestCase>