Repository: calcite
Updated Branches:
  refs/heads/master 7aa9c5d27 -> 349c7dceb


[CALCITE-1378] ArrayIndexOutOfBoundsException in sql-to-rel conversion for 
two-level columns


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/349c7dce
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/349c7dce
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/349c7dce

Branch: refs/heads/master
Commit: 349c7dcebc2c72b51b921ce692c0b16e8628ec03
Parents: 7aa9c5d
Author: maryannxue <maryann....@gmail.com>
Authored: Wed Sep 21 13:13:38 2016 -0700
Committer: maryannxue <maryann....@gmail.com>
Committed: Wed Sep 21 13:13:38 2016 -0700

----------------------------------------------------------------------
 .../calcite/sql/validate/DelegatingScope.java   | 35 ++++++++++-
 .../calcite/test/SqlToRelConverterTest.java     | 28 ++++++++-
 .../apache/calcite/test/SqlValidatorTest.java   |  5 ++
 .../calcite/test/SqlToRelConverterTest.xml      | 61 ++++++++++++++++++++
 4 files changed, 125 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/349c7dce/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java 
b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java
index 491ea1d..a1f63b6 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java
@@ -221,7 +221,7 @@ public abstract class DelegatingScope implements 
SqlValidatorScope {
       SqlValidatorNamespace fromNs = null;
       Path fromPath = null;
       final ResolvedImpl resolved = new ResolvedImpl();
-      final int size = identifier.names.size();
+      int size = identifier.names.size();
       int i = size - 1;
       for (; i > 0; i--) {
         final SqlIdentifier prefix = identifier.getComponent(0, i);
@@ -244,9 +244,38 @@ public abstract class DelegatingScope implements 
SqlValidatorScope {
           final SqlIdentifier prefix1 = identifier.skipLast(1);
           throw validator.newValidationError(prefix1,
               RESOURCE.tableNameNotFound(prefix1.toString()));
-        case 1:
+        case 1: {
+          final Map.Entry<String, SqlValidatorNamespace> entry =
+              map.entrySet().iterator().next();
+          final String tableName = entry.getKey();
+          final SqlValidatorNamespace namespace = entry.getValue();
+          fromNs = namespace;
           fromPath = resolved.emptyPath();
-          fromNs = map.entrySet().iterator().next().getValue();
+
+          // Adding table name is for RecordType column with 
StructKind.PEEK_FIELDS or
+          // StructKind.PEEK_FIELDS only. Access to a field in a RecordType 
column of
+          // other StructKind should always be qualified with table name.
+          final RelDataTypeField field =
+              validator.catalogReader.field(namespace.getRowType(), 
columnName);
+          if (field != null) {
+            switch (field.getType().getStructKind()) {
+            case PEEK_FIELDS:
+            case PEEK_FIELDS_DEFAULT:
+              columnName = field.getName(); // use resolved field name
+              resolve(ImmutableList.of(tableName), false, resolved);
+              if (resolved.count() == 1) {
+                final Resolve resolve = resolved.only();
+                fromNs = resolve.namespace;
+                fromPath = resolve.path;
+                identifier = identifier
+                    .setName(0, columnName)
+                    .add(0, tableName, SqlParserPos.ZERO);
+                ++i;
+                ++size;
+              }
+            }
+          }
+        }
         }
 
         // Throw an error if the table was not found.

http://git-wip-us.apache.org/repos/asf/calcite/blob/349c7dce/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
----------------------------------------------------------------------
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 9953355..c32e751 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -1721,7 +1721,33 @@ public class SqlToRelConverterTest extends 
SqlToRelTestBase {
   }
 
   @Test public void testStructType() {
-    sql("select * from struct.t").convertsTo("${plan}");
+    final String sql = "select k0 from struct.t";
+    sql(sql).ok();
+  }
+
+  @Test public void testStructType2() {
+    final String sql = "select c2 from struct.t";
+    sql(sql).ok();
+  }
+
+  @Test public void testStructType3() {
+    final String sql = "select f1.c2 from struct.t";
+    sql(sql).ok();
+  }
+
+  @Test public void testStructType4() {
+    final String sql = "select f1 from struct.t";
+    sql(sql).ok();
+  }
+
+  @Test public void testStructTypeWithSelectStar() {
+    final String sql = "select * from struct.t";
+    sql(sql).ok();
+  }
+
+  @Test public void testStructTypeWithSelectFieldNameDotStar() {
+    final String sql = "select f1.* from struct.t";
+    sql(sql).ok();
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/calcite/blob/349c7dce/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java 
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index e1afc68..04d0c8b 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -8290,6 +8290,11 @@ public class SqlValidatorTest extends 
SqlValidatorTestCase {
         .type("RecordType(INTEGER C0, INTEGER NOT NULL C2,"
             + " INTEGER NOT NULL A0) NOT NULL");
 
+    // Resolve struct type F1 with wildcard.
+    sql("select t.f1.* from struct.t")
+        .type("RecordType(INTEGER C0, INTEGER NOT NULL C2,"
+            + " INTEGER NOT NULL A0) NOT NULL");
+
     // Fail non-existent column B0.
     sql("select ^b0^ from struct.t")
         .fails("Column 'B0' not found in any table");

http://git-wip-us.apache.org/repos/asf/calcite/blob/349c7dce/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
----------------------------------------------------------------------
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 3c29e67..ee3a62f 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -2471,6 +2471,55 @@ LogicalTableModify(table=[[CATALOG, SALES, EMP]], 
operation=[INSERT], updateColu
     </TestCase>
     <TestCase name="testStructType">
         <Resource name="sql">
+            <![CDATA[select k0 from struct.t]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(K0=[$0])
+  LogicalProject(K0=[$0], C1=[$1], C0=[$2.C0], C13=[$2.C1], C04=[$3.C0], 
C2=[$3.C2], A0=[$3.A0], C3=[$4.C3], A08=[$4.A0])
+    LogicalTableScan(table=[[CATALOG, STRUCT, T]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testStructType2">
+        <Resource name="sql">
+            <![CDATA[select c2 from struct.t]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(C2=[$5])
+  LogicalProject(K0=[$0], C1=[$1], C0=[$2.C0], C13=[$2.C1], C04=[$3.C0], 
C2=[$3.C2], A0=[$3.A0], C3=[$4.C3], A08=[$4.A0])
+    LogicalTableScan(table=[[CATALOG, STRUCT, T]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testStructType3">
+        <Resource name="sql">
+            <![CDATA[select f1.c2 from struct.t]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(C2=[$5])
+  LogicalProject(K0=[$0], C1=[$1], C0=[$2.C0], C13=[$2.C1], C04=[$3.C0], 
C2=[$3.C2], A0=[$3.A0], C3=[$4.C3], A08=[$4.A0])
+    LogicalTableScan(table=[[CATALOG, STRUCT, T]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testStructType4">
+        <Resource name="sql">
+            <![CDATA[select f1 from struct.t]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(F1=[$0])
+  LogicalProject(F1=[$4], F11=[$5], F12=[$6])
+    LogicalProject(K0=[$0], C1=[$1], C0=[$2.C0], C13=[$2.C1], C04=[$3.C0], 
C2=[$3.C2], A0=[$3.A0], C3=[$4.C3], A08=[$4.A0])
+      LogicalTableScan(table=[[CATALOG, STRUCT, T]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testStructTypeWithSelectStar">
+        <Resource name="sql">
             <![CDATA[select * from struct.t]]>
         </Resource>
         <Resource name="plan">
@@ -2482,6 +2531,18 @@ LogicalProject(K0=[$0], C1=[$1], F0=[$2], F1=[$3], 
F2=[$4])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testStructTypeWithSelectFieldNameDotStar">
+        <Resource name="sql">
+            <![CDATA[select f1.* from struct.t]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(C0=[$4], C2=[$5], A0=[$6])
+  LogicalProject(K0=[$0], C1=[$1], C0=[$2.C0], C13=[$2.C1], C04=[$3.C0], 
C2=[$3.C2], A0=[$3.A0], C3=[$4.C3], A08=[$4.A0])
+    LogicalTableScan(table=[[CATALOG, STRUCT, T]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testWindowAggWithGroupBy">
         <Resource name="sql">
             <![CDATA[select min(deptno), rank() over (order by empno),

Reply via email to