Skip to content

Commit e5d61e1

Browse files
Fix query rendering for signed expressions & literals.
This commit makes sure to retain signed expressions (hql, jpql) and literals (jpql) when rendering the query. Prior to the change singed expression/literal rendering added a space between the sign and the actual value so that `-1` would become `- 1` and `-count(u)` would be `- count(u)`. Additionally a minor glitch in the jpql rendering was resolved that would add an extra space before the closing bracket of a LENGTH expression. See: #3342
1 parent a1ebea0 commit e5d61e1

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* An ANTLR {@link org.antlr.v4.runtime.tree.ParseTreeVisitor} that renders an HQL query without making any changes.
2525
*
2626
* @author Greg Turnquist
27+
* @author Christoph Strobl
2728
* @since 3.1
2829
*/
2930
class HqlQueryRenderer extends HqlBaseVisitor<List<JpaQueryParsingToken>> {
@@ -1325,7 +1326,7 @@ public List<JpaQueryParsingToken> visitSignedExpression(HqlParser.SignedExpressi
13251326

13261327
List<JpaQueryParsingToken> tokens = new ArrayList<>();
13271328

1328-
tokens.add(new JpaQueryParsingToken(ctx.op));
1329+
tokens.add(new JpaQueryParsingToken(ctx.op, false));
13291330
tokens.addAll(visit(ctx.expression()));
13301331

13311332
return tokens;

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlQueryRenderer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,7 @@ public List<JpaQueryParsingToken> visitArithmetic_factor(JpqlParser.Arithmetic_f
14681468
List<JpaQueryParsingToken> tokens = new ArrayList<>();
14691469

14701470
if (ctx.op != null) {
1471-
tokens.add(new JpaQueryParsingToken(ctx.op));
1471+
tokens.add(new JpaQueryParsingToken(ctx.op, false));
14721472
}
14731473
tokens.addAll(visit(ctx.arithmetic_primary()));
14741474

@@ -1699,6 +1699,7 @@ public List<JpaQueryParsingToken> visitFunctions_returning_numerics(
16991699
tokens.add(new JpaQueryParsingToken(ctx.LENGTH(), false));
17001700
tokens.add(TOKEN_OPEN_PAREN);
17011701
tokens.addAll(visit(ctx.string_expression(0)));
1702+
NOSPACE(tokens);
17021703
tokens.add(TOKEN_CLOSE_PAREN);
17031704
} else if (ctx.LOCATE() != null) {
17041705

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
* IMPORTANT: Purely verifies the parser without any transformations.
3434
*
3535
* @author Greg Turnquist
36+
* @author Christoph Strobl
3637
* @since 3.1
3738
*/
3839
class HqlQueryRendererTests {
@@ -1651,4 +1652,13 @@ group by extract(epoch from departureTime)
16511652
void signedLiteralShouldWork(String query) {
16521653
assertQuery(query);
16531654
}
1655+
1656+
@ParameterizedTest // GH-3342
1657+
@ValueSource(strings = {
1658+
"select -count(u) from User u",
1659+
"select +1*(-count(u)) from User u"
1660+
})
1661+
void signedExpressionsShouldWork(String query) {
1662+
assertQuery(query);
1663+
}
16541664
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpqlQueryRendererTests.java

+26
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import org.antlr.v4.runtime.CommonTokenStream;
2323
import org.junit.jupiter.api.Disabled;
2424
import org.junit.jupiter.api.Test;
25+
import org.junit.jupiter.params.ParameterizedTest;
26+
import org.junit.jupiter.params.provider.ValueSource;
2527

2628
/**
2729
* Tests built around examples of JPQL found in the JPA spec
@@ -30,6 +32,7 @@
3032
* IMPORTANT: Purely verifies the parser without any transformations.
3133
*
3234
* @author Greg Turnquist
35+
* @author Christoph Strobl
3336
* @since 3.1
3437
*/
3538
class JpqlQueryRendererTests {
@@ -988,4 +991,27 @@ void newShouldBeLegalAsPartOfAStateFieldPathExpression() {
988991
void powerShouldBeLegalInAQuery() {
989992
assertQuery("select e.power.id from MyEntity e");
990993
}
994+
995+
@ParameterizedTest // GH-3342
996+
@ValueSource(strings = {
997+
"select 1 as value from User u",
998+
"select -1 as value from User u",
999+
"select +1 as value from User u",
1000+
"select +1*-100 as value from User u",
1001+
"select count(u)*-0.7f as value from User u",
1002+
"select count(oi) + (-100) as perc from StockOrderItem oi",
1003+
"select p from Payment p where length(p.cardNumber) between +16 and -20"
1004+
})
1005+
void signedLiteralShouldWork(String query) {
1006+
assertQuery(query);
1007+
}
1008+
1009+
@ParameterizedTest // GH-3342
1010+
@ValueSource(strings = {
1011+
"select -count(u) from User u",
1012+
"select +1*(-count(u)) from User u"
1013+
})
1014+
void signedExpressionsShouldWork(String query) {
1015+
assertQuery(query);
1016+
}
9911017
}

0 commit comments

Comments
 (0)