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),