Skip to content

Commit 4bc46bb

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 10a738c commit 4bc46bb

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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 26 additions & 0 deletions
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

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

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

Lines changed: 10 additions & 0 deletions
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

Lines changed: 26 additions & 0 deletions
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 {
@@ -993,4 +996,27 @@ void newShouldBeLegalAsPartOfAStateFieldPathExpression() {
993996
void powerShouldBeLegalInAQuery() {
994997
assertQuery("select e.power.id from MyEntity e");
995998
}
999+
1000+
@ParameterizedTest // GH-3342
1001+
@ValueSource(strings = {
1002+
"select 1 as value from User u",
1003+
"select -1 as value from User u",
1004+
"select +1 as value from User u",
1005+
"select +1*-100 as value from User u",
1006+
"select count(u)*-0.7f as value from User u",
1007+
"select count(oi) + (-100) as perc from StockOrderItem oi",
1008+
"select p from Payment p where length(p.cardNumber) between +16 and -20"
1009+
})
1010+
void signedLiteralShouldWork(String query) {
1011+
assertQuery(query);
1012+
}
1013+
1014+
@ParameterizedTest // GH-3342
1015+
@ValueSource(strings = {
1016+
"select -count(u) from User u",
1017+
"select +1*(-count(u)) from User u"
1018+
})
1019+
void signedExpressionsShouldWork(String query) {
1020+
assertQuery(query);
1021+
}
9961022
}

0 commit comments

Comments
 (0)