This is an automated email from the ASF dual-hosted git repository.
mihaibudiu 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 7925800cb8 [CALCITE-7718] Lambda capturing ROW field crashes at
compilation with assertion failure
7925800cb8 is described below
commit 7925800cb86892e32183959776cf476c4add1244
Author: Mihai Budiu <[email protected]>
AuthorDate: Thu Aug 13 17:22:33 2026 -0700
[CALCITE-7718] Lambda capturing ROW field crashes at compilation with
assertion failure
Signed-off-by: Mihai Budiu <[email protected]>
---
.../java/org/apache/calcite/plan/RelOptUtil.java | 13 ----------
.../apache/calcite/test/SqlToRelConverterTest.java | 28 ++++++++++++++++++++++
.../apache/calcite/test/SqlToRelConverterTest.xml | 24 +++++++++++++++++++
core/src/test/resources/sql/lambda.iq | 26 ++++++++++++++++++++
4 files changed, 78 insertions(+), 13 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 97146b625a..42e86b5c4b 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -70,7 +70,6 @@
import org.apache.calcite.rex.RexExecutorImpl;
import org.apache.calcite.rex.RexFieldAccess;
import org.apache.calcite.rex.RexInputRef;
-import org.apache.calcite.rex.RexLambda;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
@@ -3371,12 +3370,6 @@ private static RexShuttle pushShuttle(final Project
project) {
@Override public RexNode visitInputRef(RexInputRef ref) {
return project.getProjects().get(ref.getIndex());
}
-
- @Override public RexNode visitLambda(RexLambda lambda) {
- // Lambda body references are at a different scope level.
- // Do not remap indices inside lambda body against this project.
- return lambda;
- }
};
}
@@ -3400,12 +3393,6 @@ private static RexShuttle pushShuttle(final Calc calc) {
@Override public RexNode visitInputRef(RexInputRef ref) {
return projects.get(ref.getIndex());
}
-
- @Override public RexNode visitLambda(RexLambda lambda) {
- // Lambda body references are at a different scope level.
- // Do not remap indices inside lambda body against this calc.
- return lambda;
- }
};
}
diff --git
a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index fb814f3e88..d56b7d5437 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -158,6 +158,34 @@ public static void checkActualAndReferenceFiles() {
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-7718">[CALCITE-7718]
+ * Lambda capturing ROW field crashes at compilation with assertion
+ * failure</a>. */
+ @Test void testLambdaExpressionWithStructCaptureMerge() {
+ final String sql = "select \"EXISTS\"(array(1, 2), x -> x =
t.r.\"EXPR$0\")\n"
+ + "from (select ROW(1, 2) as r) as t";
+ fixture()
+ .withFactory(c ->
+ c.withOperatorTable(t ->
SqlValidatorTest.operatorTableFor(SqlLibrary.SPARK)))
+ .withSql(sql)
+ .ok();
+ }
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-7718">[CALCITE-7718]
+ * Lambda capturing ROW field crashes at compilation with assertion
+ * failure</a>. */
+ @Test void testLambdaExpressionWithStructCaptureMergeOverScan() {
+ final String sql = "select \"EXISTS\"(array(1, 2), x -> x =
t.r.\"EXPR$0\")\n"
+ + "from (select ROW(deptno, sal) as r from emp) as t";
+ fixture()
+ .withFactory(c ->
+ c.withOperatorTable(t ->
SqlValidatorTest.operatorTableFor(SqlLibrary.SPARK)))
+ .withSql(sql)
+ .ok();
+ }
+
/** Test case for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-3679">[CALCITE-3679]
* Allow lambda expressions in SQL queries</a>. */
diff --git
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 38479e0da8..0d97150eb6 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -5166,6 +5166,30 @@ LogicalProject(EXPR$0=[HIGHER_ORDER_FUNCTION($7, (X,
DEPTNO) -> +(DEPTNO, 1))])
<![CDATA[
LogicalProject(EXPR$0=[EXISTS(ARRAY(1, 2, 3, 4), (N) -> OR(=(N, 1), =(N, 3)))])
LogicalValues(tuples=[[{ 0 }]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testLambdaExpressionWithStructCaptureMerge">
+ <Resource name="sql">
+ <![CDATA[select "EXISTS"(array(1, 2), x -> x = t.r."EXPR$0")
+from (select ROW(1, 2) as r) as t]]>
+ </Resource>
+ <Resource name="plan">
+ <![CDATA[
+LogicalProject(EXPR$0=[EXISTS(ARRAY(1, 2), (X) -> =(X, ROW(1, 2).EXPR$0))])
+ LogicalValues(tuples=[[{ 0 }]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testLambdaExpressionWithStructCaptureMergeOverScan">
+ <Resource name="sql">
+ <![CDATA[select "EXISTS"(array(1, 2), x -> x = t.r."EXPR$0")
+from (select ROW(deptno, sal) as r from emp) as t]]>
+ </Resource>
+ <Resource name="plan">
+ <![CDATA[
+LogicalProject(EXPR$0=[EXISTS(ARRAY(1, 2), (X) -> =(X, ROW($7, $5).EXPR$0))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>
diff --git a/core/src/test/resources/sql/lambda.iq
b/core/src/test/resources/sql/lambda.iq
index 82808ff19d..accc60b4e8 100644
--- a/core/src/test/resources/sql/lambda.iq
+++ b/core/src/test/resources/sql/lambda.iq
@@ -145,3 +145,29 @@ select "EXISTS"(array(1, 2, 3), x -> "EXISTS"(array(1, 2,
3), y -> x + y = 4)) a
(1 row)
!ok
+
+# [CALCITE-7718] Lambda capturing ROW field crashes at compilation with
+# assertion failure.
+# Lambda captures a field of a struct value from the enclosing query.
+select "EXISTS"(array(1, 2), x -> x = t.r."EXPR$0") from (select ROW(1, 2) as
r) as t;
++--------+
+| EXPR$0 |
++--------+
+| true |
++--------+
+(1 row)
+
+!ok
+
+# Same, but the captured struct is built from table columns
+# Jane is in dept 10
+select "EXISTS"(array(5, 10), x -> x = t.r."EXPR$0")
+from (select ROW(deptno, 1) as r from emp where ename = 'Jane') as t;
++--------+
+| EXPR$0 |
++--------+
+| true |
++--------+
+(1 row)
+
+!ok