Skip to content

Fix NullPointer when deriving a count query for non-SELECT statements, delay count query derivation #2817

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-GH-2812-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data JPA Parent</name>
Expand Down
4 changes: 2 additions & 2 deletions spring-data-envers/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-envers</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-GH-2812-SNAPSHOT</version>

<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-GH-2812-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-jpa-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-GH-2812-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
4 changes: 2 additions & 2 deletions spring-data-jpa/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-GH-2812-SNAPSHOT</version>

<name>Spring Data JPA</name>
<description>Spring Data module for JPA repositories.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-GH-2812-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.QueryRewriter;
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.data.util.Lazy;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
Expand All @@ -46,7 +44,7 @@
abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {

private final DeclaredQuery query;
private final DeclaredQuery countQuery;
private final Lazy<DeclaredQuery> countQuery;
private final QueryMethodEvaluationContextProvider evaluationContextProvider;
private final SpelExpressionParser parser;
private final QueryParameterSetter.QueryMetadataCache metadataCache = new QueryParameterSetter.QueryMetadataCache();
Expand All @@ -65,8 +63,8 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
* @param queryRewriter must not be {@literal null}.
*/
public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em, String queryString,
@Nullable String countQueryString, QueryRewriter queryRewriter, QueryMethodEvaluationContextProvider evaluationContextProvider,
SpelExpressionParser parser) {
@Nullable String countQueryString, QueryRewriter queryRewriter,
QueryMethodEvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {

super(method, em);

Expand All @@ -79,9 +77,10 @@ public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em, Stri
this.query = new ExpressionBasedStringQuery(queryString, method.getEntityInformation(), parser,
method.isNativeQuery());

DeclaredQuery countQuery = query.deriveCountQuery(countQueryString, method.getCountQueryProjection());
this.countQuery = ExpressionBasedStringQuery.from(countQuery, method.getEntityInformation(), parser,
method.isNativeQuery());
this.countQuery = Lazy.of(() -> {
DeclaredQuery countQuery = query.deriveCountQuery(countQueryString, method.getCountQueryProjection());
return ExpressionBasedStringQuery.from(countQuery, method.getEntityInformation(), parser, method.isNativeQuery());
});

this.parser = parser;
this.queryRewriter = queryRewriter;
Expand Down Expand Up @@ -117,7 +116,7 @@ protected ParameterBinder createBinder() {
@Override
protected Query doCreateCountQuery(JpaParametersParameterAccessor accessor) {

String queryString = countQuery.getQueryString();
String queryString = countQuery.get().getQueryString();
EntityManager em = getEntityManager();

Query query = getQueryMethod().isNativeQuery() //
Expand All @@ -142,7 +141,7 @@ public DeclaredQuery getQuery() {
* @return the countQuery
*/
public DeclaredQuery getCountQuery() {
return countQuery;
return countQuery.get();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ default boolean usesPaging() {

/**
* Return whether the query is a native query of not.
*
*
* @return <code>true</code> if native query otherwise <code>false</code>
*/
default boolean isNativeQuery() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ static String createCountQueryFor(String originalQuery, @Nullable String countPr

String replacement = useVariable ? SIMPLE_COUNT_VALUE : complexCountValue;

if (nativeQuery && (variable.contains(",") || "*".equals(variable))) {
if (variable != null && (nativeQuery && (variable.contains(",") || "*".equals(variable)))) {
replacement = "1";
} else {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ void createsCountQueryForDistinctQueries() {
"select count(distinct u) from User u where u.foo = ?");
}

@Test // GH-2812
void createsCountQueryForDeleteQuery() {

String result = createCountQueryFor("delete from some_table where id in :ids", null, true);

// ح(•̀ж•́)ง †
assertThat(result).isEqualTo("deleteselect count(where) from some_table where id in :ids");
}

@Test
void createsCountQueryForConstructorQueries() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ void findsExistingOrderByIndependentOfCase() {
assertThat(query).endsWithIgnoringCase("ORDER BY p.firstname, p.lastname asc");
}

@Test // GH-2812
void createCountQueryFromDeleteQuery() {

StringQuery query = new StringQuery("delete from some_table where id in :ids", true);

assertThat(getEnhancer(query).createCountQueryFor("p.lastname"))
.isEqualToIgnoringCase("delete from some_table where id in :ids");
}

@Test // DATAJPA-456
void createCountQueryFromTheGivenCountProjection() {

Expand Down