diff --git a/pom.xml b/pom.xml
index c94ae35cd5..6e62fb99c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.1.0-SNAPSHOT
+ 3.1.0-GH-2773-SNAPSHOT
pom
Spring Data JPA Parent
diff --git a/spring-data-envers/pom.xml b/spring-data-envers/pom.xml
index db915d7c3b..6e24605d3c 100755
--- a/spring-data-envers/pom.xml
+++ b/spring-data-envers/pom.xml
@@ -5,12 +5,12 @@
org.springframework.data
spring-data-envers
- 3.1.0-SNAPSHOT
+ 3.1.0-GH-2773-SNAPSHOT
org.springframework.data
spring-data-jpa-parent
- 3.1.0-SNAPSHOT
+ 3.1.0-GH-2773-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa-distribution/pom.xml b/spring-data-jpa-distribution/pom.xml
index a5cb2f09b5..52cf3c12a0 100644
--- a/spring-data-jpa-distribution/pom.xml
+++ b/spring-data-jpa-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.1.0-SNAPSHOT
+ 3.1.0-GH-2773-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml
index 95a83aac44..bd8aa8d5cb 100644
--- a/spring-data-jpa/pom.xml
+++ b/spring-data-jpa/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-jpa
- 3.1.0-SNAPSHOT
+ 3.1.0-GH-2773-SNAPSHOT
Spring Data JPA
Spring Data module for JPA repositories.
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.1.0-SNAPSHOT
+ 3.1.0-GH-2773-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/DefaultQueryEnhancer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/DefaultQueryEnhancer.java
index 53a07bf6f9..92387c973e 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/DefaultQueryEnhancer.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/DefaultQueryEnhancer.java
@@ -46,7 +46,7 @@ public String detectAlias() {
@Override
public String createCountQueryFor(@Nullable String countProjection) {
- return QueryUtils.createCountQueryFor(this.query.getQueryString(), countProjection);
+ return QueryUtils.createCountQueryFor(this.query.getQueryString(), countProjection, this.query.isNativeQuery());
}
@Override
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java
index 7a44873ac4..cd76876ac7 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java
@@ -15,9 +15,8 @@
*/
package org.springframework.data.jpa.repository.query;
-import static org.springframework.data.jpa.repository.query.JSqlParserUtils.getJSqlCount;
-import static org.springframework.data.jpa.repository.query.JSqlParserUtils.getJSqlLower;
-import static org.springframework.data.jpa.repository.query.QueryUtils.checkSortExpression;
+import static org.springframework.data.jpa.repository.query.JSqlParserUtils.*;
+import static org.springframework.data.jpa.repository.query.QueryUtils.*;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Alias;
@@ -29,11 +28,23 @@
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.merge.Merge;
-import net.sf.jsqlparser.statement.select.*;
+import net.sf.jsqlparser.statement.select.OrderByElement;
+import net.sf.jsqlparser.statement.select.PlainSelect;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.select.SelectBody;
+import net.sf.jsqlparser.statement.select.SelectExpressionItem;
+import net.sf.jsqlparser.statement.select.SelectItem;
+import net.sf.jsqlparser.statement.select.SetOperationList;
+import net.sf.jsqlparser.statement.select.WithItem;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.values.ValuesStatement;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.data.domain.Sort;
@@ -400,7 +411,7 @@ public String createCountQueryFor(@Nullable String countProjection) {
return selectBody.toString();
}
- String countProp = tableAlias == null ? "*" : tableAlias;
+ String countProp = query.isNativeQuery() ? (distinct ? "*" : "1") : tableAlias == null ? "*" : tableAlias;
Function jSqlCount = getJSqlCount(Collections.singletonList(countProp), distinct);
selectBody.setSelectItems(Collections.singletonList(new SelectExpressionItem(jSqlCount)));
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 5707caec26..785dde580d 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,10 +18,23 @@
import static jakarta.persistence.metamodel.Attribute.PersistentAttributeType.*;
import static java.util.regex.Pattern.*;
-import jakarta.persistence.*;
-import jakarta.persistence.criteria.*;
-import jakarta.persistence.metamodel.*;
+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.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;
@@ -570,6 +583,19 @@ public static String createCountQueryFor(String originalQuery) {
*/
@Deprecated
public static String createCountQueryFor(String originalQuery, @Nullable String countProjection) {
+ return createCountQueryFor(originalQuery, countProjection, false);
+ }
+
+ /**
+ * Creates a count projected query from the given original query.
+ *
+ * @param originalQuery must not be {@literal null}.
+ * @param countProjection may be {@literal null}.
+ * @param nativeQuery whether the underlying query is a native query.
+ * @return a query String to be used a count query for pagination. Guaranteed to be not {@literal null}.
+ * @since 2.7.8
+ */
+ static String createCountQueryFor(String originalQuery, @Nullable String countProjection, boolean nativeQuery) {
Assert.hasText(originalQuery, "OriginalQuery must not be null or empty");
@@ -591,9 +617,14 @@ public static String createCountQueryFor(String originalQuery, @Nullable String
String replacement = useVariable ? SIMPLE_COUNT_VALUE : complexCountValue;
- String alias = QueryUtils.detectAlias(originalQuery);
- if ("*".equals(variable) && alias != null) {
- replacement = alias;
+ if (nativeQuery && (variable.contains(",") || "*".equals(variable))) {
+ replacement = "1";
+ } else {
+
+ String alias = QueryUtils.detectAlias(originalQuery);
+ if (("*".equals(variable) && alias != null)) {
+ replacement = alias;
+ }
}
countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, replacement));
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/DefaultQueryEnhancerUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/DefaultQueryEnhancerUnitTests.java
new file mode 100644
index 0000000000..8b38061bf1
--- /dev/null
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/DefaultQueryEnhancerUnitTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jpa.repository.query;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+/**
+ * TCK Tests for {@link DefaultQueryEnhancer}.
+ *
+ * @author Mark Paluch
+ */
+public class DefaultQueryEnhancerUnitTests extends QueryEnhancerTckTests {
+
+ @Override
+ QueryEnhancer createQueryEnhancer(DeclaredQuery declaredQuery) {
+ return new DefaultQueryEnhancer(declaredQuery);
+ }
+
+ @Override
+ @Test // GH-2511, GH-2773
+ @Disabled("Not properly supported by QueryUtils")
+ void shouldDeriveNativeCountQueryWithVariable(String query, String expected) {}
+}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java
new file mode 100644
index 0000000000..5d97802439
--- /dev/null
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jpa.repository.query;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.assertj.core.api.Assumptions.*;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.springframework.data.domain.Sort;
+
+/**
+ * TCK Tests for {@link JSqlParserQueryEnhancer}.
+ *
+ * @author Mark Paluch
+ * @author Diego Krupitza
+ * @author Geoffrey Deremetz
+ */
+public class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
+
+ @Override
+ QueryEnhancer createQueryEnhancer(DeclaredQuery declaredQuery) {
+ return new JSqlParserQueryEnhancer(declaredQuery);
+ }
+
+ @Override
+ @ParameterizedTest // GH-2773
+ @MethodSource("jpqlCountQueries")
+ void shouldDeriveJpqlCountQuery(String query, String expected) {
+
+ assumeThat(query).as("JSQLParser does not support simple JPQL syntax").doesNotStartWithIgnoringCase("FROM");
+
+ assumeThat(query).as("JSQLParser does not support constructor JPQL syntax").doesNotContain(" new ");
+
+ super.shouldDeriveJpqlCountQuery(query, expected);
+ }
+
+ @Test
+ // GH-2578
+ void setOperationListWorks() {
+
+ String setQuery = "select SOME_COLUMN from SOME_TABLE where REPORTING_DATE = :REPORTING_DATE \n" //
+ + "except \n" //
+ + "select SOME_COLUMN from SOME_OTHER_TABLE where REPORTING_DATE = :REPORTING_DATE";
+
+ StringQuery stringQuery = new StringQuery(setQuery, true);
+ QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
+
+ assertThat(stringQuery.getAlias()).isNullOrEmpty();
+ assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
+ assertThat(stringQuery.hasConstructorExpression()).isFalse();
+
+ assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
+ assertThat(queryEnhancer.applySorting(Sort.by("SOME_COLUMN"))).endsWith("ORDER BY SOME_COLUMN ASC");
+ assertThat(queryEnhancer.getJoinAliases()).isEmpty();
+ assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
+ assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
+ assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
+ }
+
+ @Test // GH-2578
+ void complexSetOperationListWorks() {
+
+ String setQuery = "select SOME_COLUMN from SOME_TABLE where REPORTING_DATE = :REPORTING_DATE \n" //
+ + "except \n" //
+ + "select SOME_COLUMN from SOME_OTHER_TABLE where REPORTING_DATE = :REPORTING_DATE \n" //
+ + "union select SOME_COLUMN from SOME_OTHER_OTHER_TABLE";
+
+ StringQuery stringQuery = new StringQuery(setQuery, true);
+ QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
+
+ assertThat(stringQuery.getAlias()).isNullOrEmpty();
+ assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
+ assertThat(stringQuery.hasConstructorExpression()).isFalse();
+
+ assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
+ assertThat(queryEnhancer.applySorting(Sort.by("SOME_COLUMN").ascending())).endsWith("ORDER BY SOME_COLUMN ASC");
+ assertThat(queryEnhancer.getJoinAliases()).isEmpty();
+ assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
+ assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
+ assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
+ }
+
+ @Test // GH-2578
+ void deeplyNestedcomplexSetOperationListWorks() {
+
+ String setQuery = "SELECT CustomerID FROM (\n" //
+ + "\t\t\tselect * from Customers\n" //
+ + "\t\t\texcept\n"//
+ + "\t\t\tselect * from Customers where country = 'Austria'\n"//
+ + "\t)\n" //
+ + "\texcept\n"//
+ + "\tselect CustomerID from customers where country = 'Germany'\n"//
+ + "\t;";
+
+ StringQuery stringQuery = new StringQuery(setQuery, true);
+ QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
+
+ assertThat(stringQuery.getAlias()).isNullOrEmpty();
+ assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("CustomerID");
+ assertThat(stringQuery.hasConstructorExpression()).isFalse();
+
+ assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
+ assertThat(queryEnhancer.applySorting(Sort.by("CustomerID").descending())).endsWith("ORDER BY CustomerID DESC");
+ assertThat(queryEnhancer.getJoinAliases()).isEmpty();
+ assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
+ assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("CustomerID");
+ assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
+ }
+
+ @Test // GH-2578
+ void valuesStatementsWorks() {
+
+ String setQuery = "VALUES (1, 2, 'test')";
+
+ StringQuery stringQuery = new StringQuery(setQuery, true);
+ QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
+
+ assertThat(stringQuery.getAlias()).isNullOrEmpty();
+ assertThat(stringQuery.getProjection()).isNullOrEmpty();
+ assertThat(stringQuery.hasConstructorExpression()).isFalse();
+
+ assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
+ assertThat(queryEnhancer.applySorting(Sort.by("CustomerID").descending())).isEqualTo(setQuery);
+ assertThat(queryEnhancer.getJoinAliases()).isEmpty();
+ assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
+ assertThat(queryEnhancer.getProjection()).isNullOrEmpty();
+ assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
+ }
+
+ @Test // GH-2578
+ void withStatementsWorks() {
+
+ String setQuery = "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))) \n"
+ + "select day, value from sample_data as a";
+
+ StringQuery stringQuery = new StringQuery(setQuery, true);
+ QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
+
+ assertThat(stringQuery.getAlias()).isEqualToIgnoringCase("a");
+ assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("day, value");
+ assertThat(stringQuery.hasConstructorExpression()).isFalse();
+
+ assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(
+ "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)))\n"
+ + "SELECT count(1) FROM sample_data AS a");
+ assertThat(queryEnhancer.applySorting(Sort.by("day").descending())).endsWith("ORDER BY a.day DESC");
+ assertThat(queryEnhancer.getJoinAliases()).isEmpty();
+ assertThat(queryEnhancer.detectAlias()).isEqualToIgnoringCase("a");
+ assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("day, value");
+ assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
+ }
+
+ @Test // GH-2578
+ void multipleWithStatementsWorks() {
+
+ String setQuery = "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))), test2 as (values (1,2,3)) \n"
+ + "select day, value from sample_data as a";
+
+ StringQuery stringQuery = new StringQuery(setQuery, true);
+ QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
+
+ assertThat(stringQuery.getAlias()).isEqualToIgnoringCase("a");
+ assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("day, value");
+ assertThat(stringQuery.hasConstructorExpression()).isFalse();
+
+ assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(
+ "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))),test2 AS (VALUES (1, 2, 3))\n"
+ + "SELECT count(1) FROM sample_data AS a");
+ assertThat(queryEnhancer.applySorting(Sort.by("day").descending())).endsWith("ORDER BY a.day DESC");
+ assertThat(queryEnhancer.getJoinAliases()).isEmpty();
+ assertThat(queryEnhancer.detectAlias()).isEqualToIgnoringCase("a");
+ assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("day, value");
+ assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
+ }
+
+ @ParameterizedTest // GH-2641
+ @MethodSource("mergeStatementWorksSource")
+ void mergeStatementWorksWithJSqlParser(String query, String alias) {
+
+ StringQuery stringQuery = new StringQuery(query, true);
+ QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
+
+ assertThat(queryEnhancer.detectAlias()).isEqualTo(alias);
+ assertThat(QueryUtils.detectAlias(query)).isNull();
+
+ assertThat(queryEnhancer.getJoinAliases()).isEmpty();
+ assertThat(queryEnhancer.detectAlias()).isEqualTo(alias);
+ assertThat(queryEnhancer.getProjection()).isEmpty();
+ assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
+ }
+
+ static Stream mergeStatementWorksSource() {
+
+ return Stream.of( //
+ Arguments.of(
+ "merge into a using (select id, value from b) query on (a.id = query.id) when matched then update set a.value = value",
+ "query"),
+ Arguments.of(
+ "merge into a using (select id2, value from b) on (id = id2) when matched then update set a.value = value",
+ null));
+ }
+}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerTckTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerTckTests.java
new file mode 100644
index 0000000000..4bbeb008fb
--- /dev/null
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerTckTests.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jpa.repository.query;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * TCK Tests for {@link QueryEnhancer}.
+ *
+ * @author Mark Paluch
+ */
+abstract class QueryEnhancerTckTests {
+
+ @ParameterizedTest
+ @MethodSource("nativeCountQueries") // GH-2773
+ void shouldDeriveNativeCountQuery(String query, String expected) {
+
+ DeclaredQuery declaredQuery = DeclaredQuery.of(query, true);
+ QueryEnhancer enhancer = createQueryEnhancer(declaredQuery);
+ String countQueryFor = enhancer.createCountQueryFor();
+
+ // lenient cleanup to allow for rendering variance
+ String sanitized = countQueryFor.replaceAll("\r", " ").replaceAll("\n", " ").replaceAll(" {2}", " ")
+ .replaceAll(" {2}", " ").trim();
+
+ assertThat(sanitized).isEqualToIgnoringCase(expected);
+ }
+
+ static Stream nativeCountQueries() {
+
+ return Stream.of(Arguments.of( //
+ "SELECT * FROM table_name some_alias", //
+ "select count(1) FROM table_name some_alias"), //
+
+ Arguments.of( //
+ "SELECT name FROM table_name some_alias", //
+ "select count(name) FROM table_name some_alias"), //
+
+ Arguments.of( //
+ "SELECT DISTINCT name FROM table_name some_alias", //
+ "select count(DISTINCT name) FROM table_name some_alias"), //
+
+ Arguments.of( //
+ "select distinct u from User u where u.foo = ?", //
+ "select count(distinct u) from User u where u.foo = ?"),
+
+ Arguments.of( //
+ "select u from User as u", //
+ "select count(u) from User as u"),
+
+ Arguments.of( //
+ "SELECT u FROM User u where u.foo.bar = ?", //
+ "select count(u) FROM User u where u.foo.bar = ?"),
+
+ Arguments.of( //
+ "select p.lastname,p.firstname from Person p", //
+ "select count(1) from Person p"),
+
+ // whitespace quirks
+ Arguments.of( //
+ """
+ select user.age,
+ user.name
+ from User user
+ where user.age = 18
+ order
+ by
+ user.name
+ \s""", //
+ "select count(1) from User user where user.age = 18"),
+
+ Arguments.of( //
+ "select * from User user\n" + //
+ " where user.age = 18\n" + //
+ " order by user.name\n ", //
+ "select count(1) from User user where user.age = 18"),
+
+ Arguments.of( //
+ "SELECT DISTINCT entity1\nFROM Entity1 entity1\nLEFT JOIN Entity2 entity2 ON entity1.key = entity2.key", //
+ "select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key"),
+
+ Arguments.of( //
+ "SELECT DISTINCT entity1\nFROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key", //
+ "select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key"),
+
+ Arguments.of( //
+ "SELECT DISTINCT entity1\nFROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key\nwhere entity1.id = 1799", //
+ "select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key where entity1.id = 1799"),
+
+ Arguments.of( //
+ "select distinct m.genre from Media m where m.user = ?1 OrDer By m.genre ASC", //
+ "select count(distinct m.genre) from Media m where m.user = ?1"));
+ }
+
+ @ParameterizedTest // GH-2773
+ @MethodSource("jpqlCountQueries")
+ void shouldDeriveJpqlCountQuery(String query, String expected) {
+
+ DeclaredQuery declaredQuery = DeclaredQuery.of(query, false);
+ QueryEnhancer enhancer = createQueryEnhancer(declaredQuery);
+ String countQueryFor = enhancer.createCountQueryFor(null);
+
+ assertThat(countQueryFor).isEqualToIgnoringCase(expected);
+ }
+
+ static Stream jpqlCountQueries() {
+
+ return Stream.of(Arguments.of( //
+ "SELECT some_alias FROM table_name some_alias", //
+ "select count(some_alias) FROM table_name some_alias"), //
+
+ Arguments.of( //
+ "SELECT name FROM table_name some_alias", //
+ "select count(name) FROM table_name some_alias"), //
+
+ Arguments.of( //
+ "SELECT DISTINCT name FROM table_name some_alias", //
+ "select count(DISTINCT name) FROM table_name some_alias"),
+
+ Arguments.of( //
+ "select distinct new User(u.name) from User u where u.foo = ?", //
+ "select count(distinct u) from User u where u.foo = ?"),
+
+ Arguments.of( //
+ "FROM User u WHERE u.foo.bar = ?", //
+ "select count(u) FROM User u WHERE u.foo.bar = ?"),
+
+ Arguments.of( //
+ "from User u", //
+ "select count(u) FROM User u"),
+
+ Arguments.of( //
+ "select u from User as u", //
+ "select count(u) from User as u"),
+
+ Arguments.of( //
+ "select p.lastname,p.firstname from Person p", //
+ "select count(p) from Person p"),
+
+ Arguments.of( //
+ "select a.b from A a", //
+ "select count(a.b) from A a"),
+
+ Arguments.of( //
+ "select distinct m.genre from Media m where m.user = ?1 order by m.genre asc", //
+ "select count(distinct m.genre) from Media m where m.user = ?1"));
+ }
+
+ @ParameterizedTest // GH-2511, GH-2773
+ @MethodSource("nativeQueriesWithVariables")
+ void shouldDeriveNativeCountQueryWithVariable(String query, String expected) {
+
+ DeclaredQuery declaredQuery = DeclaredQuery.of(query, true);
+ QueryEnhancer enhancer = createQueryEnhancer(declaredQuery);
+ String countQueryFor = enhancer.createCountQueryFor();
+
+ assertThat(countQueryFor).isEqualToIgnoringCase(expected);
+ }
+
+ static Stream nativeQueriesWithVariables() {
+
+ return Stream.of(Arguments.of( //
+ "SELECT * FROM User WHERE created_at > $1", //
+ "SELECT count(1) FROM User WHERE created_at > $1"), //
+
+ Arguments.of( //
+ "SELECT * FROM (select * from test) ", //
+ "SELECT count(1) FROM (SELECT * FROM test)"), //
+
+ Arguments.of( //
+ "SELECT * FROM (select * from test) as test", //
+ "SELECT count(1) FROM (SELECT * FROM test) AS test"));
+ }
+
+ @Test
+ // DATAJPA-1696
+ void findProjectionClauseWithIncludedFrom() {
+
+ StringQuery query = new StringQuery("select x, frommage, y from t", true);
+
+ assertThat(createQueryEnhancer(query).getProjection()).isEqualTo("x, frommage, y");
+ }
+
+ abstract QueryEnhancer createQueryEnhancer(DeclaredQuery declaredQuery);
+
+}
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerUnitTests.java
index 5c1137aea2..549528160f 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerUnitTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/QueryEnhancerUnitTests.java
@@ -15,9 +15,7 @@
*/
package org.springframework.data.jpa.repository.query;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.*;
import java.util.Arrays;
import java.util.Collections;
@@ -47,37 +45,8 @@ class QueryEnhancerUnitTests {
private static final String FQ_QUERY = "select u from org.acme.domain.User$Foo_Bar u";
private static final String SIMPLE_QUERY = "from User u";
private static final String COUNT_QUERY = "select count(u) from User u";
-
private static final String QUERY_WITH_AS = "select u from User as u where u.username = ?";
- @Test
- void createsCountQueryCorrectly() {
- assertCountQuery(QUERY, COUNT_QUERY, true);
- }
-
- @Test
- void createsCountQueriesCorrectlyForCapitalLetterJPQL() {
-
- assertCountQuery("FROM User u WHERE u.foo.bar = ?", "select count(u) FROM User u WHERE u.foo.bar = ?", false);
-
- assertCountQuery("SELECT u FROM User u where u.foo.bar = ?", "select count(u) FROM User u where u.foo.bar = ?",
- true);
- }
-
- @Test
- void createsCountQueryForDistinctQueries() {
-
- assertCountQuery("select distinct u from User u where u.foo = ?",
- "select count(distinct u) from User u where u.foo = ?", true);
- }
-
- @Test
- void createsCountQueryForConstructorQueries() {
-
- assertCountQuery("select distinct new User(u.name) from User u where u.foo = ?",
- "select count(distinct u) from User u where u.foo = ?", false);
- }
-
@Test
void createsCountQueryForJoinsNoneNative() {
@@ -99,11 +68,6 @@ void createsCountQueryForQueriesWithSubSelects() {
"select count(u) from User u left outer join u.roles r where r in (select r from Role)", true);
}
- @Test
- void createsCountQueryForAliasesCorrectly() {
- assertCountQuery("select u from User as u", "select count(u) from User as u", true);
- }
-
@Test
void allowsShortJpaSyntax() {
assertCountQuery(SIMPLE_QUERY, COUNT_QUERY, false);
@@ -179,13 +143,6 @@ void appendsIgnoreCaseOrderingCorrectly() {
.endsWithIgnoringCase("order by p.lastname asc, lower(p.firstname) asc");
}
- @Test // DATAJPA-342
- void usesReturnedVariableInCountProjectionIfSet() {
-
- assertCountQuery("select distinct m.genre from Media m where m.user = ?1 order by m.genre asc",
- "select count(distinct m.genre) from Media m where m.user = ?1", true);
- }
-
@Test // DATAJPA-343
void projectsCountQueriesForQueriesWithSubSelects() {
@@ -205,13 +162,6 @@ void doesNotPrefixSortsIfFunction() {
.isInstanceOf(InvalidDataAccessApiUsageException.class);
}
- @Test // DATAJPA-377
- void removesOrderByInGeneratedCountQueryFromOriginalQueryIfPresent() {
-
- assertCountQuery("select distinct m.genre from Media m where m.user = ?1 OrDer By m.genre ASC",
- "select count(distinct m.genre) from Media m where m.user = ?1", true);
- }
-
@Test // DATAJPA-375
void findsExistingOrderByIndependentOfCase() {
@@ -222,16 +172,6 @@ void findsExistingOrderByIndependentOfCase() {
assertThat(query).endsWithIgnoringCase("ORDER BY p.firstname, p.lastname asc");
}
- @Test // DATAJPA-409
- void createsCountQueryForNestedReferenceCorrectly() {
- assertCountQuery("select a.b from A a", "select count(a.b) from A a", true);
- }
-
- @Test // DATAJPA-420
- void createsCountQueryForScalarSelects() {
- assertCountQuery("select p.lastname,p.firstname from Person p", "select count(p) from Person p", true);
- }
-
@Test // DATAJPA-456
void createCountQueryFromTheGivenCountProjection() {
@@ -482,30 +422,6 @@ void detectsAliasWithGroupAndOrderBy() {
assertThat(getEnhancer(queryWithOrderAlias).detectAlias()).isEqualTo("u");
}
- @Test // DATAJPA-1500
- void createCountQuerySupportsWhitespaceCharacters() {
-
- StringQuery query = new StringQuery("select * from User user\n" + //
- " where user.age = 18\n" + //
- " order by user.name\n ", true);
-
- assertThat(getEnhancer(query).createCountQueryFor())
- .isEqualToIgnoringCase("select count(user) from User user where user.age = 18");
- }
-
- @Test
- void createCountQuerySupportsLineBreaksInSelectClause() {
-
- StringQuery query = new StringQuery("select user.age,\n" + //
- " user.name\n" + //
- " from User user\n" + //
- " where user.age = 18\n" + //
- " order\nby\nuser.name\n ", true);
-
- assertThat(getEnhancer(query).createCountQueryFor())
- .isEqualToIgnoringCase("select count(user) from User user where user.age = 18");
- }
-
@Test // DATAJPA-1061
void appliesSortCorrectlyForFieldAliases() {
@@ -627,52 +543,6 @@ void findProjectionClauseWithSubselectNative() {
assertThat(getEnhancer(query).getProjection()).isEqualTo("*");
}
- @Test // DATAJPA-1696
- void findProjectionClauseWithIncludedFrom() {
-
- StringQuery query = new StringQuery("select x, frommage, y from t", true);
-
- assertThat(getEnhancer(query).getProjection()).isEqualTo("x, frommage, y");
- }
-
- @Test
- void countProjectionDistinctQueryIncludesNewLineAfterFromAndBeforeJoin() {
-
- StringQuery originalQuery = new StringQuery(
- "SELECT DISTINCT entity1\nFROM Entity1 entity1\nLEFT JOIN Entity2 entity2 ON entity1.key = entity2.key", true);
-
- assertCountQuery(originalQuery,
- "select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key");
- }
-
- @Test
- void countProjectionDistinctQueryIncludesNewLineAfterEntity() {
-
- StringQuery originalQuery = new StringQuery(
- "SELECT DISTINCT entity1\nFROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key", true);
-
- assertCountQuery(originalQuery,
- "select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key");
- }
-
- @Test
- void countProjectionDistinctQueryIncludesNewLineAfterEntityAndBeforeWhere() {
-
- StringQuery originalQuery = new StringQuery(
- "SELECT DISTINCT entity1\nFROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key\nwhere entity1.id = 1799",
- true);
-
- assertCountQuery(originalQuery,
- "select count(DISTINCT entity1) FROM Entity1 entity1 LEFT JOIN Entity2 entity2 ON entity1.key = entity2.key where entity1.id = 1799");
- }
-
- @Test
- void createsCountQueriesCorrectlyForCapitalLetter() {
-
- assertCountQuery("SELECT u FROM User u where u.foo.bar = ?", "select count(u) FROM User u where u.foo.bar = ?",
- true);
- }
-
@ParameterizedTest // DATAJPA-252
@MethodSource("detectsJoinAliasesCorrectlySource")
void detectsJoinAliasesCorrectly(String queryString, List aliases) {
@@ -686,7 +556,6 @@ void detectsJoinAliasesCorrectly(String queryString, List aliases) {
assertThat(nonNativeJoinAliases).containsAll(nativeJoinAliases);
assertThat(nativeJoinAliases).hasSameSizeAs(aliases) //
.containsAll(aliases);
-
}
@Test // GH-2441
@@ -717,26 +586,6 @@ void correctApplySortOnComplexNestedFunctionQuery() {
assertThat(result).containsIgnoringCase("order by dd.institutesIds");
}
- @Test // GH-2511
- void countQueryUsesCorrectVariable() {
-
- StringQuery nativeQuery = new StringQuery("SELECT * FROM User WHERE created_at > $1", true);
-
- QueryEnhancer queryEnhancer = getEnhancer(nativeQuery);
- String countQueryFor = queryEnhancer.createCountQueryFor();
- assertThat(countQueryFor).isEqualTo("SELECT count(*) FROM User WHERE created_at > $1");
-
- nativeQuery = new StringQuery("SELECT * FROM (select * from test) ", true);
- queryEnhancer = getEnhancer(nativeQuery);
- countQueryFor = queryEnhancer.createCountQueryFor();
- assertThat(countQueryFor).isEqualTo("SELECT count(*) FROM (SELECT * FROM test)");
-
- nativeQuery = new StringQuery("SELECT * FROM (select * from test) as test", true);
- queryEnhancer = getEnhancer(nativeQuery);
- countQueryFor = queryEnhancer.createCountQueryFor();
- assertThat(countQueryFor).isEqualTo("SELECT count(test) FROM (SELECT * FROM test) AS test");
- }
-
@Test // GH-2555
void modifyingQueriesAreDetectedCorrectly() {
@@ -757,143 +606,6 @@ void modifyingQueriesAreDetectedCorrectly() {
assertThat(QueryEnhancerFactory.forQuery(modiQuery).createCountQueryFor()).isEqualToIgnoringCase(modifyingQuery);
}
- @Test // GH-2578
- void setOperationListWorksWithJSQLParser() {
-
- String setQuery = "select SOME_COLUMN from SOME_TABLE where REPORTING_DATE = :REPORTING_DATE \n" //
- + "except \n" //
- + "select SOME_COLUMN from SOME_OTHER_TABLE where REPORTING_DATE = :REPORTING_DATE";
-
- StringQuery stringQuery = new StringQuery(setQuery, true);
- QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
-
- assertThat(stringQuery.getAlias()).isNullOrEmpty();
- assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
- assertThat(stringQuery.hasConstructorExpression()).isFalse();
-
- assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
- assertThat(queryEnhancer.applySorting(Sort.by("SOME_COLUMN"))).endsWith("ORDER BY SOME_COLUMN ASC");
- assertThat(queryEnhancer.getJoinAliases()).isEmpty();
- assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
- assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
- assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
- }
-
- @Test // GH-2578
- void complexSetOperationListWorksWithJSQLParser() {
-
- String setQuery = "select SOME_COLUMN from SOME_TABLE where REPORTING_DATE = :REPORTING_DATE \n" //
- + "except \n" //
- + "select SOME_COLUMN from SOME_OTHER_TABLE where REPORTING_DATE = :REPORTING_DATE \n" //
- + "union select SOME_COLUMN from SOME_OTHER_OTHER_TABLE";
-
- StringQuery stringQuery = new StringQuery(setQuery, true);
- QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
-
- assertThat(stringQuery.getAlias()).isNullOrEmpty();
- assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
- assertThat(stringQuery.hasConstructorExpression()).isFalse();
-
- assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
- assertThat(queryEnhancer.applySorting(Sort.by("SOME_COLUMN").ascending())).endsWith("ORDER BY SOME_COLUMN ASC");
- assertThat(queryEnhancer.getJoinAliases()).isEmpty();
- assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
- assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
- assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
- }
-
- @Test // GH-2578
- void deeplyNestedcomplexSetOperationListWorksWithJSQLParser() {
-
- String setQuery = "SELECT CustomerID FROM (\n" //
- + "\t\t\tselect * from Customers\n" //
- + "\t\t\texcept\n"//
- + "\t\t\tselect * from Customers where country = 'Austria'\n"//
- + "\t)\n" //
- + "\texcept\n"//
- + "\tselect CustomerID from customers where country = 'Germany'\n"//
- + "\t;";
-
- StringQuery stringQuery = new StringQuery(setQuery, true);
- QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
-
- assertThat(stringQuery.getAlias()).isNullOrEmpty();
- assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("CustomerID");
- assertThat(stringQuery.hasConstructorExpression()).isFalse();
-
- assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
- assertThat(queryEnhancer.applySorting(Sort.by("CustomerID").descending())).endsWith("ORDER BY CustomerID DESC");
- assertThat(queryEnhancer.getJoinAliases()).isEmpty();
- assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
- assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("CustomerID");
- assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
- }
-
- @Test // GH-2578
- void valuesStatementsWorksWithJSQLParser() {
-
- String setQuery = "VALUES (1, 2, 'test')";
-
- StringQuery stringQuery = new StringQuery(setQuery, true);
- QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
-
- assertThat(stringQuery.getAlias()).isNullOrEmpty();
- assertThat(stringQuery.getProjection()).isNullOrEmpty();
- assertThat(stringQuery.hasConstructorExpression()).isFalse();
-
- assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(setQuery);
- assertThat(queryEnhancer.applySorting(Sort.by("CustomerID").descending())).isEqualTo(setQuery);
- assertThat(queryEnhancer.getJoinAliases()).isEmpty();
- assertThat(queryEnhancer.detectAlias()).isNullOrEmpty();
- assertThat(queryEnhancer.getProjection()).isNullOrEmpty();
- assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
- }
-
- @Test // GH-2578
- void withStatementsWorksWithJSQLParser() {
-
- String setQuery = "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))) \n"
- + "select day, value from sample_data as a";
-
- StringQuery stringQuery = new StringQuery(setQuery, true);
- QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
-
- assertThat(stringQuery.getAlias()).isEqualToIgnoringCase("a");
- assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("day, value");
- assertThat(stringQuery.hasConstructorExpression()).isFalse();
-
- assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(
- "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)))\n"
- + "SELECT count(a) FROM sample_data AS a");
- assertThat(queryEnhancer.applySorting(Sort.by("day").descending())).endsWith("ORDER BY a.day DESC");
- assertThat(queryEnhancer.getJoinAliases()).isEmpty();
- assertThat(queryEnhancer.detectAlias()).isEqualToIgnoringCase("a");
- assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("day, value");
- assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
- }
-
- @Test // GH-2578
- void multipleWithStatementsWorksWithJSQLParser() {
-
- String setQuery = "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))), test2 as (values (1,2,3)) \n"
- + "select day, value from sample_data as a";
-
- StringQuery stringQuery = new StringQuery(setQuery, true);
- QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
-
- assertThat(stringQuery.getAlias()).isEqualToIgnoringCase("a");
- assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("day, value");
- assertThat(stringQuery.hasConstructorExpression()).isFalse();
-
- assertThat(queryEnhancer.createCountQueryFor()).isEqualToIgnoringCase(
- "with sample_data (day, value) AS (VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))),test2 AS (VALUES (1, 2, 3))\n"
- + "SELECT count(a) FROM sample_data AS a");
- assertThat(queryEnhancer.applySorting(Sort.by("day").descending())).endsWith("ORDER BY a.day DESC");
- assertThat(queryEnhancer.getJoinAliases()).isEmpty();
- assertThat(queryEnhancer.detectAlias()).isEqualToIgnoringCase("a");
- assertThat(queryEnhancer.getProjection()).isEqualToIgnoringCase("day, value");
- assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
- }
@ParameterizedTest // GH-2593
@MethodSource("insertStatementIsProcessedSameAsDefaultSource")
@@ -926,21 +638,7 @@ void insertStatementIsProcessedSameAsDefault(String insertQuery) {
assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
}
- @ParameterizedTest // GH-2641
- @MethodSource("mergeStatementWorksWithJSqlParserSource")
- void mergeStatementWorksWithJSqlParser(String query, String alias) {
-
- StringQuery stringQuery = new StringQuery(query, true);
- QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery);
- assertThat(queryEnhancer.detectAlias()).isEqualTo(alias);
- assertThat(QueryUtils.detectAlias(query)).isNull();
-
- assertThat(queryEnhancer.getJoinAliases()).isEmpty();
- assertThat(queryEnhancer.detectAlias()).isEqualTo(alias);
- assertThat(queryEnhancer.getProjection()).isEmpty();
- assertThat(queryEnhancer.hasConstructorExpression()).isFalse();
- }
public static Stream insertStatementIsProcessedSameAsDefaultSource() {
@@ -950,17 +648,6 @@ public static Stream insertStatementIsProcessedSameAsDefaultSource()
);
}
- public static Stream mergeStatementWorksWithJSqlParserSource() {
-
- return Stream.of( //
- Arguments.of(
- "merge into a using (select id, value from b) query on (a.id = query.id) when matched then update set a.value = value",
- "query"),
- Arguments.of(
- "merge into a using (select id2, value from b) on (id = id2) when matched then update set a.value = value",
- null));
- }
-
public static Stream detectsJoinAliasesCorrectlySource() {
return Stream.of( //
@@ -985,4 +672,5 @@ private static void assertCountQuery(StringQuery originalQuery, String countQuer
private static QueryEnhancer getEnhancer(DeclaredQuery query) {
return QueryEnhancerFactory.forQuery(query);
}
+
}