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

jhyde pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit 280f67bf0a7a0973ee69f3ef9eda6526d6997d0d
Author: Chunwei Lei <[email protected]>
AuthorDate: Mon Dec 7 16:03:23 2020 +0800

    [CALCITE-4429] RelOptUtil#createCastRel should throw if source and target 
row types have a different number of fields
    
    Close apache/calcite#2292
---
 .../main/java/org/apache/calcite/plan/RelOptUtil.java | 10 ++++++++++
 .../java/org/apache/calcite/tools/RelBuilder.java     |  3 +++
 .../java/org/apache/calcite/test/RelBuilderTest.java  | 19 +++++++++++++++++++
 3 files changed, 32 insertions(+)

diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java 
b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index ea7b2dc..059b9ce 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -829,6 +829,9 @@ public abstract class RelOptUtil {
    * instead, create a projection with the input of {@code rel} and the new
    * cast expressions.
    *
+   * <p>The desired row type and the row type to be converted must have the
+   * same number of fields.
+   *
    * @param rel         producer of rows to be converted
    * @param castRowType row type after cast
    * @param rename      if true, use field names from castRowType; if false,
@@ -850,6 +853,9 @@ public abstract class RelOptUtil {
    * instead, create a projection with the input of {@code rel} and the new
    * cast expressions.
    *
+   * <p>The desired row type and the row type to be converted must have the
+   * same number of fields.
+   *
    * @param rel         producer of rows to be converted
    * @param castRowType row type after cast
    * @param rename      if true, use field names from castRowType; if false,
@@ -868,6 +874,10 @@ public abstract class RelOptUtil {
       // nothing to do
       return rel;
     }
+    if (rowType.getFieldCount() != castRowType.getFieldCount()) {
+      throw new IllegalArgumentException("Field counts are not equal: "
+          + "rowType [" + rowType + "] castRowType [" + castRowType + "]");
+    }
     final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
     List<RexNode> castExps;
     RelNode input;
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java 
b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index b45d1d2..3c9acf5 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -2838,6 +2838,9 @@ public class RelBuilder {
    * Creates a projection that converts the current relational expression's
    * output to a desired row type.
    *
+   * <p>The desired row type and the row type to be converted must have the
+   * same number of fields.
+   *
    * @param castRowType row type after cast
    * @param rename      if true, use field names from castRowType; if false,
    *                    preserve field names from rel
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java 
b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index 0d09de3..2549b76 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -1102,6 +1102,25 @@ public class RelBuilderTest {
     assertThat(root, hasTree(expected));
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-4429";>[CALCITE-4429]
+   * RelOptUtil#createCastRel should throw an exception when the desired row 
type
+   * and the row type to be converted don't have the same number of 
fields</a>. */
+  @Test void testConvertNegative() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    RelDataType rowType =
+        builder.getTypeFactory().builder()
+            .add("a", SqlTypeName.BIGINT)
+            .add("b", SqlTypeName.VARCHAR, 10)
+            .build();
+    IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, 
() -> {
+      builder.scan("DEPT")
+          .convert(rowType, false)
+          .build();
+    }, "Convert should fail since the field counts are not equal.");
+    assertThat(ex.getMessage(), containsString("Field counts are not equal"));
+  }
+
   @Test void testAggregate() {
     // Equivalent SQL:
     //   SELECT COUNT(DISTINCT deptno) AS c

Reply via email to