mihaibudiu commented on code in PR #4288:
URL: https://github.com/apache/calcite/pull/4288#discussion_r2033718813


##########
core/src/main/java/org/apache/calcite/rex/RexBuilder.java:
##########
@@ -1917,6 +1917,27 @@ public RexLiteral makeZeroLiteral(RelDataType type) {
     return makeLiteral(zeroValue(type), type);
   }
 
+  public RexNode makeZeroForNestedType(RelDataType type) {
+    SqlOperator op;
+    switch (type.getSqlTypeName()) {
+    case ARRAY:
+      op = SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR;
+      break;
+    case MULTISET:
+      op = SqlStdOperatorTable.MULTISET_VALUE;
+      break;
+    case MAP:
+      op = SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR;
+      break;
+    case ROW:
+      op = SqlStdOperatorTable.ROW;

Review Comment:
   I don't think this works for ROW. For ROW your original solution was 
correct: you need to create a zero for each field using a recursive call.



##########
core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java:
##########
@@ -1104,6 +1107,140 @@ private static Stream<Arguments> 
testData4testMakeZeroLiteral() {
             relDataType -> new TimestampWithTimeZoneString(0, 1, 1, 0, 0, 0, 
"GMT+00:00")));
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6938";>[CALCITE-6938]
+   * Support zero value creation of nested data types</a>. */
+  @ParameterizedTest
+  @MethodSource("testData4testMakeZeroForNestedType")
+  void testMakeZeroForNestedType(RelDataType type, RexNode expected) {
+    final RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    final RexBuilder rexBuilder = new RexBuilder(typeFactory);
+    assertThat(rexBuilder.makeZeroForNestedType(type), is(equalTo(expected)));
+  }
+
+  @Test void testCreateCoalesce() {
+    RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    RexBuilder b = new RexBuilder(typeFactory);
+    RelDataType varcharType = typeFactory.createSqlType(SqlTypeName.VARCHAR);
+
+    RelDataType arrayType = new ArraySqlType(varcharType, false);
+    RexNode arrayZero = b.makeZeroForNestedType(arrayType);
+
+    RexNode array =
+        b.makeCall(arrayType, SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
+        ImmutableList.of(
+            b.makeLiteral("1", varcharType)));
+
+    RexNode coalesce1 = b.makeCall(SqlStdOperatorTable.COALESCE, array, 
arrayZero);
+    assertThat(
+        coalesce1, hasToString(
+        "COALESCE(ARRAY('1'), CAST(ARRAY()):VARCHAR NOT NULL ARRAY NOT 
NULL)"));
+
+    RelDataType mapType = new MapSqlType(arrayType, arrayType, true);
+    RexNode mapZero = b.makeZeroForNestedType(mapType);
+
+    RexNode map =
+        b.makeCall(new MapSqlType(arrayType, arrayType, true),
+        SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR,
+        ImmutableList.of(array, array));
+
+    RexNode coalesce2 = b.makeCall(SqlStdOperatorTable.COALESCE, map, mapZero);
+    assertThat(
+        coalesce2, hasToString(
+        "COALESCE(MAP(ARRAY('1'), ARRAY('1')), "
+        + "CAST(MAP()):(VARCHAR NOT NULL ARRAY NOT NULL, VARCHAR NOT NULL 
ARRAY NOT NULL) MAP)"));
+  }
+
+  private static Stream<Arguments> testData4testMakeZeroForNestedType() {
+    RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    RexBuilder b = new RexBuilder(typeFactory);
+
+    RelDataType integerType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+    RelDataType varcharType = typeFactory.createSqlType(SqlTypeName.VARCHAR);
+
+    // ARRAY<INTEGER>
+    RelDataType arrayType = new ArraySqlType(integerType, false);
+    RexNode expectedArray =
+        b.makeCast(
+            arrayType, b.makeCall(arrayType, 
SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
+            ImmutableList.of()));
+
+    // MULTISET<INTEGER>
+    RelDataType multisetType = new MultisetSqlType(integerType, false);
+    RexNode expectedMultiset =
+        b.makeCast(
+            multisetType, b.makeCall(multisetType, 
SqlStdOperatorTable.MULTISET_VALUE,
+            ImmutableList.of()));
+
+    // MAP<VARCHAR, INTEGER>
+    RelDataType mapType = new MapSqlType(varcharType, integerType, false);
+    RexNode expectedMap =
+        b.makeCast(
+            mapType, b.makeCall(mapType, 
SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR,
+            ImmutableList.of()));
+
+    // ROW<INTEGER, VARCHAR>
+    RelDataType rowType =

Review Comment:
   I don't think this would pass validation.
   Which means that these tests are not really conclusive, since they can 
generate incorrect programs. Is there a way you could make sure that these 
programs are valid?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to