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"
+ + " }"));
+ }
}