You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2022/09/24 05:13:09 UTC

[calcite] 02/04: [CALCITE-5291] Make lexical policy for BigQuery case-insensitive

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

jhyde pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit abb4cf00254ce2f4d7580b285a6e2226e8d50192
Author: TJ Banghart <tj...@gmail.com>
AuthorDate: Tue Sep 20 03:47:57 2022 +0000

    [CALCITE-5291] Make lexical policy for BigQuery case-insensitive
    
    Close apache/calcite#2914
---
 .../main/java/org/apache/calcite/config/Lex.java   |  2 +-
 .../calcite/sql/validate/LexCaseSensitiveTest.java | 69 +++++++++++++---------
 .../java/org/apache/calcite/test/JdbcTest.java     |  8 +--
 3 files changed, 45 insertions(+), 34 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/config/Lex.java b/core/src/main/java/org/apache/calcite/config/Lex.java
index 172b6b8c5c..e486c1a94e 100644
--- a/core/src/main/java/org/apache/calcite/config/Lex.java
+++ b/core/src/main/java/org/apache/calcite/config/Lex.java
@@ -36,7 +36,7 @@ public enum Lex {
    * a back-tick is escaped using a backslash.
    * Character literals may be enclosed in single or double quotes. */
   BIG_QUERY(Quoting.BACK_TICK_BACKSLASH, Casing.UNCHANGED, Casing.UNCHANGED,
-      true, CharLiteralStyle.BQ_SINGLE, CharLiteralStyle.BQ_DOUBLE),
+      false, CharLiteralStyle.BQ_SINGLE, CharLiteralStyle.BQ_DOUBLE),
 
   /** Lexical policy similar to Oracle. The case of identifiers enclosed in
    * double-quotes is preserved; unquoted identifiers are converted to
diff --git a/core/src/test/java/org/apache/calcite/sql/validate/LexCaseSensitiveTest.java b/core/src/test/java/org/apache/calcite/sql/validate/LexCaseSensitiveTest.java
index 0c9d82aaa7..68937790ae 100644
--- a/core/src/test/java/org/apache/calcite/sql/validate/LexCaseSensitiveTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/validate/LexCaseSensitiveTest.java
@@ -24,7 +24,6 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.parser.SqlParseException;
 import org.apache.calcite.sql.parser.SqlParser;
 import org.apache.calcite.sql.parser.SqlParser.Config;
 import org.apache.calcite.test.CalciteAssert;
@@ -33,7 +32,6 @@ import org.apache.calcite.tools.Frameworks;
 import org.apache.calcite.tools.Planner;
 import org.apache.calcite.tools.Program;
 import org.apache.calcite.tools.Programs;
-import org.apache.calcite.tools.RelConversionException;
 import org.apache.calcite.tools.ValidationException;
 
 import org.junit.jupiter.api.Test;
@@ -64,7 +62,7 @@ class LexCaseSensitiveTest {
   }
 
   private static void runProjectQueryWithLex(Lex lex, String sql)
-      throws SqlParseException, ValidationException, RelConversionException {
+      throws Exception {
     Config javaLex = SqlParser.config().withLex(lex);
     Planner planner = getPlanner(null, javaLex, Programs.ofRules(Programs.RULE_SET));
     SqlNode parse = planner.parse(sql);
@@ -85,8 +83,7 @@ class LexCaseSensitiveTest {
     }
   }
 
-  @Test void testCalciteCaseOracle()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseOracle() throws Exception {
     String sql = "select \"empid\" as EMPID, \"empid\" from\n"
         + " (select \"empid\" from \"emps\" order by \"emps\".\"deptno\")";
     runProjectQueryWithLex(Lex.ORACLE, sql);
@@ -101,50 +98,43 @@ class LexCaseSensitiveTest {
     });
   }
 
-  @Test void testCalciteCaseMySql()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseMySql() throws Exception {
     String sql = "select empid as EMPID, empid from (\n"
         + "  select empid from emps order by `EMPS`.DEPTNO)";
     runProjectQueryWithLex(Lex.MYSQL, sql);
   }
 
-  @Test void testCalciteCaseMySqlNoException()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseMySqlNoException() throws Exception {
     String sql = "select EMPID, empid from\n"
         + " (select empid from emps order by emps.deptno)";
     runProjectQueryWithLex(Lex.MYSQL, sql);
   }
 
-  @Test void testCalciteCaseMySqlAnsi()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseMySqlAnsi() throws Exception {
     String sql = "select empid as EMPID, empid from (\n"
         + "  select empid from emps order by EMPS.DEPTNO)";
     runProjectQueryWithLex(Lex.MYSQL_ANSI, sql);
   }
 
-  @Test void testCalciteCaseMySqlAnsiNoException()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseMySqlAnsiNoException() throws Exception {
     String sql = "select EMPID, empid from\n"
         + " (select empid from emps order by emps.deptno)";
     runProjectQueryWithLex(Lex.MYSQL_ANSI, sql);
   }
 
-  @Test void testCalciteCaseSqlServer()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseSqlServer() throws Exception {
     String sql = "select empid as EMPID, empid from (\n"
         + "  select empid from emps order by EMPS.DEPTNO)";
     runProjectQueryWithLex(Lex.SQL_SERVER, sql);
   }
 
-  @Test void testCalciteCaseSqlServerNoException()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseSqlServerNoException() throws Exception {
     String sql = "select EMPID, empid from\n"
         + " (select empid from emps order by emps.deptno)";
     runProjectQueryWithLex(Lex.SQL_SERVER, sql);
   }
 
-  @Test void testCalciteCaseJava()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseJava() throws Exception {
     String sql = "select empid as EMPID, empid from (\n"
         + "  select empid from emps order by emps.deptno)";
     runProjectQueryWithLex(Lex.JAVA, sql);
@@ -159,8 +149,7 @@ class LexCaseSensitiveTest {
     });
   }
 
-  @Test void testCalciteCaseJoinOracle()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseJoinOracle() throws Exception {
     String sql = "select t.\"empid\" as EMPID, s.\"empid\" from\n"
         + "(select * from \"emps\" where \"emps\".\"deptno\" > 100) t join\n"
         + "(select * from \"emps\" where \"emps\".\"deptno\" < 200) s\n"
@@ -168,35 +157,57 @@ class LexCaseSensitiveTest {
     runProjectQueryWithLex(Lex.ORACLE, sql);
   }
 
-  @Test void testCalciteCaseJoinMySql()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseJoinMySql() throws Exception {
     String sql = "select t.empid as EMPID, s.empid from\n"
         + "(select * from emps where emps.deptno > 100) t join\n"
         + "(select * from emps where emps.deptno < 200) s on t.empid = s.empid";
     runProjectQueryWithLex(Lex.MYSQL, sql);
   }
 
-  @Test void testCalciteCaseJoinMySqlAnsi()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseJoinMySqlAnsi() throws Exception {
     String sql = "select t.empid as EMPID, s.empid from\n"
         + "(select * from emps where emps.deptno > 100) t join\n"
         + "(select * from emps where emps.deptno < 200) s on t.empid = s.empid";
     runProjectQueryWithLex(Lex.MYSQL_ANSI, sql);
   }
 
-  @Test void testCalciteCaseJoinSqlServer()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseJoinSqlServer() throws Exception {
     String sql = "select t.empid as EMPID, s.empid from\n"
         + "(select * from emps where emps.deptno > 100) t join\n"
         + "(select * from emps where emps.deptno < 200) s on t.empid = s.empid";
     runProjectQueryWithLex(Lex.SQL_SERVER, sql);
   }
 
-  @Test void testCalciteCaseJoinJava()
-      throws SqlParseException, ValidationException, RelConversionException {
+  @Test void testCalciteCaseJoinJava() throws Exception {
     String sql = "select t.empid as EMPID, s.empid from\n"
         + "(select * from emps where emps.deptno > 100) t join\n"
         + "(select * from emps where emps.deptno < 200) s on t.empid = s.empid";
     runProjectQueryWithLex(Lex.JAVA, sql);
   }
+
+  @Test void testCalciteCaseBigQuery() throws Exception {
+    String sql = "select empid as EMPID, empid from (\n"
+        + "  select empid from emps order by EMPS.DEPTNO)";
+    runProjectQueryWithLex(Lex.BIG_QUERY, sql);
+  }
+
+  @Test void testCalciteCaseBigQueryNoException() throws Exception {
+    String sql = "select EMPID, empid from\n"
+        + " (select empid from emps order by emps.deptno)";
+    runProjectQueryWithLex(Lex.BIG_QUERY, sql);
+  }
+
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-5291">[CALCITE-5291]
+   * Make BigQuery lexical policy case insensitive</a>.
+   *
+   * <p>In reality, BigQuery treats table names as case-sensitive, column names
+   * and aliases as case-insensitive. Calcite cannot currently support a hybrid
+   * policy, so it treats table names as case-insensitive. */
+  @Test void testCalciteCaseJoinBigQuery() throws Exception {
+    String sql = "select t.empid as EMPID, s.empid from\n"
+        + "(select * from emps where emps.deptno > 100) t join\n"
+        + "(select * from emps where emps.deptno < 200) s on t.empid = s.empid";
+    runProjectQueryWithLex(Lex.BIG_QUERY, sql);
+  }
 }
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 7aa4790955..c7033255c8 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -6842,17 +6842,17 @@ public class JdbcTest {
             DatabaseMetaData metaData = connection.getMetaData();
             assertThat(metaData.getIdentifierQuoteString(), equalTo("`"));
             assertThat(metaData.supportsMixedCaseIdentifiers(),
-                equalTo(true));
-            assertThat(metaData.storesMixedCaseIdentifiers(),
                 equalTo(false));
+            assertThat(metaData.storesMixedCaseIdentifiers(),
+                equalTo(true));
             assertThat(metaData.storesUpperCaseIdentifiers(),
                 equalTo(false));
             assertThat(metaData.storesLowerCaseIdentifiers(),
                 equalTo(false));
             assertThat(metaData.supportsMixedCaseQuotedIdentifiers(),
-                equalTo(true));
-            assertThat(metaData.storesMixedCaseQuotedIdentifiers(),
                 equalTo(false));
+            assertThat(metaData.storesMixedCaseQuotedIdentifiers(),
+                equalTo(true));
             assertThat(metaData.storesUpperCaseIdentifiers(),
                 equalTo(false));
             assertThat(metaData.storesLowerCaseQuotedIdentifiers(),