Fix missing DISTINCT in count queries.

The `COUNT_MATCH` does not consider line breaks after the `from` clause or the `where` clause. This leads to a no match scenario in the construction of the count query. With the fix we now consider line breaks/whitespaces after the `from` and `where` clause.

See #2341
Related tickets: #2177
This commit is contained in:
Diego Krupitza
2021-12-18 00:48:58 +01:00
committed by Greg L. Turnquist
parent 32f0f54ebb
commit 3e64d9ad9b
2 changed files with 30 additions and 2 deletions

View File

@@ -147,7 +147,7 @@ public abstract class QueryUtils {
builder.append(IDENTIFIER_GROUP);
builder.append("(.*)");
COUNT_MATCH = compile(builder.toString(), CASE_INSENSITIVE);
COUNT_MATCH = compile(builder.toString(), CASE_INSENSITIVE | DOTALL);
Map<PersistentAttributeType, Class<? extends Annotation>> persistentAttributeTypes = new HashMap<>();
persistentAttributeTypes.put(ONE_TO_ONE, OneToOne.class);
@@ -490,7 +490,8 @@ 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

View File

@@ -423,6 +423,11 @@ class QueryUtilsUnitTests {
" where user.age = 18\n ");
}
@Test // GH-2341
void createCountQueryStarCharacterConverted() {
assertThat(createCountQueryFor("select * from User user")).isEqualTo("select count(user) from User user");
}
@Test
void createCountQuerySupportsLineBreaksInSelectClause() {
@@ -524,6 +529,28 @@ class QueryUtilsUnitTests {
assertThat(QueryUtils.getProjection("select x, frommage, y from t")).isEqualTo("x, frommage, y");
}
@Test // GH-2341
void countProjectionDistrinctQueryIncludesNewLineAfterFromAndBeforeJoin() {
String originalQuery = "SELECT DISTINCT entity1\nFROM Entity1 entity1\nLEFT JOIN Entity2 entity2 ON entity1.key = entity2.key";
assertCountQuery(originalQuery,
"select count(DISTINCT entity1) FROM Entity1 entity1\nLEFT JOIN Entity2 entity2 ON entity1.key = entity2.key");
}
@Test // GH-2341
void countProjectionDistinctQueryIncludesNewLineAfterEntity() {
String originalQuery = "SELECT DISTINCT entity1\nFROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key";
assertCountQuery(originalQuery,
"select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key");
}
@Test // GH-2341
void countProjectionDistinctQueryIncludesNewLineAfterEntityAndBeforeWhere() {
String originalQuery = "SELECT DISTINCT entity1\nFROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key\nwhere entity1.id = 1799";
assertCountQuery(originalQuery,
"select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key\nwhere entity1.id = 1799");
}
private static void assertCountQuery(String originalQuery, String countQuery) {
assertThat(createCountQueryFor(originalQuery)).isEqualTo(countQuery);
}