Skip to content

Commit 9c5d611

Browse files
Fix query rendering for signed expressions & literals.
This commit makes sure to retain signed expressions (hql, eql, jpql) and literals (eql, 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 a364c4a commit 9c5d611

File tree

6 files changed

+67
-3
lines changed

6 files changed

+67
-3
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,7 @@ public List<JpaQueryParsingToken> visitArithmetic_factor(EqlParser.Arithmetic_fa
16091609
List<JpaQueryParsingToken> tokens = new ArrayList<>();
16101610

16111611
if (ctx.op != null) {
1612-
tokens.add(new JpaQueryParsingToken(ctx.op));
1612+
tokens.add(new JpaQueryParsingToken(ctx.op, false));
16131613
}
16141614
tokens.addAll(visit(ctx.arithmetic_primary()));
16151615

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
@SuppressWarnings({ "ConstantConditions", "DuplicatedCode" })
@@ -1326,7 +1327,7 @@ public List<JpaQueryParsingToken> visitSignedExpression(HqlParser.SignedExpressi
13261327

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

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

13321333
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
@@ -1469,7 +1469,7 @@ public List<JpaQueryParsingToken> visitArithmetic_factor(JpqlParser.Arithmetic_f
14691469
List<JpaQueryParsingToken> tokens = new ArrayList<>();
14701470

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

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

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlQueryRendererTests.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 EQL 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
*/
3437
class EqlQueryRendererTests {
3538

@@ -990,4 +993,27 @@ void newShouldBeLegalAsPartOfAStateFieldPathExpression() {
990993
void powerShouldBeLegalInAQuery() {
991994
assertQuery("select e.power.id from MyEntity e");
992995
}
996+
997+
@ParameterizedTest // GH-3342
998+
@ValueSource(strings = {
999+
"select 1 from User u",
1000+
"select -1 from User u",
1001+
"select +1 from User u",
1002+
"select +1*-100 from User u",
1003+
"select count(u)*-0.7f from User u",
1004+
"select count(oi) + (-100) as perc from StockOrderItem oi",
1005+
"select p from Payment p where length(p.cardNumber) between +16 and -20"
1006+
})
1007+
void signedLiteralShouldWork(String query) {
1008+
assertQuery(query);
1009+
}
1010+
1011+
@ParameterizedTest // GH-3342
1012+
@ValueSource(strings = {
1013+
"select -count(u) from User u",
1014+
"select +1*(-count(u)) from User u"
1015+
})
1016+
void signedExpressionsShouldWork(String query) {
1017+
assertQuery(query);
1018+
}
9931019
}

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 {
@@ -1649,4 +1650,13 @@ group by extract(epoch from departureTime)
16491650
void signedLiteralShouldWork(String query) {
16501651
assertQuery(query);
16511652
}
1653+
1654+
@ParameterizedTest // GH-3342
1655+
@ValueSource(strings = {
1656+
"select -count(u) from User u",
1657+
"select +1*(-count(u)) from User u"
1658+
})
1659+
void signedExpressionsShouldWork(String query) {
1660+
assertQuery(query);
1661+
}
16521662
}

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 {
@@ -991,4 +994,27 @@ void newShouldBeLegalAsPartOfAStateFieldPathExpression() {
991994
void powerShouldBeLegalInAQuery() {
992995
assertQuery("select e.power.id from MyEntity e");
993996
}
997+
998+
@ParameterizedTest // GH-3342
999+
@ValueSource(strings = {
1000+
"select 1 as value from User u",
1001+
"select -1 as value from User u",
1002+
"select +1 as value from User u",
1003+
"select +1*-100 as value from User u",
1004+
"select count(u)*-0.7f as value from User u",
1005+
"select count(oi) + (-100) as perc from StockOrderItem oi",
1006+
"select p from Payment p where length(p.cardNumber) between +16 and -20"
1007+
})
1008+
void signedLiteralShouldWork(String query) {
1009+
assertQuery(query);
1010+
}
1011+
1012+
@ParameterizedTest // GH-3342
1013+
@ValueSource(strings = {
1014+
"select -count(u) from User u",
1015+
"select +1*(-count(u)) from User u"
1016+
})
1017+
void signedExpressionsShouldWork(String query) {
1018+
assertQuery(query);
1019+
}
9941020
}

0 commit comments

Comments
 (0)