From 1f630e4a5d310c3cdc81745dc26e53725dd61fc9 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Mon, 19 Dec 2022 19:10:29 +0100 Subject: [PATCH] HHH-15805 Subquery with where condition on a column with columnDefinition results in wrong SQL grammer --- .../MariaDBLegacySqlAstTranslator.java | 13 +++++ .../dialect/MySQLLegacySqlAstTranslator.java | 13 +++++ .../dialect/MariaDBSqlAstTranslator.java | 13 +++++ .../dialect/MySQLSqlAstTranslator.java | 50 +++++++++++++++++++ .../dialect/TiDBSqlAstTranslator.java | 12 +++++ .../sql/ast/spi/AbstractSqlAstTranslator.java | 3 ++ 6 files changed, 104 insertions(+) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java index c9cf647429..ccc1c885f1 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java @@ -6,10 +6,12 @@ */ package org.hibernate.community.dialect; +import org.hibernate.dialect.MySQLSqlAstTranslator; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator; import org.hibernate.sql.ast.tree.Statement; +import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Literal; import org.hibernate.sql.ast.tree.expression.Summarization; @@ -227,4 +229,15 @@ public class MariaDBLegacySqlAstTranslator extends Abst private boolean supportsWindowFunctions() { return dialect.getVersion().isSameOrAfter( 10, 2 ); } + + @Override + public void visitCastTarget(CastTarget castTarget) { + String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, dialect ); + if ( sqlType != null ) { + appendSql( sqlType ); + } + else { + super.visitCastTarget( castTarget ); + } + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java index 5f6e88c5a9..61b6e7d21d 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java @@ -7,10 +7,12 @@ package org.hibernate.community.dialect; import org.hibernate.dialect.MySQLDialect; +import org.hibernate.dialect.MySQLSqlAstTranslator; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator; import org.hibernate.sql.ast.tree.Statement; +import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Literal; import org.hibernate.sql.ast.tree.expression.Summarization; @@ -240,4 +242,15 @@ public class MySQLLegacySqlAstTranslator extends Abstra public MySQLDialect getDialect() { return (MySQLDialect) super.getDialect(); } + + @Override + public void visitCastTarget(CastTarget castTarget) { + String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, getDialect() ); + if ( sqlType != null ) { + appendSql( sqlType ); + } + else { + super.visitCastTarget( castTarget ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java index aaffe44894..8f75a89032 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java @@ -10,6 +10,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator; import org.hibernate.sql.ast.tree.Statement; +import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Literal; import org.hibernate.sql.ast.tree.expression.Summarization; @@ -222,4 +223,16 @@ public class MariaDBSqlAstTranslator extends AbstractSq private boolean supportsWindowFunctions() { return true; } + + @Override + public void visitCastTarget(CastTarget castTarget) { + String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, dialect ); + if ( sqlType != null ) { + appendSql( sqlType ); + } + else { + super.visitCastTarget( castTarget ); + } + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java index 82cbadc4fe..0f19d8c62e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java @@ -6,10 +6,14 @@ */ package org.hibernate.dialect; +import java.util.Locale; + +import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator; import org.hibernate.sql.ast.tree.Statement; +import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Literal; import org.hibernate.sql.ast.tree.expression.Summarization; @@ -33,6 +37,41 @@ public class MySQLSqlAstTranslator extends AbstractSqlA super( sessionFactory, statement ); } + public static String getSqlType(CastTarget castTarget, Dialect dialect) { + final String sqlType = castTarget.getSqlType(); + + if ( sqlType != null ) { + int parenthesesIndex = sqlType.indexOf( '(' ); + final String baseName = parenthesesIndex == -1 ? sqlType : sqlType.substring( 0, parenthesesIndex ); + switch ( baseName.toLowerCase( Locale.ROOT ) ) { + case "bit": + return "unsigned"; + case "tinyint": + case "smallint": + case "integer": + case "bigint": + return "signed"; + case "float": + case "real": + case "double precision": + final int precision = castTarget.getPrecision() == null ? + dialect.getDefaultDecimalPrecision() : + castTarget.getPrecision(); + final int scale = castTarget.getScale() == null ? Size.DEFAULT_SCALE : castTarget.getScale(); + return "decimal(" + precision + "," + scale + ")"; + case "char": + case "varchar": + case "nchar": + case "nvarchar": + return "char"; + case "binary": + case "varbinary": + return "binary"; + } + } + return sqlType; + } + @Override protected void renderExpressionAsClauseItem(Expression expression) { expression.accept( this ); @@ -239,4 +278,15 @@ public class MySQLSqlAstTranslator extends AbstractSqlA public MySQLDialect getDialect() { return (MySQLDialect) super.getDialect(); } + + @Override + public void visitCastTarget(CastTarget castTarget) { + String sqlType = getSqlType( castTarget, getDialect() ); + if ( sqlType != null ) { + appendSql( sqlType ); + } + else { + super.visitCastTarget( castTarget ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java index 9f859a55dd..27f0fc938b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java @@ -11,6 +11,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator; import org.hibernate.sql.ast.tree.Statement; +import org.hibernate.sql.ast.tree.expression.CastTarget; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Literal; import org.hibernate.sql.ast.tree.expression.Summarization; @@ -189,4 +190,15 @@ public class TiDBSqlAstTranslator extends AbstractSqlAs public TiDBDialect getDialect() { return this.dialect; } + + @Override + public void visitCastTarget(CastTarget castTarget) { + String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, dialect ); + if ( sqlType != null ) { + appendSql( sqlType ); + } + else { + super.visitCastTarget( castTarget ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index f29fa1d4f7..a9b6f3626f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -943,8 +943,10 @@ public abstract class AbstractSqlAstTranslator implemen @Override public void visitSelectStatement(SelectStatement statement) { + final SqlAstNodeRenderingMode oldParameterRenderingMode = getParameterRenderingMode(); try { statementStack.push( statement ); + parameterRenderingMode = SqlAstNodeRenderingMode.DEFAULT; final boolean needsParenthesis = !statement.getQueryPart().isRoot(); if ( needsParenthesis ) { appendSql( OPEN_PARENTHESIS ); @@ -956,6 +958,7 @@ public abstract class AbstractSqlAstTranslator implemen } } finally { + parameterRenderingMode = oldParameterRenderingMode; statementStack.pop(); } }