[CALCITE-6323] Serialize return type during RelJson.toJson(RexNode node) for SqlKind.SAFE_CAST
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 ebc4d2e..3f7cbbc 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
@@ -632,6 +632,7 @@
switch (node.getKind()) {
case MINUS:
case CAST:
+ case SAFE_CAST:
map.put("type", toJson(node.getType()));
break;
default:
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 9bde841..ccb3755 100644
--- a/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
+++ b/core/src/test/java/org/apache/calcite/plan/RelWriterTest.java
@@ -1091,6 +1091,36 @@
assertThat(result, isLinux(expected));
}
+ /** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-6323">[CALCITE-6323]</a>
+ *
+ * <p>Before the fix, RelJson.toRex would throw an ArrayIndexOutOfBounds error
+ * when deserializing SAFE_CAST due to type inference requiring 2 operands.
+ *
+ * <p>The solution is to add in 'type' when serializing to JSON.
+ */
+ @Test void testDeserializeSafeCastOperator() {
+ final FrameworkConfig config = RelBuilderTest.config().build();
+ final RelBuilder builder = RelBuilder.create(config);
+ final RexBuilder rb = builder.getRexBuilder();
+ final RelDataTypeFactory typeFactory = rb.getTypeFactory();
+ final RelDataType type = typeFactory.createSqlType(SqlTypeName.DATE);
+ final RelNode rel = builder
+ .scan("EMP")
+ .project(builder.field("JOB"),
+ rb.makeCall(type, SqlLibraryOperators.SAFE_CAST,
+ ImmutableList.of(builder.field("SAL")))).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=[SAFE_CAST($5)])\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);