diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java index fe902759db1..fcd3b46641f 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java @@ -375,6 +375,7 @@ default boolean isColonFieldAccessAllowed() { * fields of T if T is a STRUCT type. * *
Among the built-in conformance levels, true in
+ * {@link SqlConformanceEnum#BIG_QUERY},
* {@link SqlConformanceEnum#PRESTO};
* false otherwise.
*/
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java
index 047f05981a1..f0f258171b3 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java
@@ -435,6 +435,7 @@ public enum SqlConformanceEnum implements SqlConformance {
@Override public boolean allowAliasUnnestItems() {
switch (this) {
+ case BIG_QUERY:
case PRESTO:
return true;
default:
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 ebad0e9450a..1fe413761df 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -1939,6 +1939,32 @@ public static void checkActualAndReferenceFiles() {
sql(sql).withConformance(SqlConformanceEnum.PRESTO).ok();
}
+ /**
+ * Test case for
+ * [CALCITE-7547]
+ * BIG_QUERY conformance should allow field access on
+ * UNNEST(array_of_struct) AS alias.
+ */
+ @Test void testAliasUnnestArrayPlanWithSingleColumnBigQuery() {
+ final String sql = "select d.deptno, employee.empno\n"
+ + "from dept_nested_expanded as d,\n"
+ + " UNNEST(d.employees) as t(employee)";
+ sql(sql).withConformance(SqlConformanceEnum.BIG_QUERY).ok();
+ }
+
+ /**
+ * Test case for
+ * [CALCITE-7547]
+ * BIG_QUERY conformance should allow field access on
+ * UNNEST(array_of_struct) AS alias.
+ */
+ @Test void testAliasUnnestArrayPlanWithDoubleColumnBigQuery() {
+ final String sql = "select d.deptno, e, k.empno\n"
+ + "from dept_nested_expanded as d CROSS JOIN\n"
+ + " UNNEST(d.admins, d.employees) as t(e, k)";
+ sql(sql).withConformance(SqlConformanceEnum.BIG_QUERY).ok();
+ }
+
@Test void testArrayOfRecord() {
sql("select employees[1].detail.skills[2+3].desc from dept_nested").ok();
}
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 5198762c106..9a080efbf86 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -8816,6 +8816,37 @@ void testGroupExpressionEquivalenceParams() {
+ "\\('EMPNO', 'ENAME', 'DETAIL'\\), whereas alias list has 1 columns");
}
+ /**
+ * Test case for
+ * [CALCITE-7547]
+ * BIG_QUERY conformance should allow field access on
+ * UNNEST(array_of_struct) AS alias.
+ */
+ @Test void testAliasUnnestMultipleArraysBigQuery() {
+ // for accessing a field in STRUCT type unnested from array
+ sql("select e.ENAME\n"
+ + "from dept_nested_expanded as d CROSS JOIN\n"
+ + " UNNEST(d.employees) as t(e)")
+ .withConformance(SqlConformanceEnum.BIG_QUERY).columnType("VARCHAR(10) NOT NULL");
+
+ // for unnesting multiple arrays at the same time
+ sql("select d.deptno, e, k.empno, l.\"unit\", l.\"X\" * l.\"Y\"\n"
+ + "from dept_nested_expanded as d CROSS JOIN\n"
+ + " UNNEST(d.admins, d.employees, d.offices) as t(e, k, l)")
+ .withConformance(SqlConformanceEnum.BIG_QUERY).ok();
+
+ // Make sure validation fails properly given illegal select items
+ sql("select d.deptno, ^e^.some_column, k.empno\n"
+ + "from dept_nested_expanded as d CROSS JOIN\n"
+ + " UNNEST(d.admins, d.employees) as t(e, k)")
+ .withConformance(SqlConformanceEnum.BIG_QUERY)
+ .fails("Table 'E' not found");
+ sql("select d.deptno, e.detail, ^unknown^.detail\n"
+ + "from dept_nested_expanded as d CROSS JOIN\n"
+ + " UNNEST(d.employees) as t(e)")
+ .withConformance(SqlConformanceEnum.BIG_QUERY).fails("Incompatible types");
+ }
+
@Test void testUnnestArray() {
sql("select*from unnest(array[1])")
.columnType("INTEGER NOT NULL");
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 56f169629ae..5ee7180efa7 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -341,6 +341,23 @@ LogicalProject(DEPTNO=[$0], E=[$5], EMPNO=[$6.EMPNO])