From 2f4723501857506c43833664f784d7f98df0ed0b Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Fri, 9 Feb 2018 21:28:39 +1300 Subject: [PATCH] #1255 - Regression on raw LIKE expression with slashes on Postgres --- .../config/dbplatform/DatabasePlatform.java | 30 ++++++++++++++----- .../config/dbplatform/db2/DB2Platform.java | 5 +--- .../dbplatform/mysql/MySqlPlatform.java | 4 +-- .../dbplatform/oracle/OraclePlatform.java | 4 +-- .../sqlserver/SqlServerPlatform.java | 5 ++-- .../api/SpiExpressionRequest.java | 2 +- .../server/core/OrmQueryRequest.java | 4 +-- .../server/core/SpiOrmQueryRequest.java | 2 +- .../expression/DefaultExpressionRequest.java | 4 +-- .../server/expression/LikeExpression.java | 2 +- .../expression/TDSpiExpressionRequest.java | 2 +- 11 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java index e2e1bd5ed..3b6073c60 100644 --- a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java @@ -140,9 +140,25 @@ public class DatabasePlatform { private static final char BACK_TICK = '`'; /** - * The like clause. Can be overridden to disable default escape character. + * The non-escaped like clause (to stop slash being escaped on some platforms). + * Used for the 'raw like' expression but not for startsWith, endsWith and contains expressions. */ - protected String likeClause = "like ?"; + protected String likeClauseRaw = "like ? escape''"; + + /** + * Escaped like clause for startsWith, endsWith and contains. + */ + protected String likeClauseEscaped = "like ? escape'|'"; + + /** + * Escape character used for startsWith, endsWith and contains. + */ + protected char likeEscapeChar = '|'; + + /** + * Characters escaped for startsWith, endsWith and contains. + */ + protected char[] likeSpecialCharacters = { '%', '_', '|' }; protected DbEncrypt dbEncrypt; @@ -177,8 +193,6 @@ public class DatabasePlatform { protected SqlExceptionTranslator exceptionTranslator = new SqlCodeTranslator(); - protected char[] specialLikeCharacters = { '%', '_', '\\' }; - /** * Instantiates a new database platform. */ @@ -583,8 +597,8 @@ public class DatabasePlatform { *

* This may include an escape clause to disable a default escape character. */ - public String getLikeClause() { - return likeClause; + public String getLikeClause(boolean rawLikeExpression) { + return rawLikeExpression ? likeClauseRaw : likeClauseEscaped; } /** @@ -627,7 +641,7 @@ public class DatabasePlatform { for (int i = 0; i < value.length(); i++) { char ch = value.charAt(i); boolean escaped = false; - for (char escapeChar: specialLikeCharacters) { + for (char escapeChar: likeSpecialCharacters) { if (ch == escapeChar) { if (sb == null) { sb = new StringBuilder(value.substring(0, i)); @@ -649,6 +663,6 @@ public class DatabasePlatform { } protected void escapeLikeCharacter(char ch, StringBuilder sb) { - sb.append('\\').append(ch); + sb.append(likeEscapeChar).append(ch); } } diff --git a/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java b/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java index ccc9b9fc6..c8bcbd7f6 100644 --- a/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java +++ b/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java @@ -26,10 +26,7 @@ public class DB2Platform extends DatabasePlatform { this.dbIdentity.setSupportsGetGeneratedKeys(true); this.dbIdentity.setSupportsSequence(true); - - this.likeClause = "like ? escape '|'"; - this.specialLikeCharacters = new char[] { '%', '_', '|' }; - + this.exceptionTranslator = new SqlErrorCodes() .addAcquireLock("40001","57033") // key -911/-913 diff --git a/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java b/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java index 21b9c903b..f004be7d5 100644 --- a/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java @@ -49,8 +49,8 @@ public class MySqlPlatform extends DatabasePlatform { this.openQuote = "`"; this.closeQuote = "`"; // use pipe for escaping as it depends if mysql runs in no_backslash_escapes or not. - this.likeClause = "like binary ? escape '|'"; - this.specialLikeCharacters = new char[] { '%', '_', '|' }; + this.likeClauseRaw = "like binary ? escape ''"; + this.likeClauseEscaped = "like binary ? escape '|'"; this.forwardOnlyHintOnFindIterate = true; this.booleanDbType = Types.BIT; diff --git a/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java b/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java index 4e51d4e4c..5f0b1ca3e 100644 --- a/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java @@ -36,9 +36,7 @@ public class OraclePlatform extends DatabasePlatform { dbIdentity.setSupportsGetGeneratedKeys(true); this.treatEmptyStringsAsNull = true; - - this.likeClause = "like ? escape '|'"; - this.specialLikeCharacters = new char[] { '%', '_', '|' }; + this.likeClauseRaw = "like ?"; this.exceptionTranslator = new SqlErrorCodes() diff --git a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java index ef3b38c31..f0ed6744a 100644 --- a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java @@ -39,8 +39,9 @@ public class SqlServerPlatform extends DatabasePlatform { this.openQuote = "["; this.closeQuote = "]"; - this.specialLikeCharacters = new char[]{'%', '_', '['}; - this.likeClause = "like ? COLLATE Latin1_General_BIN"; + this.likeSpecialCharacters = new char[]{'%', '_', '['}; + this.likeClauseRaw = "like ? collate Latin1_General_BIN"; + this.likeClauseEscaped = "like ? collate Latin1_General_BIN"; booleanDbType = Types.INTEGER; dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("bit default 0")); diff --git a/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java b/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java index 4eb6a1284..49bb47bf9 100644 --- a/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java +++ b/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java @@ -64,7 +64,7 @@ public interface SpiExpressionRequest { /** * Append a DB Like clause. */ - void appendLike(); + void appendLike(boolean rawLikeExpression); /** * Escapes a string to use it as exact match in Like clause. diff --git a/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java index 82ab72153..98692c0fc 100644 --- a/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java +++ b/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java @@ -132,8 +132,8 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe * Return the database platform like clause. */ @Override - public String getDBLikeClause() { - return ebeanServer.getDatabasePlatform().getLikeClause(); + public String getDBLikeClause(boolean rawLikeExpression) { + return ebeanServer.getDatabasePlatform().getLikeClause(rawLikeExpression); } /** diff --git a/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java b/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java index 66830935b..279ddf6c9 100644 --- a/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java +++ b/src/main/java/io/ebeaninternal/server/core/SpiOrmQueryRequest.java @@ -139,7 +139,7 @@ public interface SpiOrmQueryRequest extends DocQueryRequest { /** * Return the Database platform like clause. */ - String getDBLikeClause(); + String getDBLikeClause(boolean rawLikeExpression); /** * Escapes a string to use it as exact match in Like clause. diff --git a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java index 9f8cbb4ca..a1cc868f0 100644 --- a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java +++ b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java @@ -91,9 +91,9 @@ public class DefaultExpressionRequest implements SpiExpressionRequest { * Append the database platform like clause. */ @Override - public void appendLike() { + public void appendLike(boolean rawLikeExpression) { sql.append(" "); - sql.append(queryRequest.getDBLikeClause()); + sql.append(queryRequest.getDBLikeClause(rawLikeExpression)); sql.append(" "); } diff --git a/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java b/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java index 638d545e3..1d782f57c 100644 --- a/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java +++ b/src/main/java/io/ebeaninternal/server/expression/LikeExpression.java @@ -54,7 +54,7 @@ class LikeExpression extends AbstractValueExpression { request.append(" = ? "); } else { // append db platform like clause - request.appendLike(); + request.appendLike(type == LikeType.RAW); } } diff --git a/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java b/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java index 47ee67204..f0179ea0a 100644 --- a/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java +++ b/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java @@ -75,7 +75,7 @@ public class TDSpiExpressionRequest implements SpiExpressionRequest { } @Override - public void appendLike() { + public void appendLike(boolean rawLikeExpression) { }