From a620b03482f35d4a7cad270256eb0dbbee93cf09 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 19 Jun 2018 00:42:08 +0200 Subject: [PATCH] DATAJPA-1363 - QueryUtils now detects aliases for functions using complex expressions. --- .../data/jpa/repository/query/QueryUtils.java | 12 +++++++----- .../jpa/repository/query/QueryUtilsUnitTests.java | 8 ++++++++ 2 files changed, 15 insertions(+), 5 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 6477b482b..0de601733 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 @@ -169,9 +169,10 @@ public abstract class QueryUtils { CONSTRUCTOR_EXPRESSION = compile(builder.toString(), CASE_INSENSITIVE + DOTALL); builder = new StringBuilder(); - builder.append("\\s+"); // at least one space - builder.append("\\w+\\([0-9a-zA-z\\._,\\s']+\\)"); // any function call including parameters within the brackets - builder.append("\\s+[as|AS]+\\s+(([\\w\\.]+))"); // the potential alias + // any function call including parameters within the brackets + builder.append("\\w+\\s*\\([\\w\\.,\\s'=]+\\)"); + // the potential alias + builder.append("\\s+[as|AS]+\\s+(([\\w\\.]+))"); FUNCTION_PATTERN = compile(builder.toString()); } @@ -325,7 +326,7 @@ public abstract class QueryUtils { * @param query a {@literal String} containing a query. Must not be {@literal null}. * @return a {@literal Set} containing all found aliases. Guaranteed to be not {@literal null}. */ - private static Set getFunctionAliases(String query) { + static Set getFunctionAliases(String query) { Set result = new HashSet<>(); Matcher matcher = FUNCTION_PATTERN.matcher(query); @@ -588,7 +589,8 @@ public abstract class QueryUtils { propertyPathModel = from.get(segment).getModel(); } - if (requiresJoin(propertyPathModel, model instanceof PluralAttribute, !property.hasNext()) && !isAlreadyFetched(from, segment)) { + if (requiresJoin(propertyPathModel, model instanceof PluralAttribute, !property.hasNext()) + && !isAlreadyFetched(from, segment)) { Join join = getOrCreateJoin(from, segment); return (Expression) (property.hasNext() ? toExpressionRecursively(join, property.next()) : join); } else { 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 d20608c5a..9c3384820 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 @@ -395,6 +395,14 @@ public class QueryUtilsUnitTests { .endsWith("WHERE x.id = :id"); } + @Test // DATAJPA-1363 + public void discoversAliasWithComplexFunction() { + + assertThat( + QueryUtils.getFunctionAliases("select new MyDto(sum(case when myEntity.prop3=0 then 1 else 0 end) as myAlias")) // + .contains("myAlias"); + } + private static void assertCountQuery(String originalQuery, String countQuery) { assertThat(createCountQueryFor(originalQuery), is(countQuery)); }