You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by za...@apache.org on 2019/03/29 22:57:47 UTC

[calcite] branch master updated: [CALCITE-2900] RelStructuredTypeFlattener generates wrong types on nested columns (Will Yu)

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 <wm...@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