Skip to content

Commit 3191b88

Browse files
committed
Polishing.
Ensure ordering of the last query only, applying ordering after the set operation. Original pull request: #3429 See #3427
1 parent b02081b commit 3191b88

File tree

4 files changed

+35
-36
lines changed

4 files changed

+35
-36
lines changed

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

+15-10
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ class HqlSortedQueryTransformer extends HqlQueryRenderer {
4747
this.primaryFromAlias = primaryFromAlias;
4848
}
4949

50-
50+
@Override
5151
public QueryTokenStream visitQueryExpression(HqlParser.QueryExpressionContext ctx) {
5252

53-
if(ObjectUtils.isEmpty(ctx.setOperator())) {
53+
if (ObjectUtils.isEmpty(ctx.setOperator())) {
5454
return super.visitQueryExpression(ctx);
5555
}
5656

@@ -59,15 +59,20 @@ public QueryTokenStream visitQueryExpression(HqlParser.QueryExpressionContext ct
5959
builder.appendExpression(visit(ctx.withClause()));
6060
}
6161

62-
builder.append(visitOrderedQuery(ctx.orderedQuery(0), Sort.unsorted()));
62+
List<HqlParser.OrderedQueryContext> orderedQueries = ctx.orderedQuery();
63+
for (int i = 0; i < orderedQueries.size(); i++) {
6364

64-
for (int i = 1; i < ctx.orderedQuery().size(); i++) {
65+
if (i != 0) {
66+
builder.append(visit(ctx.setOperator(i - 1)));
67+
}
6568

66-
builder.append(visit(ctx.setOperator(i - 1)));
67-
builder.append(visit(ctx.orderedQuery(i)));
69+
if (i == orderedQueries.size() - 1) {
70+
builder.append(visitOrderedQuery(ctx.orderedQuery(i), this.sort));
71+
} else {
72+
builder.append(visitOrderedQuery(ctx.orderedQuery(i), Sort.unsorted()));
73+
}
6874
}
6975

70-
7176
return builder;
7277
}
7378

@@ -81,7 +86,7 @@ public QueryTokenStream visitJoinPath(HqlParser.JoinPathContext ctx) {
8186

8287
QueryTokenStream tokens = super.visitJoinPath(ctx);
8388

84-
if (ctx.variable() != null && !isSubquery(ctx)) {
89+
if (ctx.variable() != null && !isSubquery(ctx)) {
8590
transformerSupport.registerAlias(tokens.getLast());
8691
}
8792

@@ -93,7 +98,7 @@ public QueryTokenStream visitJoinSubquery(HqlParser.JoinSubqueryContext ctx) {
9398

9499
QueryTokenStream tokens = super.visitJoinSubquery(ctx);
95100

96-
if (ctx.variable() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
101+
if (ctx.variable() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
97102
transformerSupport.registerAlias(tokens.getLast());
98103
}
99104

@@ -105,7 +110,7 @@ public QueryTokenStream visitVariable(HqlParser.VariableContext ctx) {
105110

106111
QueryTokenStream tokens = super.visitVariable(ctx);
107112

108-
if (ctx.identifier() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
113+
if (ctx.identifier() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
109114
transformerSupport.registerAlias(tokens.getLast());
110115
}
111116

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void applyCountToMoreComplexQuery() {
9898
}
9999

100100
@Test
101-
void applyCountToAlreadySorteQuery() {
101+
void applyCountToAlreadySortedQuery() {
102102

103103
// given
104104
var original = "SELECT e FROM Employee e where e.name = :name ORDER BY e.modified_date";
@@ -762,10 +762,12 @@ void sortingRecognizesJoinAliases() {
762762
@Test // GH-3427
763763
void sortShouldBeAppendedToFullSelectOnlyInCaseOfSetOperator() {
764764

765-
String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B')";
765+
String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B') UNION SELECT tb FROM Test tb WHERE (tb.type='C')";
766766
String target = createQueryFor(source, Sort.by("Type").ascending());
767767

768-
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') order by tb.Type asc");
768+
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') " //
769+
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') " //
770+
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'C') order by tb.Type asc");
769771
}
770772

771773
static Stream<Arguments> queriesWithReservedWordsAsIdentifiers() {

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

+15-13
Original file line numberDiff line numberDiff line change
@@ -705,11 +705,9 @@ void applySortingAccountsForNativeWindowFunction() {
705705
.isEqualTo("select dense_rank() over (order by lastname) from user u order by u.lastname, u.age desc");
706706

707707
// partition by + order by in over clause
708-
assertThat(
709-
createQueryFor(
710-
"select dense_rank() over (partition by active, age order by lastname range between 1.0 preceding and 1.0 following) from user u",
711-
sort))
712-
.isEqualTo(
708+
assertThat(createQueryFor(
709+
"select dense_rank() over (partition by active, age order by lastname range between 1.0 preceding and 1.0 following) from user u",
710+
sort)).isEqualTo(
713711
"select dense_rank() over (partition by active, age order by lastname range between 1.0 preceding and 1.0 following) from user u order by u.age desc");
714712

715713
// partition by + order by in over clause + order by at the end
@@ -1068,30 +1066,34 @@ void createsCountQueryUsingAliasCorrectly() {
10681066
@Test // GH-3427
10691067
void sortShouldBeAppendedWithSpacingInCaseOfSetOperator() {
10701068

1071-
String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B')";
1069+
String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B') UNION SELECT tb FROM Test tb WHERE (tb.type='C')";
10721070
String target = createQueryFor(source, Sort.by("Type").ascending());
1073-
1074-
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') order by tb.Type asc");
1071+
1072+
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') " //
1073+
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') " //
1074+
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'C') order by tb.Type asc");
10751075
}
10761076

10771077
@ParameterizedTest // GH-3427
1078-
@ValueSource(strings = {"", "res"})
1078+
@ValueSource(strings = { "", "res" })
10791079
void sortShouldBeAppendedToSubSelectWithSetOperatorInSubselect(String alias) {
10801080

10811081
String prefix = StringUtils.hasText(alias) ? (alias + ".") : "";
1082-
String source = "SELECT %sname FROM (SELECT c.name as name FROM Category c UNION SELECT t.name as name FROM Tag t)".formatted(prefix);
1083-
if(StringUtils.hasText(alias)) {
1082+
String source = "SELECT %sname FROM (SELECT c.name as name FROM Category c UNION SELECT t.name as name FROM Tag t)"
1083+
.formatted(prefix);
1084+
1085+
if (StringUtils.hasText(alias)) {
10841086
source = source + " %s".formatted(alias);
10851087
}
10861088

10871089
String target = createQueryFor(source, Sort.by("name").ascending());
10881090

10891091
assertThat(target).contains(" UNION SELECT ").doesNotContainPattern(Pattern.compile(".*\\SUNION"));
10901092
assertThat(target).endsWith("order by %sname asc".formatted(prefix)).satisfies(it -> {
1091-
Pattern pattern = Pattern.compile("order by %sname".formatted(prefix));
1093+
Pattern pattern = Pattern.compile("order by");
10921094
Matcher matcher = pattern.matcher(target);
10931095
int count = 0;
1094-
while(matcher.find()) {
1096+
while (matcher.find()) {
10951097
count++;
10961098
}
10971099
assertThat(count).describedAs("Found order by clause more than once in: \n%s", it).isOne();

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

-10
Original file line numberDiff line numberDiff line change
@@ -198,16 +198,6 @@ void applySortingAccountsForNewlinesInSubselect() {
198198

199199
Sort sort = Sort.by(Sort.Order.desc("age"));
200200

201-
//
202-
//
203-
//
204-
//
205-
//
206-
//
207-
//
208-
//
209-
//
210-
//
211201
assertThat(newParser("""
212202
select u
213203
from user u

0 commit comments

Comments
 (0)