diff --git a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 index e5ad3cfe8..751694914 100644 --- a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 +++ b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 @@ -605,7 +605,7 @@ dealingWithNullExpression // https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-like-predicate stringPatternMatching - : expression NOT? (LIKE | ILIKE) expression (ESCAPE (character|parameter))? + : expression NOT? (LIKE | ILIKE) expression (ESCAPE (stringLiteral|parameter))? ; // https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-elements-indices @@ -1078,7 +1078,7 @@ fragment HEX_DIGIT : [0-9a-fA-F]; CHARACTER : '\'' (~ ('\'' | '\\' )) '\'' ; -STRINGLITERAL : '\'' ('\'' '\'' | ~('\'' | '\\'))* '\'' ; +STRINGLITERAL : '\'' ('\'' '\'' | ~('\''))* '\'' ; JAVASTRINGLITERAL : '"' ( ('\\' [btnfr"']) | ~('"'))* '"'; INTEGER_LITERAL : INTEGER_NUMBER (L | B I)? ; FLOAT_LITERAL : FLOAT_NUMBER (D | F | B D)?; diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java index 0affea51a..e705664a7 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java @@ -2231,8 +2231,9 @@ class HqlQueryRenderer extends HqlBaseVisitor> { if (ctx.ESCAPE() != null) { tokens.add(new JpaQueryParsingToken(ctx.ESCAPE())); - if (ctx.character() != null) { - tokens.addAll(visit(ctx.character())); + + if (ctx.stringLiteral() != null) { + tokens.addAll(visit(ctx.stringLiteral())); } else if (ctx.parameter() != null) { tokens.addAll(visit(ctx.parameter())); } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java index 319084421..fcd151679 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java @@ -1544,4 +1544,9 @@ class HqlQueryRendererTests { assertQuery("SELECT ce.id FROM CalendarEvent ce WHERE ce.value = X'DEADBEEF'"); assertQuery("SELECT ce.id FROM CalendarEvent ce WHERE ce.value = x'deadbeef'"); } + + @Test // GH-3040 + void escapeClauseShouldWork() { + assertQuery("select t.name from SomeDbo t where t.name LIKE :name escape '\\\\'"); + } }