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
This commit is contained in:
Mark Paluch
2024-12-10 15:17:37 +01:00
parent 813bf498d4
commit dcd36bf108
2 changed files with 23 additions and 5 deletions

View File

@@ -354,11 +354,11 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer {
return this.query.getQueryString();
}
return createCountQueryFor(this.query, selectBody, countProjection);
return createCountQueryFor(this.query, selectBody, countProjection, primaryAlias);
}
private static String createCountQueryFor(DeclaredQuery query, PlainSelect selectBody,
@Nullable String countProjection) {
@Nullable String countProjection, @Nullable String primaryAlias) {
// remove order by
selectBody.setOrderByElements(null);
@@ -373,7 +373,8 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer {
selectBody.setDistinct(null); // reset possible distinct
Function jSqlCount = getJSqlCount(
Collections.singletonList(countPropertyNameForSelection(selectBody.getSelectItems(), distinct)), distinct);
Collections.singletonList(countPropertyNameForSelection(selectBody.getSelectItems(), distinct, primaryAlias)),
distinct);
selectBody.setSelectItems(Collections.singletonList(SelectItem.from(jSqlCount)));
}
@@ -463,7 +464,8 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer {
* @param tableAlias the table alias which can be {@literal null}.
* @return
*/
private static String countPropertyNameForSelection(List<SelectItem<?>> selectItems, boolean distinct) {
private static String countPropertyNameForSelection(List<SelectItem<?>> selectItems, boolean distinct,
@Nullable String tableAlias) {
if (onlyASingleColumnProjection(selectItems)) {
@@ -472,7 +474,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer {
return column.getFullyQualifiedName();
}
return (distinct ? "*" : "1");
return distinct ? ((tableAlias != null ? tableAlias + "." : "") + "*") : "1";
}
/**

View File

@@ -51,6 +51,22 @@ public class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
assertThat(sql).isEqualTo("SELECT e FROM Employee e ORDER BY e.foo ASC, e.bar ASC");
}
@Test // GH-3707
void countQueriesShouldConsiderPrimaryTableAlias() {
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.of("""
SELECT DISTINCT a.*, b.b1
FROM TableA a
JOIN TableB b ON a.b = b.b
LEFT JOIN TableC c ON b.c = c.c
ORDER BY b.b1, a.a1, a.a2
""", true));
String sql = enhancer.createCountQueryFor();
assertThat(sql).startsWith("SELECT count(DISTINCT a.*) FROM TableA a");
}
@Override
@ParameterizedTest // GH-2773
@MethodSource("jpqlCountQueries")