Skip to content

Commit 4fe7c2e

Browse files
christophstroblmp911de
authored andcommitted
Drop AS token when creating JPQL count query using DISTINCT.
Fixes: #3269 Original pull request: #3276
1 parent 249991f commit 4fe7c2e

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

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

+20-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* An ANTLR {@link org.antlr.v4.runtime.tree.ParseTreeVisitor} that transforms a parsed HQL query.
3131
*
3232
* @author Greg Turnquist
33+
* @author Christoph Strobl
3334
* @since 3.1
3435
*/
3536
class HqlQueryTransformer extends HqlQueryRenderer {
@@ -357,12 +358,14 @@ public List<JpaQueryParsingToken> visitSelectClause(HqlParser.SelectClauseContex
357358

358359
if (ctx.DISTINCT() != null) {
359360

360-
if (selectionListTokens.stream().anyMatch(hqlToken -> hqlToken.getToken().contains("new"))) {
361+
List<JpaQueryParsingToken> countSelection = getCountSelection(selectionListTokens);
362+
363+
if (countSelection.stream().anyMatch(hqlToken -> hqlToken.getToken().contains("new"))) {
361364
// constructor
362365
tokens.add(new JpaQueryParsingToken(() -> primaryFromAlias));
363366
} else {
364367
// keep all the select items to distinct against
365-
tokens.addAll(selectionListTokens);
368+
tokens.addAll(countSelection);
366369
}
367370
} else {
368371
tokens.add(new JpaQueryParsingToken(() -> primaryFromAlias));
@@ -394,4 +397,19 @@ public List<JpaQueryParsingToken> visitInstantiation(HqlParser.InstantiationCont
394397
static <T> ArrayList<T> newArrayList() {
395398
return new ArrayList<>();
396399
}
400+
401+
private static List<JpaQueryParsingToken> getCountSelection(List<JpaQueryParsingToken> selectionListTokens) {
402+
403+
List<JpaQueryParsingToken> target = new ArrayList<>(selectionListTokens.size());
404+
for (int i = 0; i < selectionListTokens.size(); i++) {
405+
JpaQueryParsingToken token = selectionListTokens.get(i);
406+
if (token.isA(TOKEN_AS)) {
407+
i++;
408+
continue;
409+
}
410+
target.add(token);
411+
}
412+
selectionListTokens = target;
413+
return selectionListTokens;
414+
}
397415
}

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

+9
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ boolean getSpace() {
131131
return this.space;
132132
}
133133

134+
boolean isA(JpaQueryParsingToken token) {
135+
return token.getToken().equalsIgnoreCase(this.getToken());
136+
}
137+
138+
@Override
139+
public String toString() {
140+
return getToken();
141+
}
142+
134143
/**
135144
* Switch the last {@link JpaQueryParsingToken}'s spacing to {@literal true}.
136145
*/

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

+12
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
* Verify that HQL queries are properly transformed through the {@link JpaQueryEnhancer} and the {@link HqlQueryParser}.
3535
*
3636
* @author Greg Turnquist
37+
* @author Christoph Strobl
3738
*/
3839
class HqlQueryTransformerTests {
3940

@@ -1031,6 +1032,17 @@ void aliasesShouldNotOverlapWithSortProperties() {
10311032
"SELECT t3 FROM Test3 t3 JOIN t3.test2 x WHERE x.id = :test2Id order by t3.testDuplicateColumnName desc");
10321033
}
10331034

1035+
@Test // GH-3269
1036+
void createsCountQueryUsingAliasCorrectly() {
1037+
1038+
assertCountQuery("select distinct 1 as x from Employee","select count(distinct 1) from Employee AS __");
1039+
assertCountQuery("SELECT DISTINCT abc AS x FROM T","SELECT count(DISTINCT abc) FROM T AS __");
1040+
assertCountQuery("select distinct a as x, b as y from Employee","select count(distinct a , b) from Employee AS __");
1041+
assertCountQuery("select distinct sum(amount) as x from Employee GROUP BY n","select count(distinct sum(amount)) from Employee AS __ GROUP BY n");
1042+
assertCountQuery("select distinct a, b, sum(amount) as c, d from Employee GROUP BY n","select count(distinct a, b, sum(amount) , d) from Employee AS __ GROUP BY n");
1043+
assertCountQuery("select distinct a, count(b) as c from Employee GROUP BY n","select count(distinct a, count(b)) from Employee AS __ GROUP BY n");
1044+
}
1045+
10341046
private void assertCountQuery(String originalQuery, String countQuery) {
10351047
assertThat(createCountQueryFor(originalQuery)).isEqualTo(countQuery);
10361048
}

0 commit comments

Comments
 (0)