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
