Skip to content

Commit

Permalink
Suppress selection item aliasing for the actual count query.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mp911de authored and christophstrobl committed Aug 9, 2024
1 parent f15d158 commit f62d382
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

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;

Expand Down Expand Up @@ -331,6 +332,17 @@ public List<JpaQueryParsingToken> visitVariable(HqlParser.VariableContext ctx) {
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) {

Expand All @@ -339,6 +351,7 @@ public List<JpaQueryParsingToken> visitSelectClause(HqlParser.SelectClauseContex
tokens.add(new JpaQueryParsingToken(ctx.SELECT()));

if (countQuery && !isSubquery(ctx)) {

tokens.add(TOKEN_COUNT_FUNC);

if (countProjection != null) {
Expand All @@ -358,14 +371,12 @@ public List<JpaQueryParsingToken> visitSelectClause(HqlParser.SelectClauseContex

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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,23 @@ void applyCountToSimpleQuery() {
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() {

Expand Down Expand Up @@ -1037,9 +1054,9 @@ void createsCountQueryUsingAliasCorrectly() {

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");
}

Expand Down

0 comments on commit f62d382

Please sign in to comment.