Suppress selection item aliasing for the actual count query.

We now no longer apply count selection filtering but rather skip select field aliasing when rendering a count query to drop the field alias within a count query.

Previously, we removed field aliasing by filtering the token stream which also removed the AS keyword from cast operators.

Closes: #3536
Original Pull Request: #3553
This commit is contained in:
Mark Paluch
2024-08-01 09:50:01 +02:00
committed by Christoph Strobl
parent e3da2f7c47
commit 9d4bde3e7d
2 changed files with 35 additions and 7 deletions

View File

@@ -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;
}

View File

@@ -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() {