From fc7bdce2c8a24d291831c0ff3c77d93226bd5af4 Mon Sep 17 00:00:00 2001 From: Marco Belladelli Date: Thu, 15 Dec 2022 11:33:49 +0100 Subject: [PATCH] HHH-15736 Add escape logic to cockroach and fix mysql 5.7 --- .../CockroachLegacySqlAstTranslator.java | 26 +++++++++ .../dialect/MySQLLegacySqlAstTranslator.java | 53 +++++++++++++++++-- .../dialect/CockroachSqlAstTranslator.java | 26 +++++++++ .../dialect/MySQLSqlAstTranslator.java | 53 +++++++++++++++++-- 4 files changed, 148 insertions(+), 10 deletions(-) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacySqlAstTranslator.java index 334b4c5a0b..adee88464b 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacySqlAstTranslator.java @@ -15,6 +15,7 @@ import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Literal; import org.hibernate.sql.ast.tree.expression.Summarization; import org.hibernate.sql.ast.tree.predicate.BooleanExpressionPredicate; +import org.hibernate.sql.ast.tree.predicate.LikePredicate; import org.hibernate.sql.ast.tree.select.QueryGroup; import org.hibernate.sql.ast.tree.select.QueryPart; import org.hibernate.sql.ast.tree.select.QuerySpec; @@ -153,6 +154,31 @@ public class CockroachLegacySqlAstTranslator extends Ab } } + @Override + public void visitLikePredicate(LikePredicate likePredicate) { + // Custom implementation because CockroachDB uses backslash as default escape character + likePredicate.getMatchExpression().accept( this ); + if ( likePredicate.isNegated() ) { + appendSql( " not" ); + } + if ( likePredicate.isCaseSensitive() ) { + appendSql( " like " ); + } + else { + appendSql( WHITESPACE ); + appendSql( getDialect().getCaseInsensitiveLike() ); + appendSql( WHITESPACE ); + } + likePredicate.getPattern().accept( this ); + if ( likePredicate.getEscapeCharacter() != null ) { + appendSql( " escape " ); + likePredicate.getEscapeCharacter().accept( this ); + } + else { + appendSql( " escape ''" ); + } + } + @Override protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() { return false; 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 5f2cd6c313..bb79632546 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 @@ -143,12 +143,50 @@ public class MySQLLegacySqlAstTranslator extends Abstra @Override public void visitLikePredicate(LikePredicate likePredicate) { - super.visitLikePredicate( likePredicate ); // Custom implementation because MySQL uses backslash as the default escape character - // We can override this by specifying an empty escape character - // See https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like - if ( !( (MySQLLegacyDialect) getDialect() ).isNoBackslashEscapesEnabled() && likePredicate.getEscapeCharacter() == null ) { - appendSql( " escape ''" ); + if ( getDialect().getVersion().isSameOrAfter( 8 ) ) { + // From version 8 we can override this by specifying an empty escape character + // See https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like + super.visitLikePredicate( likePredicate ); + if ( !getDialect().isNoBackslashEscapesEnabled() && likePredicate.getEscapeCharacter() == null ) { + appendSql( " escape ''" ); + } + } + else { + if ( likePredicate.isCaseSensitive() ) { + likePredicate.getMatchExpression().accept( this ); + if ( likePredicate.isNegated() ) { + appendSql( " not" ); + } + appendSql( " like " ); + renderBackslashEscapedLikePattern( + likePredicate.getPattern(), + likePredicate.getEscapeCharacter(), + getDialect().isNoBackslashEscapesEnabled() + ); + } + else { + appendSql( getDialect().getLowercaseFunction() ); + appendSql( OPEN_PARENTHESIS ); + likePredicate.getMatchExpression().accept( this ); + appendSql( CLOSE_PARENTHESIS ); + if ( likePredicate.isNegated() ) { + appendSql( " not" ); + } + appendSql( " like " ); + appendSql( getDialect().getLowercaseFunction() ); + appendSql( OPEN_PARENTHESIS ); + renderBackslashEscapedLikePattern( + likePredicate.getPattern(), + likePredicate.getEscapeCharacter(), + getDialect().isNoBackslashEscapesEnabled() + ); + appendSql( CLOSE_PARENTHESIS ); + } + if ( likePredicate.getEscapeCharacter() != null ) { + appendSql( " escape " ); + likePredicate.getEscapeCharacter().accept( this ); + } } } @@ -197,4 +235,9 @@ public class MySQLLegacySqlAstTranslator extends Abstra protected String getFromDual() { return " from dual"; } + + @Override + public MySQLDialect getDialect() { + return (MySQLDialect) super.getDialect(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachSqlAstTranslator.java index 5ffef6d983..c02756f6bf 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachSqlAstTranslator.java @@ -15,6 +15,7 @@ import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Literal; import org.hibernate.sql.ast.tree.expression.Summarization; import org.hibernate.sql.ast.tree.predicate.BooleanExpressionPredicate; +import org.hibernate.sql.ast.tree.predicate.LikePredicate; import org.hibernate.sql.ast.tree.select.QueryGroup; import org.hibernate.sql.ast.tree.select.QueryPart; import org.hibernate.sql.ast.tree.select.QuerySpec; @@ -125,6 +126,31 @@ public class CockroachSqlAstTranslator extends Abstract } } + @Override + public void visitLikePredicate(LikePredicate likePredicate) { + // Custom implementation because CockroachDB uses backslash as default escape character + likePredicate.getMatchExpression().accept( this ); + if ( likePredicate.isNegated() ) { + appendSql( " not" ); + } + if ( likePredicate.isCaseSensitive() ) { + appendSql( " like " ); + } + else { + appendSql( WHITESPACE ); + appendSql( getDialect().getCaseInsensitiveLike() ); + appendSql( WHITESPACE ); + } + likePredicate.getPattern().accept( this ); + if ( likePredicate.getEscapeCharacter() != null ) { + appendSql( " escape " ); + likePredicate.getEscapeCharacter().accept( this ); + } + else { + appendSql( " escape ''" ); + } + } + @Override protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() { return false; 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 cb2ebc9392..411d62ba23 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java @@ -142,12 +142,50 @@ public class MySQLSqlAstTranslator extends AbstractSqlA @Override public void visitLikePredicate(LikePredicate likePredicate) { - super.visitLikePredicate( likePredicate ); // Custom implementation because MySQL uses backslash as the default escape character - // We can override this by specifying an empty escape character - // See https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like - if ( !( (MySQLDialect) getDialect() ).isNoBackslashEscapesEnabled() && likePredicate.getEscapeCharacter() == null ) { - appendSql( " escape ''" ); + if ( getDialect().getVersion().isSameOrAfter( 8 ) ) { + // From version 8 we can override this by specifying an empty escape character + // See https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like + super.visitLikePredicate( likePredicate ); + if ( !getDialect().isNoBackslashEscapesEnabled() && likePredicate.getEscapeCharacter() == null ) { + appendSql( " escape ''" ); + } + } + else { + if ( likePredicate.isCaseSensitive() ) { + likePredicate.getMatchExpression().accept( this ); + if ( likePredicate.isNegated() ) { + appendSql( " not" ); + } + appendSql( " like " ); + renderBackslashEscapedLikePattern( + likePredicate.getPattern(), + likePredicate.getEscapeCharacter(), + getDialect().isNoBackslashEscapesEnabled() + ); + } + else { + appendSql( getDialect().getLowercaseFunction() ); + appendSql( OPEN_PARENTHESIS ); + likePredicate.getMatchExpression().accept( this ); + appendSql( CLOSE_PARENTHESIS ); + if ( likePredicate.isNegated() ) { + appendSql( " not" ); + } + appendSql( " like " ); + appendSql( getDialect().getLowercaseFunction() ); + appendSql( OPEN_PARENTHESIS ); + renderBackslashEscapedLikePattern( + likePredicate.getPattern(), + likePredicate.getEscapeCharacter(), + getDialect().isNoBackslashEscapesEnabled() + ); + appendSql( CLOSE_PARENTHESIS ); + } + if ( likePredicate.getEscapeCharacter() != null ) { + appendSql( " escape " ); + likePredicate.getEscapeCharacter().accept( this ); + } } } @@ -196,4 +234,9 @@ public class MySQLSqlAstTranslator extends AbstractSqlA protected String getFromDual() { return " from dual"; } + + @Override + public MySQLDialect getDialect() { + return (MySQLDialect) super.getDialect(); + } }