This is an automated email from the ASF dual-hosted git repository. zabetak pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new 1018d25 [CALCITE-2900] RelStructuredTypeFlattener generates wrong types on nested columns (Will Yu) 1018d25 is described below commit 1018d25af62da638f8125e24214d3b97a76f71c2 Author: Will Yu <wmy7...@gmail.com> AuthorDate: Fri Mar 22 21:36:16 2019 -0700 [CALCITE-2900] RelStructuredTypeFlattener generates wrong types on nested columns (Will Yu) Close #1104 --- .../sql2rel/RelStructuredTypeFlattener.java | 22 +++++++++++++++++----- .../apache/calcite/test/SqlToRelConverterTest.java | 11 +++++++++++ .../apache/calcite/test/SqlToRelConverterTest.xml | 10 ++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java index 3a28d84..6b26808 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java @@ -303,9 +303,11 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor { * corresponding field post-flattening, and also returns its type. * * @param oldOrdinal Pre-flattening ordinal + * @param existingOffset offset already calculated the target column inside the oldOrdinal column. + * For unnested column, it should be 0. * @return Post-flattening ordinal and type */ - protected Ord<RelDataType> getNewFieldForOldInput(int oldOrdinal) { + private Ord<RelDataType> getNewFieldForOldInput(int oldOrdinal, int existingOffset) { assert currentRel != null; int newOrdinal = 0; @@ -328,7 +330,7 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor { assert newInput != null; RelDataType oldInputType = oldInput.getRowType(); - final int newOffset = calculateFlattenedOffset(oldInputType, oldOrdinal); + final int newOffset = calculateFlattenedOffset(oldInputType, oldOrdinal) + existingOffset; newOrdinal += newOffset; final RelDataTypeField field = newInput.getRowType().getFieldList().get(newOffset); @@ -336,6 +338,17 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor { } /** + * Maps the ordinal of a field pre-flattening to the ordinal of the + * corresponding field post-flattening, and also returns its type. + * + * @param oldOrdinal Pre-flattening ordinal + * @return Post-flattening ordinal and type + */ + protected Ord<RelDataType> getNewFieldForOldInput(int oldOrdinal) { + return getNewFieldForOldInput(oldOrdinal, 0); + } + + /** * Returns a mapping between old and new fields. * * @param oldRel Old relational expression @@ -822,9 +835,8 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor { // correct ordinal and type. RexInputRef inputRef = (RexInputRef) refExp; final Ord<RelDataType> newField = - getNewFieldForOldInput(inputRef.getIndex()); - iInput += newField.i; - return new RexInputRef(iInput, removeDistinct(newField.e)); + getNewFieldForOldInput(inputRef.getIndex(), iInput); + return new RexInputRef(newField.getKey(), removeDistinct(newField.getValue())); } else if (refExp instanceof RexCorrelVariable) { RelDataType refType = SqlTypeUtil.flattenRecordType( diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java index b5749b1..7d13416 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java @@ -2616,6 +2616,17 @@ public class SqlToRelConverterTest extends SqlToRelTestBase { sql(sql).with(getTesterWithDynamicTable()).ok(); } + /** + * Test case for <a href="https://issues.apache.org/jira/browse/CALCITE-2900">[CALCITE-2900] + * RelStructuredTypeFlattener generates wrong types on nested columns</a>. + */ + @Test + public void testNestedColumnType() { + final String sql = + "select empa.home_address.zip from sales.emp_address empa where empa.home_address.city = 'abc'"; + sql(sql).ok(); + } + @Test public void testDynamicSchemaUnnest() { final String sql3 = "select t1.c_nationkey, t3.fake_col3\n" + "from SALES.CUSTOMER as t1,\n" diff --git a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml index dc4219c..25589d2 100644 --- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml @@ -860,6 +860,16 @@ LogicalProject(FAKE2=[ITEM($0, 'fake_col2')]) ]]> </Resource> </TestCase> + <TestCase name="testNestedColumnType"> + <Resource name="plan"> + <![CDATA[ +LogicalProject(ZIP=[$4]) + LogicalFilter(condition=[=($3, 'abc':VARCHAR(20))]) + LogicalProject(EMPNO=[$0], STREET=[$1.STREET], CITY=[$1.CITY], ZIP=[$1.ZIP], STATE=[$1.STATE], STREET5=[$2.STREET], CITY6=[$2.CITY], ZIP7=[$2.ZIP], STATE8=[$2.STATE]) + LogicalTableScan(table=[[CATALOG, SALES, EMP_ADDRESS]]) +]]> + </Resource> + </TestCase> <TestCase name="testDynamicSchemaUnnest"> <Resource name="sql"> <![CDATA[select t1.c_nationkey, t3.fake_col3