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

Reply via email to