This is an automated email from the ASF dual-hosted git repository.

oliver 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 943921e494 [CALCITE-5607] Serialize return type during 
RelJson.toJson(RexNode node) for SqlKind.MINUS
943921e494 is described below

commit 943921e4941282457c7b48ba0a8cd6075ddb82d7
Author: Oliver Lee <[email protected]>
AuthorDate: Tue Mar 14 15:15:21 2023 -0700

    [CALCITE-5607] Serialize return type during RelJson.toJson(RexNode node) 
for SqlKind.MINUS
    
    Uncovered a bug in RelJson#toRex for the TIMESTAMP_DIFF call for Big Query 
dialect.
    MINUS_DATE uses an ARG2_NULLABLE return type inference which requires 3 
operands, however there are only 2 operands for BQ.
    The solution here is to do something similar to how we handle CAST and to 
add in "type" when serializing to JSON in RelJson.toJson(RexNode node) for 
SqlKind.MINUS so that jsonType will be defined in toRex.
    
    Co-authored-by: TJ Banghart <[email protected]>
---
 .../apache/calcite/rel/externalize/RelJson.java    |  1 +
 .../org/apache/calcite/plan/RelWriterTest.java     | 40 +++++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

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 e915917c91..81978283da 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
@@ -622,6 +622,7 @@ public class RelJson {
         }
         map.put("operands", list);
         switch (node.getKind()) {
+        case MINUS:
         case CAST:
           map.put("type", toJson(node.getType()));
           break;
diff --git a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java 
b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
index 4a1c05d24a..f09ec0e24f 100644
--- a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
+++ b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
@@ -786,7 +786,8 @@ class RelWriterTest {
       throw TestUtil.rethrow(e);
     }
     final RelJson relJson = RelJson.create()
-        .withInputTranslator(RelWriterTest::translateInput);
+        .withInputTranslator(RelWriterTest::translateInput)
+        .withLibraryOperatorTable();
     final RexNode e = relJson.toRex(cluster, o);
     assertThat(e, hasToString(matcher));
   }
@@ -1052,6 +1053,43 @@ class RelWriterTest {
     assertThat(result, isLinux(expected));
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-5607";>[CALCITE-5607]</a>
+   *
+   * <p>Before the fix, RelJson.toRex would throw an ArrayIndexOutOfBounds 
error
+   * when deserializing MINUS_DATE due to type inference requiring 3 operands.
+   *
+   * <p>The solution is to add in 'type' when serializing to JSON.
+   */
+  @Test void testDeserializeMinusDateOperator() {
+    final FrameworkConfig config = RelBuilderTest.config().build();
+    final RelBuilder builder = RelBuilder.create(config);
+    final RexBuilder rb = builder.getRexBuilder();
+    final RelDataTypeFactory typeFactory = rb.getTypeFactory();
+    final SqlIntervalQualifier qualifier =
+        new SqlIntervalQualifier(TimeUnit.MONTH, null, SqlParserPos.ZERO);
+    final RexNode op1 = rb.makeTimestampLiteral(new 
TimestampString("2012-12-03 12:34:44"), 0);
+    final RexNode op2 = rb.makeTimestampLiteral(new 
TimestampString("2014-12-23 12:34:44"), 0);
+    final RelDataType intervalType =
+        typeFactory.createTypeWithNullability(
+            typeFactory.createSqlIntervalType(qualifier),
+            op1.getType().isNullable() || op2.getType().isNullable());
+    final RelNode rel = builder
+        .scan("EMP")
+        .project(builder.field("JOB"),
+            rb.makeCall(intervalType, SqlStdOperatorTable.MINUS_DATE,
+                ImmutableList.of(op2, op1))).build();
+    final RelJsonWriter jsonWriter =
+        new RelJsonWriter(new JsonBuilder(), 
RelJson::withLibraryOperatorTable);
+    rel.explain(jsonWriter);
+    String relJson = jsonWriter.asString();
+    String result = deserializeAndDumpToTextFormat(getSchema(rel), relJson);
+    final String expected =
+        "LogicalProject(JOB=[$2], $f1=[-(2014-12-23 12:34:44, 2012-12-03 
12:34:44)])\n"
+        + "  LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(result, isLinux(expected));
+  }
+
   @Test void testAggregateWithoutAlias() {
     final FrameworkConfig config = RelBuilderTest.config().build();
     final RelBuilder builder = RelBuilder.create(config);

Reply via email to