Polishing.
Revisit DISTINCT count queries when primary alias isn't set. HQL can handle such queries, JPQL and EQL transformers now fail properly. See #3744
This commit is contained in:
@@ -99,6 +99,10 @@ class EqlCountQueryTransformer extends EqlQueryRenderer {
|
||||
|
||||
if (countSelection.requiresPrimaryAlias()) {
|
||||
// constructor
|
||||
if (primaryFromAlias == null) {
|
||||
throw new IllegalStateException(
|
||||
"Primary alias must be set for DISTINCT count selection using constructor expressions");
|
||||
}
|
||||
nested.append(QueryTokens.token(primaryFromAlias));
|
||||
} else {
|
||||
// keep all the select items to distinct against
|
||||
|
||||
@@ -100,6 +100,10 @@ class JpqlCountQueryTransformer extends JpqlQueryRenderer {
|
||||
|
||||
if (countSelection.requiresPrimaryAlias()) {
|
||||
// constructor
|
||||
if (primaryFromAlias == null) {
|
||||
throw new IllegalStateException(
|
||||
"Primary alias must be set for DISTINCT count selection using constructor expressions");
|
||||
}
|
||||
nested.append(QueryTokens.token(primaryFromAlias));
|
||||
} else {
|
||||
// keep all the select items to distinct against
|
||||
|
||||
@@ -71,6 +71,42 @@ class QueryTransformers {
|
||||
return new CountSelectionTokenStream(target, containsNew);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter constructor expression and return the selection list of the constructor.
|
||||
*
|
||||
* @return the selection list of the constructor without {@code NEW}, class name, and the first level of
|
||||
* parentheses.
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public CountSelectionTokenStream withoutConstructorExpression() {
|
||||
|
||||
if (!requiresPrimaryAlias()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
List<QueryToken> target = new ArrayList<>(size());
|
||||
int nestingLevel = 0;
|
||||
|
||||
for (QueryToken token : this) {
|
||||
|
||||
if (token.equals(TOKEN_OPEN_PAREN)) {
|
||||
nestingLevel++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.equals(TOKEN_CLOSE_PAREN)) {
|
||||
nestingLevel--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nestingLevel > 0) {
|
||||
target.add(token);
|
||||
}
|
||||
}
|
||||
|
||||
return new CountSelectionTokenStream(target, requiresPrimaryAlias());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<QueryToken> iterator() {
|
||||
return tokens.iterator();
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class HqlQueryTransformerTests {
|
||||
|
||||
@@ -182,6 +183,12 @@ class HqlQueryTransformerTests {
|
||||
|
||||
@Test
|
||||
void createsCountQueryCorrectly() {
|
||||
|
||||
assertCountQuery("SELECT id FROM Person", "SELECT count(id) FROM Person");
|
||||
assertCountQuery("SELECT p.id FROM Person p", "SELECT count(p) FROM Person p");
|
||||
assertCountQuery("SELECT id FROM Person p", "SELECT count(id) FROM Person p");
|
||||
assertCountQuery("SELECT id, name FROM Person", "SELECT count(*) FROM Person");
|
||||
assertCountQuery("SELECT id, name FROM Person p", "SELECT count(p) FROM Person p");
|
||||
assertCountQuery(QUERY, COUNT_QUERY);
|
||||
}
|
||||
|
||||
@@ -204,6 +211,9 @@ class HqlQueryTransformerTests {
|
||||
|
||||
assertCountQuery("select distinct new com.example.User(u.name) from User u where u.foo = ?1",
|
||||
"select count(distinct u) from User u where u.foo = ?1");
|
||||
|
||||
assertCountQuery("select distinct new com.example.User(name, lastname) from User where foo = ?1",
|
||||
"select count(distinct name, lastname) from User where foo = ?1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -913,7 +923,7 @@ class HqlQueryTransformerTests {
|
||||
void countQueryShouldWorkEvenWithoutExplicitAlias() {
|
||||
|
||||
assertCountQuery("FROM BookError WHERE portal = :portal",
|
||||
"select count(__) FROM BookError AS __ WHERE portal = :portal");
|
||||
"select count(__) FROM BookError WHERE portal = :portal");
|
||||
|
||||
assertCountQuery("FROM BookError b WHERE portal = :portal",
|
||||
"select count(b) FROM BookError b WHERE portal = :portal");
|
||||
@@ -1107,15 +1117,15 @@ class HqlQueryTransformerTests {
|
||||
@Test // GH-3269, GH-3689
|
||||
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 1 as x from Employee", "select count(distinct 1) from Employee");
|
||||
assertCountQuery("SELECT DISTINCT abc AS x FROM T", "SELECT count(DISTINCT abc) FROM T");
|
||||
assertCountQuery("select distinct a as x, b as y from Employee", "select count(distinct a, b) from Employee");
|
||||
assertCountQuery("select distinct sum(amount) as x from Employee GROUP BY n",
|
||||
"select count(distinct sum(amount)) from Employee AS __ GROUP BY n");
|
||||
"select count(distinct sum(amount)) from Employee 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");
|
||||
"select count(distinct a, b, sum(amount), d) from Employee 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");
|
||||
"select count(distinct a, count(b)) from Employee GROUP BY n");
|
||||
assertCountQuery("select distinct substring(e.firstname, 1, position('a' in e.lastname)) as x from from Employee",
|
||||
"select count(distinct substring(e.firstname, 1, position('a' in e.lastname))) from from Employee");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user