You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by hy...@apache.org on 2019/04/12 23:07:54 UTC

[calcite] branch master updated: [CALCITE-2977] Exception is not thrown when there are ambiguous field in select list

This is an automated email from the ASF dual-hosted git repository.

hyuan 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 38e3c30  [CALCITE-2977] Exception is not thrown when there are ambiguous field in select list
38e3c30 is described below

commit 38e3c3015b661f8f9dc61d8d0ef4be6186a4bc7a
Author: pengzhiwei <pe...@icloud.com>
AuthorDate: Thu Apr 4 16:32:21 2019 +0800

    [CALCITE-2977] Exception is not thrown when there are ambiguous field in select list
    
    Close #1147
---
 .../calcite/sql/validate/DelegatingScope.java      | 24 +++++++----
 .../apache/calcite/test/SqlToRelConverterTest.java |  2 +-
 .../org/apache/calcite/test/SqlValidatorTest.java  | 47 +++++++++++++++-------
 3 files changed, 50 insertions(+), 23 deletions(-)

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 cf5d9d2..ee9e112 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
@@ -273,8 +273,8 @@ public abstract class DelegatingScope implements SqlValidatorScope {
       final RelDataTypeField field =
           nameMatcher.field(namespace.getRowType(), columnName);
       if (field != null) {
-        if (hasAmbiguousUnresolvedStar(namespace.getRowType(), field,
-            columnName)) {
+        if (hasAmbiguousField(namespace.getRowType(), field,
+            columnName, nameMatcher)) {
           throw validator.newValidationError(identifier,
               RESOURCE.columnAmbiguous(columnName));
         }
@@ -492,7 +492,7 @@ public abstract class DelegatingScope implements SqlValidatorScope {
           if (!fieldName.equals(name)) {
             identifier = identifier.setName(k, fieldName);
           }
-          if (hasAmbiguousUnresolvedStar(step.rowType, field0, name)) {
+          if (hasAmbiguousField(step.rowType, field0, name, nameMatcher)) {
             throw validator.newValidationError(identifier,
                 RESOURCE.columnAmbiguous(name));
           }
@@ -542,10 +542,10 @@ public abstract class DelegatingScope implements SqlValidatorScope {
     return parent.getOrderList();
   }
 
-  /** Returns whether {@code rowType} contains more than one star column.
-   * Having more than one star columns implies ambiguous column. */
-  private boolean hasAmbiguousUnresolvedStar(RelDataType rowType,
-      RelDataTypeField field, String columnName) {
+  /** Returns whether {@code rowType} contains more than one star column or
+   * fields with the same name, which implies ambiguous column. */
+  private boolean hasAmbiguousField(RelDataType rowType,
+      RelDataTypeField field, String columnName, SqlNameMatcher nameMatcher) {
     if (field.isDynamicStar()
         && !DynamicRecordType.isDynamicStarColName(columnName)) {
       int count = 0;
@@ -556,6 +556,16 @@ public abstract class DelegatingScope implements SqlValidatorScope {
           }
         }
       }
+    } else { // check if there are fields with the same name
+      int count = 0;
+      for (RelDataTypeField f : rowType.getFieldList()) {
+        if (Util.matches(nameMatcher.isCaseSensitive(), f.getName(), columnName)) {
+          count++;
+        }
+      }
+      if (count > 1) {
+        return true;
+      }
     }
     return false;
   }
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 d4e2c9b..35b8841 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -596,7 +596,7 @@ public class SqlToRelConverterTest extends SqlToRelTestBase {
    * and rename the second column to "e0". */
   @Test public void testDuplicateColumnsInSubQuery() {
     String sql = "select \"e\" from (\n"
-        + "select empno as \"e\", deptno as d, 1 as \"e\" from EMP)";
+        + "select empno as \"e\", deptno as d, 1 as \"e0\" from EMP)";
     sql(sql).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 b12bbca..4238a9c 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -5743,7 +5743,7 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
     // make sal occur more than once on rhs, it is ignored and therefore
     // there is no error about incompatible types
     sql("select * from emp natural join\n"
-        + " (select deptno, name as sal, 'foo' as sal from dept)").ok();
+        + " (select deptno, name as sal, 'foo' as sal2 from dept)").ok();
   }
 
   @Test public void testJoinUsingIncompatibleDatatype() {
@@ -6390,7 +6390,7 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
 
     // empno is not an alias in the first select in the union
     checkFails(
-        "select deptno, deptno from dept "
+        "select deptno, deptno as no2 from dept "
             + "union all "
             + "select empno, sal from emp "
             + "order by deptno asc, ^empno^",
@@ -7934,6 +7934,21 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
         .fails("SELECT must have a FROM clause");
   }
 
+  @Test public void testSelectAmbiguousField() {
+    tester = tester.withCaseSensitive(false)
+        .withUnquotedCasing(Casing.UNCHANGED);
+    sql("select ^t0^ from (select 1 as t0, 2 as T0 from dept)")
+        .fails("Column 't0' is ambiguous");
+    sql("select ^t0^ from (select 1 as t0, 2 as t0,3 as t1,4 as t1, 5 as t2 from dept)")
+        .fails("Column 't0' is ambiguous");
+    // t0 is not referenced,so this case is allowed
+    sql("select 1 as t0, 2 as t0 from dept").ok();
+
+    tester = tester.withCaseSensitive(true)
+        .withUnquotedCasing(Casing.UNCHANGED);
+    sql("select t0 from (select 1 as t0, 2 as T0 from DEPT)").ok();
+  }
+
   @Test public void testTableExtend() {
     checkResultType("select * from dept extend (x int not null)",
         "RecordType(INTEGER NOT NULL DEPTNO, VARCHAR(10) NOT NULL NAME, INTEGER NOT NULL X) NOT NULL");
@@ -8576,19 +8591,20 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
   @Test public void testCaseSensitiveBuiltinFunction() {
     final SqlTester tester1 = tester
         .withCaseSensitive(true)
+        .withUnquotedCasing(Casing.UNCHANGED)
         .withQuoting(Quoting.BRACKET);
     tester1.withOperatorTable(SqlStdOperatorTable.instance());
 
-    tester1.checkQuery("select sum(empno) from EMP group by ename, empno");
-    tester1.checkQuery("select [sum](empno) from EMP group by ename, empno");
-    tester1.checkQuery("select [SUM](empno) from EMP group by ename, empno");
-    tester1.checkQuery("select SUM(empno) from EMP group by ename, empno");
-    tester1.checkQuery("select Sum(empno) from EMP group by ename, empno");
-    tester1.checkQuery("select count(empno) from EMP group by ename, empno");
-    tester1.checkQuery("select [count](empno) from EMP group by ename, empno");
-    tester1.checkQuery("select [COUNT](empno) from EMP group by ename, empno");
-    tester1.checkQuery("select COUNT(empno) from EMP group by ename, empno");
-    tester1.checkQuery("select Count(empno) from EMP group by ename, empno");
+    tester1.checkQuery("select sum(EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select [sum](EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select [SUM](EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select SUM(EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select Sum(EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select count(EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select [count](EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select [COUNT](EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select COUNT(EMPNO) from EMP group by ENAME, EMPNO");
+    tester1.checkQuery("select Count(EMPNO) from EMP group by ENAME, EMPNO");
   }
 
   /** Test case for
@@ -9022,13 +9038,14 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
         .withQuoting(Quoting.BRACKET);
     final SqlTester sensitive = tester
         .withCaseSensitive(true)
+        .withUnquotedCasing(Casing.UNCHANGED)
         .withQuoting(Quoting.BRACKET);
     String sql = "select [e] from (\n"
-        + "select empno as [e], deptno as d, 1 as [e] from EMP)";
+        + "select EMPNO as [e], DEPTNO as d, 1 as [e2] from EMP)";
     sensitive.checkQuery(sql);
     insensitive.checkQuery(sql);
-    String sql1 = "select e from (\n"
-        + "select empno as [e], deptno as d, 1 as [E] from EMP)";
+    String sql1 = "select e2 from (\n"
+        + "select EMPNO as [e2], DEPTNO as d, 1 as [E] from EMP)";
     insensitive.checkQuery(sql1);
     sensitive.checkQuery(sql1);
   }