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 347664b494 [CALCITE-7113] RelJson cannot serialize RexLambda
347664b494 is described below

commit 347664b4943ba0680cd5aa7af23405ca5bdde08a
Author: Mihai Budiu <[email protected]>
AuthorDate: Wed Jul 30 16:24:10 2025 -0700

    [CALCITE-7113] RelJson cannot serialize RexLambda
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../apache/calcite/rel/externalize/RelJson.java    | 22 ++++++
 .../calcite/rel/externalize/RelJsonTest.java       | 79 ++++++++++++++++++++++
 2 files changed, 101 insertions(+)

diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java 
b/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java
index a0d09e13a3..17a34411eb 100644
--- a/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java
+++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java
@@ -43,6 +43,8 @@
 import org.apache.calcite.rex.RexDynamicParam;
 import org.apache.calcite.rex.RexFieldAccess;
 import org.apache.calcite.rex.RexFieldCollation;
+import org.apache.calcite.rex.RexLambda;
+import org.apache.calcite.rex.RexLambdaRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexOver;
@@ -615,6 +617,26 @@ public Object toJson(RexNode node) {
       map.put("correl", ((RexCorrelVariable) node).getName());
       map.put("type", toJson(node.getType()));
       return map;
+    case LAMBDA_REF: {
+      RexLambdaRef ref = (RexLambdaRef) node;
+      map = jsonBuilder().map();
+      map.put("index", ref.getIndex());
+      map.put("name", ref.getName());
+      map.put("type", toJson(ref.getType()));
+      return map;
+    }
+    case LAMBDA: {
+      RexLambda lambda = (RexLambda) node;
+      map = jsonBuilder().map();
+      final List<@Nullable Object> parameters = jsonBuilder().list();
+      for (RexLambdaRef param : lambda.getParameters()) {
+        parameters.add(toJson(param));
+      }
+      map.put("op", "lambda");
+      map.put("parameters", parameters);
+      map.put("expression", toJson(lambda.getExpression()));
+      return map;
+    }
     default:
       if (node instanceof RexCall) {
         final RexCall call = (RexCall) node;
diff --git 
a/core/src/test/java/org/apache/calcite/rel/externalize/RelJsonTest.java 
b/core/src/test/java/org/apache/calcite/rel/externalize/RelJsonTest.java
index 07d823bac8..9bc8040b90 100644
--- a/core/src/test/java/org/apache/calcite/rel/externalize/RelJsonTest.java
+++ b/core/src/test/java/org/apache/calcite/rel/externalize/RelJsonTest.java
@@ -16,18 +16,39 @@
  */
 package org.apache.calcite.rel.externalize;
 
+import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.sql.SqlExplainFormat;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperatorTable;
+import org.apache.calcite.sql.fun.SqlLibrary;
+import org.apache.calcite.sql.fun.SqlLibraryOperatorTableFactory;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.calcite.sql.parser.SqlParser;
 import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.test.DiffRepository;
+import org.apache.calcite.tools.FrameworkConfig;
+import org.apache.calcite.tools.Frameworks;
+import org.apache.calcite.tools.Planner;
+import org.apache.calcite.tools.RelConversionException;
+import org.apache.calcite.tools.ValidationException;
 import org.apache.calcite.util.JsonBuilder;
 
 import org.junit.jupiter.api.Test;
 
+import java.util.EnumSet;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+
 /**
  * Unit tests for @{@link RelJson}.
  */
@@ -50,4 +71,62 @@ public class RelJsonTest {
     REPO.assertEquals("content", "${content}", builder.toJsonString(jsonObj));
   }
 
+  /** Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-7113";>[CALCITE-7113]
+   * RelJson cannot serialize RexLambda</a>. */
+  @Test void testLambda() throws SqlParseException, ValidationException, 
RelConversionException {
+    final String query = "SELECT \"EXISTS\"(ARRAY[1], x -> x > 2)";
+    SqlOperatorTable opTab = SqlLibraryOperatorTableFactory.INSTANCE
+        .getOperatorTable(EnumSet.of(SqlLibrary.STANDARD, SqlLibrary.SPARK));
+    final SchemaPlus rootSchema = Frameworks.createRootSchema(true);
+    final FrameworkConfig config = Frameworks.newConfigBuilder()
+        .parserConfig(SqlParser.Config.DEFAULT)
+        .operatorTable(opTab)
+        .defaultSchema(rootSchema)
+        .build();
+    Planner planner = Frameworks.getPlanner(config);
+    SqlNode n = planner.parse(query);
+    n = planner.validate(n);
+    RelNode root = planner.rel(n).project();
+    String plan =
+        RelOptUtil.dumpPlan("-- Plan", root,
+            SqlExplainFormat.JSON, SqlExplainLevel.DIGEST_ATTRIBUTES);
+    assertThat(
+        plan, containsString("{\n"
+        + "              \"op\": \"lambda\",\n"
+        + "              \"parameters\": [\n"
+        + "                {\n"
+        + "                  \"index\": 0,\n"
+        + "                  \"name\": \"X\",\n"
+        + "                  \"type\": {\n"
+        + "                    \"type\": \"INTEGER\",\n"
+        + "                    \"nullable\": false\n"
+        + "                  }\n"
+        + "                }\n"
+        + "              ],\n"
+        + "              \"expression\": {\n"
+        + "                \"op\": {\n"
+        + "                  \"name\": \">\",\n"
+        + "                  \"kind\": \"GREATER_THAN\",\n"
+        + "                  \"syntax\": \"BINARY\"\n"
+        + "                },\n"
+        + "                \"operands\": [\n"
+        + "                  {\n"
+        + "                    \"index\": 0,\n"
+        + "                    \"name\": \"X\",\n"
+        + "                    \"type\": {\n"
+        + "                      \"type\": \"INTEGER\",\n"
+        + "                      \"nullable\": false\n"
+        + "                    }\n"
+        + "                  },\n"
+        + "                  {\n"
+        + "                    \"literal\": 2,\n"
+        + "                    \"type\": {\n"
+        + "                      \"type\": \"INTEGER\",\n"
+        + "                      \"nullable\": false\n"
+        + "                    }\n"
+        + "                  }\n"
+        + "                ]\n"
+        + "              }\n"
+        + "            }"));
+  }
 }

Reply via email to