Skip to content

Commit 3d03ace

Browse files
committed
Use primary table alias for SQL count query derivation with DISTINCT queries.
We now use render COUNT(DISTINCT a.*) where 'a' is the primary table alias instead of COUNT(DISTINCT *). Closes #3707
1 parent 61d1b61 commit 3d03ace

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,11 @@ public String createCountQueryFor(@Nullable String countProjection) {
354354
return this.query.getQueryString();
355355
}
356356

357-
return createCountQueryFor(this.query, selectBody, countProjection);
357+
return createCountQueryFor(this.query, selectBody, countProjection, primaryAlias);
358358
}
359359

360360
private static String createCountQueryFor(DeclaredQuery query, PlainSelect selectBody,
361-
@Nullable String countProjection) {
361+
@Nullable String countProjection, @Nullable String primaryAlias) {
362362

363363
// remove order by
364364
selectBody.setOrderByElements(null);
@@ -373,7 +373,8 @@ private static String createCountQueryFor(DeclaredQuery query, PlainSelect selec
373373
selectBody.setDistinct(null); // reset possible distinct
374374

375375
Function jSqlCount = getJSqlCount(
376-
Collections.singletonList(countPropertyNameForSelection(selectBody.getSelectItems(), distinct)), distinct);
376+
Collections.singletonList(countPropertyNameForSelection(selectBody.getSelectItems(), distinct, primaryAlias)),
377+
distinct);
377378
selectBody.setSelectItems(Collections.singletonList(SelectItem.from(jSqlCount)));
378379
}
379380

@@ -463,7 +464,8 @@ private static OrderByElement getOrderClause(Set<String> joinAliases, Set<String
463464
* @param tableAlias the table alias which can be {@literal null}.
464465
* @return
465466
*/
466-
private static String countPropertyNameForSelection(List<SelectItem<?>> selectItems, boolean distinct) {
467+
private static String countPropertyNameForSelection(List<SelectItem<?>> selectItems, boolean distinct,
468+
@Nullable String tableAlias) {
467469

468470
if (onlyASingleColumnProjection(selectItems)) {
469471

@@ -472,7 +474,7 @@ private static String countPropertyNameForSelection(List<SelectItem<?>> selectIt
472474
return column.getFullyQualifiedName();
473475
}
474476

475-
return (distinct ? "*" : "1");
477+
return distinct ? ((tableAlias != null ? tableAlias + "." : "") + "*") : "1";
476478
}
477479

478480
/**

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ void shouldApplySorting() {
5151
assertThat(sql).isEqualTo("SELECT e FROM Employee e ORDER BY e.foo ASC, e.bar ASC");
5252
}
5353

54+
@Test // GH-3707
55+
void countQueriesShouldConsiderPrimaryTableAlias() {
56+
57+
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.of("""
58+
SELECT DISTINCT a.*, b.b1
59+
FROM TableA a
60+
JOIN TableB b ON a.b = b.b
61+
LEFT JOIN TableC c ON b.c = c.c
62+
ORDER BY b.b1, a.a1, a.a2
63+
""", true));
64+
65+
String sql = enhancer.createCountQueryFor();
66+
67+
assertThat(sql).startsWith("SELECT count(DISTINCT a.*) FROM TableA a");
68+
}
69+
5470
@Override
5571
@ParameterizedTest // GH-2773
5672
@MethodSource("jpqlCountQueries")

0 commit comments

Comments
 (0)