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";