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:
committed by
Christoph Strobl
parent
d7316f4b44
commit
78ea533292
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.query.HqlParser.SelectionContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -331,6 +332,17 @@ class HqlQueryTransformer extends HqlQueryRenderer {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JpaQueryParsingToken> visitSelection(SelectionContext ctx) {
|
||||
|
||||
if(!countQuery || isSubquery(ctx)) {
|
||||
return super.visitSelection(ctx);
|
||||
}
|
||||
|
||||
// do not append variables to skip AS field aliasing
|
||||
return visit(ctx.selectExpression());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JpaQueryParsingToken> visitSelectClause(HqlParser.SelectClauseContext ctx) {
|
||||
|
||||
@@ -339,6 +351,7 @@ class HqlQueryTransformer extends HqlQueryRenderer {
|
||||
tokens.add(new JpaQueryParsingToken(ctx.SELECT()));
|
||||
|
||||
if (countQuery && !isSubquery(ctx)) {
|
||||
|
||||
tokens.add(TOKEN_COUNT_FUNC);
|
||||
|
||||
if (countProjection != null) {
|
||||
@@ -358,14 +371,12 @@ class HqlQueryTransformer extends HqlQueryRenderer {
|
||||
|
||||
if (ctx.DISTINCT() != null) {
|
||||
|
||||
List<JpaQueryParsingToken> countSelection = QueryTransformers.filterCountSelection(selectionListTokens);
|
||||
|
||||
if (countSelection.stream().anyMatch(hqlToken -> hqlToken.getToken().contains("new"))) {
|
||||
if (selectionListTokens.stream().anyMatch(hqlToken -> hqlToken.getToken().contains("new"))) {
|
||||
// constructor
|
||||
tokens.add(new JpaQueryParsingToken(() -> primaryFromAlias));
|
||||
} else {
|
||||
// keep all the select items to distinct against
|
||||
tokens.addAll(countSelection);
|
||||
tokens.addAll(selectionListTokens);
|
||||
}
|
||||
} else {
|
||||
tokens.add(new JpaQueryParsingToken(() -> primaryFromAlias));
|
||||
|
||||
@@ -85,6 +85,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() {
|
||||
|
||||
@@ -1037,9 +1054,9 @@ class HqlQueryTransformerTests {
|
||||
|
||||
assertCountQuery("select distinct 1 as x from Employee","select count(distinct 1) from Employee AS __");
|
||||
assertCountQuery("SELECT DISTINCT abc AS x FROM T","SELECT count(DISTINCT abc) FROM T AS __");
|
||||
assertCountQuery("select distinct a as x, b as y from Employee","select count(distinct a , b) from Employee AS __");
|
||||
assertCountQuery("select distinct a as x, b as y from Employee","select count(distinct a, b) from Employee AS __");
|
||||
assertCountQuery("select distinct sum(amount) as x from Employee GROUP BY n","select count(distinct sum(amount)) from Employee AS __ GROUP BY n");
|
||||
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");
|
||||
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");
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user