From f7737014944e606686ca5111574229426ec4484b Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Wed, 28 Sep 2022 16:30:38 -0500 Subject: [PATCH] Polishing. Also added more test cases from related pull requests. Closes #2582. Related: #2563, #2557, #2603 --- .../data/jpa/repository/query/QueryUtils.java | 22 +--- .../repository/query/QueryUtilsUnitTests.java | 121 +++++++++++------- 2 files changed, 80 insertions(+), 63 deletions(-) diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java index c4be6aee6..cdd49c624 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java @@ -18,23 +18,10 @@ package org.springframework.data.jpa.repository.query; import static jakarta.persistence.metamodel.Attribute.PersistentAttributeType.*; import static java.util.regex.Pattern.*; -import jakarta.persistence.EntityManager; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToOne; -import jakarta.persistence.Parameter; -import jakarta.persistence.Query; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.Expression; -import jakarta.persistence.criteria.Fetch; -import jakarta.persistence.criteria.From; -import jakarta.persistence.criteria.Join; -import jakarta.persistence.criteria.JoinType; -import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.*; +import jakarta.persistence.criteria.*; +import jakarta.persistence.metamodel.*; import jakarta.persistence.metamodel.Attribute.PersistentAttributeType; -import jakarta.persistence.metamodel.Bindable; -import jakarta.persistence.metamodel.ManagedType; -import jakarta.persistence.metamodel.PluralAttribute; -import jakarta.persistence.metamodel.SingularAttribute; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; @@ -105,7 +92,8 @@ public abstract class QueryUtils { private static final Pattern ALIAS_MATCH; private static final Pattern COUNT_MATCH; private static final Pattern STARTS_WITH_PAREN = Pattern.compile("^\\s*\\("); - private static final Pattern PARENS_TO_REMOVE = Pattern.compile("(\\(.*\\bfrom\\b[^)]+\\))", CASE_INSENSITIVE | DOTALL | MULTILINE); + private static final Pattern PARENS_TO_REMOVE = Pattern.compile("(\\(.*\\bfrom\\b[^)]+\\))", + CASE_INSENSITIVE | DOTALL | MULTILINE); private static final Pattern PROJECTION_CLAUSE = Pattern.compile("select\\s+(?:distinct\\s+)?(.+)\\s+from", Pattern.CASE_INSENSITIVE); diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java index 4f4118e4f..431569d1f 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsUnitTests.java @@ -15,7 +15,8 @@ */ package org.springframework.data.jpa.repository.query; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.springframework.data.jpa.repository.query.QueryUtils.*; import java.util.Collections; @@ -46,6 +47,7 @@ import org.springframework.util.StringUtils; * @author Jędrzej Biedrzycki * @author Darin Manica * @author Chris Fraser + * @author Michał Pachucki */ class QueryUtilsUnitTests { @@ -182,55 +184,82 @@ class QueryUtilsUnitTests { @Test // GH-2581 void testRemoveMultilineSubqueries() { - assertThat(normalizeWhitespace(removeSubqueries("select u from User u\n" - + " where not exists (\n" - + " from User u2\n" - + " )"))) - .isEqualTo("select u from User u where not exists"); - assertThat(normalizeWhitespace(removeSubqueries("(\n" - + " select u from User u \n" - + " where not exists (\n" - + " from User u2\n" - + " )\n" - + ")"))) - .isEqualTo("( select u from User u where not exists )"); - assertThat(normalizeWhitespace( - removeSubqueries("select u from User u \n" - + " where not exists (\n" - + " from User u2 \n" - + " where not exists (\n" - + " from User u3\n" - + " )\n" - + " )"))) - .isEqualTo("select u from User u where not exists"); - assertThat(normalizeWhitespace( - removeSubqueries("select u from User u \n" - + " where not exists (\n" - + " (\n" - + " from User u2 \n" - + " where not exists (\n" - + " from User u3\n" - + " )\n" - + " )\n" - + " )"))) - .isEqualTo("select u from User u where not exists ( )"); - assertThat(normalizeWhitespace( - removeSubqueries("(\n" - + " select u from User u \n" - + " where not exists (\n" - + " (\n" - + " from User u2 \n" - + " where not exists (\n" - + " from User u3\n" - + " )\n" - + " )\n" - + " )\n" - + ")"))) - .isEqualTo("( select u from User u where not exists ( ) )"); + assertThat(normalizeWhitespace(removeSubqueries("select u from User u\n" // + + " where not exists (\n" // + + " from User u2\n" // + + " )"))).isEqualTo("select u from User u where not exists"); + + assertThat(normalizeWhitespace(removeSubqueries("(\n" // + + " select u from User u \n" // + + " where not exists (\n" // + + " from User u2\n" // + + " )\n" // + + ")"))).isEqualTo("( select u from User u where not exists )"); + + assertThat(normalizeWhitespace(removeSubqueries("select u from User u \n" // + + " where not exists (\n" // + + " from User u2 \n" // + + " where not exists (\n" // + + " from User u3\n" // + + " )\n" // + + " )"))).isEqualTo("select u from User u where not exists"); + + assertThat(normalizeWhitespace(removeSubqueries("select u from User u \n" // + + " where not exists (\n" // + + " (\n" // + + " from User u2 \n" // + + " where not exists (\n" // + + " from User u3\n" // + + " )\n" // + + " )\n" // + + " )"))).isEqualTo("select u from User u where not exists ( )"); + + assertThat(normalizeWhitespace(removeSubqueries("(\n" // + + " select u from User u \n" // + + " where not exists (\n" // + + " (\n" // + + " from User u2 \n" // + + " where not exists (\n" // + + " from User u3\n" // + + " )\n" // + + " )\n" // + + " )\n" // + + ")"))).isEqualTo("( select u from User u where not exists ( ) )"); + } + + @Test // GH-2557 + void applySortingAccountsForNewlinesInSubselect() { + + Sort sort = Sort.by(Order.desc("age")); + + assertThat(QueryUtils.applySorting("select u\n" + // + "from user u\n" + // + "where exists (select u2\n" + // + "from user u2\n" + // + ")\n" + // + "", sort)).isEqualTo("select u\n" + // + "from user u\n" + // + "where exists (select u2\n" + // + "from user u2\n" + // + ")\n" + // + " order by u.age desc"); + } + + @Test // GH-2563 + void aliasDetectionProperlyHandlesNewlinesInSubselects() { + + assertThat(detectAlias("SELECT o\n" + // + "FROM Order o\n" + // + "AND EXISTS(SELECT 1\n" + // + "FROM Vehicle vehicle\n" + // + "WHERE vehicle.vehicleOrderId = o.id\n" + // + "AND LOWER(COALESCE(vehicle.make, '')) LIKE :query)")).isEqualTo("o"); } private String normalizeWhitespace(String s) { + Matcher matcher = MULTI_WHITESPACE.matcher(s); + if (matcher.find()) { return matcher.replaceAll(" ").trim(); }