From a69aa2256899b8cb47402a349586ec60ea69d979 Mon Sep 17 00:00:00 2001 From: Diego Krupitza Date: Thu, 28 Apr 2022 15:57:40 +0200 Subject: [PATCH] Fixes `*` bug in `createCountQueryFor`. In commit 3e64d9ad9b7d45fcf1231dbaf207be49cc481e7a a bug got introduced that uses the next symbol after the table name for the count function. With this commit this should be now resolved. The count query will use `*` when there is no alias present nor a variable. Related tickets #2341, #2177, #2260, #2511 --- .../data/jpa/repository/query/QueryUtils.java | 9 +++++++-- .../repository/query/QueryUtilsUnitTests.java | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java b/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java index e6a756f82..b8f7e147b 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java @@ -526,14 +526,19 @@ public abstract class QueryUtils { boolean useVariable = StringUtils.hasText(variable) // && !variable.startsWith(" new") // && !variable.startsWith("count(") // - && !variable.contains(",") // - && !variable.contains("*"); + && !variable.contains(","); String complexCountValue = matcher.matches() && StringUtils.hasText(matcher.group(COMPLEX_COUNT_FIRST_INDEX)) ? COMPLEX_COUNT_VALUE : COMPLEX_COUNT_LAST_VALUE; String replacement = useVariable ? SIMPLE_COUNT_VALUE : complexCountValue; + + String alias = QueryUtils.detectAlias(originalQuery); + if("*".equals(variable) && alias != null) { + replacement = alias; + } + countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, replacement)); } else { countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, countProjection)); diff --git a/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java index 91cdea5a3..0917c0ee7 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java @@ -640,4 +640,21 @@ class QueryUtilsUnitTests { "select * from (select * from user order by 1, 2, 3 desc limit 10) u order by u.active asc, age desc"); } + @Test //GH-2511 + void countQueryUsesCorrectVariable() { + String countQueryFor = createCountQueryFor("SELECT * FROM User WHERE created_at > $1"); + assertThat(countQueryFor).isEqualTo("select count(*) FROM User WHERE created_at > $1"); + + countQueryFor = createCountQueryFor("SELECT * FROM mytable WHERE nr = :number AND kon = :kon AND datum >= '2019-01-01'"); + assertThat(countQueryFor).isEqualTo("select count(*) FROM mytable WHERE nr = :number AND kon = :kon AND datum >= '2019-01-01'"); + + countQueryFor = createCountQueryFor("SELECT * FROM context ORDER BY time"); + assertThat(countQueryFor).isEqualTo("select count(*) FROM context"); + + countQueryFor = createCountQueryFor("select * FROM users_statuses WHERE (user_created_at BETWEEN $1 AND $2)"); + assertThat(countQueryFor).isEqualTo("select count(*) FROM users_statuses WHERE (user_created_at BETWEEN $1 AND $2)"); + + countQueryFor = createCountQueryFor("SELECT * FROM users_statuses us WHERE (user_created_at BETWEEN :fromDate AND :toDate)"); + assertThat(countQueryFor).isEqualTo("select count(us) FROM users_statuses us WHERE (user_created_at BETWEEN :fromDate AND :toDate)"); + } }