You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jc...@apache.org on 2020/02/26 01:48:24 UTC

[calcite] branch master updated: [CALCITE-3734] MySQL JDBC rewrite is producing queries with CHAR with range beyond 255 (Vineet Garg)

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

jcamacho 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 e427180  [CALCITE-3734] MySQL JDBC rewrite is producing queries with CHAR with range beyond 255 (Vineet Garg)
e427180 is described below

commit e427180b6a55445fe246b00c60259a95f96bdbf2
Author: Vineet Garg <vg...@apache.org>
AuthorDate: Tue Feb 25 13:07:37 2020 -0800

    [CALCITE-3734] MySQL JDBC rewrite is producing queries with CHAR with range beyond 255 (Vineet Garg)
    
    Close apache/calcite#1828
---
 .../apache/calcite/sql/SqlDialectFactoryImpl.java  |  6 +++--
 .../calcite/sql/dialect/MysqlSqlDialect.java       | 27 +++++++++++++++++++++-
 .../calcite/sql/dialect/PostgresqlSqlDialect.java  |  2 +-
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 16 +++++++++++++
 4 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java
index 51c6672..6d265f1 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java
@@ -122,7 +122,8 @@ public class SqlDialectFactoryImpl implements SqlDialectFactory {
     case "MYSQL (INFOBRIGHT)":
       return new InfobrightSqlDialect(c);
     case "MYSQL":
-      return new MysqlSqlDialect(c);
+      return new MysqlSqlDialect(
+          c.withDataTypeSystem(MysqlSqlDialect.MYSQL_TYPE_SYSTEM));
     case "REDSHIFT":
       return new RedshiftSqlDialect(c);
     case "SNOWFLAKE":
@@ -144,7 +145,8 @@ public class SqlDialectFactoryImpl implements SqlDialectFactory {
     } else if (databaseProductName.startsWith("HP Neoview")) {
       return new NeoviewSqlDialect(c);
     } else if (upperProductName.contains("POSTGRE")) {
-      return new PostgresqlSqlDialect(c);
+      return new PostgresqlSqlDialect(
+          c.withDataTypeSystem(PostgresqlSqlDialect.POSTGRESQL_TYPE_SYSTEM));
     } else if (upperProductName.contains("SQL SERVER")) {
       return new MssqlSqlDialect(c);
     } else if (upperProductName.contains("SYBASE")) {
diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java
index db7baf7..eca08f2 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java
@@ -22,6 +22,7 @@ import org.apache.calcite.avatica.util.TimeUnitRange;
 import org.apache.calcite.config.NullCollation;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
 import org.apache.calcite.sql.SqlAlienSystemTypeNameSpec;
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlBasicTypeNameSpec;
@@ -49,9 +50,28 @@ import org.apache.calcite.sql.type.SqlTypeName;
  * A <code>SqlDialect</code> implementation for the MySQL database.
  */
 public class MysqlSqlDialect extends SqlDialect {
+
+  /** MySQL type system. */
+  public static final RelDataTypeSystem MYSQL_TYPE_SYSTEM =
+      new RelDataTypeSystemImpl() {
+        @Override public int getMaxPrecision(SqlTypeName typeName) {
+          switch (typeName) {
+          case CHAR:
+            return 255;
+          case VARCHAR:
+            return 65535;
+          case TIMESTAMP:
+            return 6;
+          default:
+            return super.getMaxPrecision(typeName);
+          }
+        }
+      };
+
   public static final SqlDialect.Context DEFAULT_CONTEXT = SqlDialect.EMPTY_CONTEXT
       .withDatabaseProduct(SqlDialect.DatabaseProduct.MYSQL)
       .withIdentifierQuoteString("`")
+      .withDataTypeSystem(MYSQL_TYPE_SYSTEM)
       .withUnquotedCasing(Casing.UNCHANGED)
       .withNullCollation(NullCollation.LOW);
 
@@ -127,8 +147,13 @@ public class MysqlSqlDialect extends SqlDialect {
     switch (type.getSqlTypeName()) {
     case VARCHAR:
       // MySQL doesn't have a VARCHAR type, only CHAR.
+      int vcMaxPrecision = this.getTypeSystem().getMaxPrecision(SqlTypeName.CHAR);
+      int precision = type.getPrecision();
+      if (vcMaxPrecision > 0 && precision > vcMaxPrecision) {
+        precision = vcMaxPrecision;
+      }
       return new SqlDataTypeSpec(
-          new SqlBasicTypeNameSpec(SqlTypeName.CHAR, type.getPrecision(), SqlParserPos.ZERO),
+          new SqlBasicTypeNameSpec(SqlTypeName.CHAR, precision, SqlParserPos.ZERO),
           SqlParserPos.ZERO);
     case INTEGER:
     case BIGINT:
diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java
index c12f8c4..fa18abd 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java
@@ -37,7 +37,7 @@ import org.apache.calcite.sql.type.SqlTypeName;
  */
 public class PostgresqlSqlDialect extends SqlDialect {
   /** PostgreSQL type system. */
-  private static final RelDataTypeSystem POSTGRESQL_TYPE_SYSTEM =
+  public static final RelDataTypeSystem POSTGRESQL_TYPE_SYSTEM =
       new RelDataTypeSystemImpl() {
         @Override public int getMaxPrecision(SqlTypeName typeName) {
           switch (typeName) {
diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 96fd91b..de0f2b7 100644
--- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -1712,6 +1712,22 @@ public class RelToSqlConverterTest {
     sql(query).dialect(MysqlSqlDialect.DEFAULT).ok(expected);
   }
 
+  @Test public void testMySqlCastToVarcharWithLessThanMaxPrecision() {
+    final String query = "select cast(\"product_id\" as varchar(50)), \"product_id\" "
+        + "from \"product\" ";
+    final String expected = "SELECT CAST(`product_id` AS CHAR(50)), `product_id`\n"
+        + "FROM `foodmart`.`product`";
+    sql(query).withMysql().ok(expected);
+  }
+
+  @Test public void testMySqlCastToVarcharWithGreaterThanMaxPrecision() {
+    final String query = "select cast(\"product_id\" as varchar(500)), \"product_id\" "
+        + "from \"product\" ";
+    final String expected = "SELECT CAST(`product_id` AS CHAR(255)), `product_id`\n"
+        + "FROM `foodmart`.`product`";
+    sql(query).withMysql().ok(expected);
+  }
+
   @Test public void testMySqlWithHighNullsSelectWithOrderByAscNullsLastAndNoEmulation() {
     final String query = "select \"product_id\" from \"product\"\n"
         + "order by \"product_id\" nulls last";