diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java index 537da47e7..4e083c757 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java @@ -15,12 +15,7 @@ */ package org.springframework.data.jpa.repository.query; -import static org.springframework.data.jpa.repository.query.QueryTokens.TOKEN_AS; -import static org.springframework.data.jpa.repository.query.QueryTokens.TOKEN_CLOSE_PAREN; -import static org.springframework.data.jpa.repository.query.QueryTokens.TOKEN_COUNT_FUNC; -import static org.springframework.data.jpa.repository.query.QueryTokens.TOKEN_DOUBLE_UNDERSCORE; -import static org.springframework.data.jpa.repository.query.QueryTokens.TOKEN_OPEN_PAREN; -import static org.springframework.data.jpa.repository.query.QueryTokens.TOKEN_SELECT_COUNT; +import static org.springframework.data.jpa.repository.query.QueryTokens.*; import org.springframework.data.jpa.repository.query.HqlParser.SelectClauseContext; import org.springframework.data.jpa.repository.query.QueryRenderer.QueryRendererBuilder; @@ -208,6 +203,22 @@ class HqlCountQueryTransformer extends HqlQueryRenderer { return builder; } + @Override + public QueryTokenStream visitSelection(HqlParser.SelectionContext ctx) { + + if (isSubquery(ctx)) { + return super.visitSelection(ctx); + } + + QueryRendererBuilder builder = QueryRenderer.builder(); + + builder.append(visit(ctx.selectExpression())); + + // do not append variables to skip AS field aliasing + + return builder; + } + @Override public QueryRendererBuilder visitQueryOrder(HqlParser.QueryOrderContext ctx) { @@ -247,7 +258,7 @@ class HqlCountQueryTransformer extends HqlQueryRenderer { nested.append(QueryTokens.token(primaryFromAlias)); } else { // keep all the select items to distinct against - nested.append(countSelection); + nested.append(selectionListbuilder); } return nested; } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java index e19036dac..a9b692cd7 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java @@ -90,6 +90,23 @@ class HqlQueryTransformerTests { assertThat(results).isEqualTo("select count(e) FROM Employee e where e.name = :name"); } + @Test // GH-3536 + void shouldCreateCountQueryForDistinctCount() { + + // given + var original = """ + select distinct cast(e.timestampField as date) as foo + from ExampleEntity e + order by cast(e.timestampField as date) desc + """; + + // when + var results = createCountQueryFor(original); + + // then + assertThat(results).isEqualTo("select count(distinct cast(e.timestampField as date)) from ExampleEntity e"); + } + @Test void applyCountToMoreComplexQuery() {