committed by
Mark Paluch
parent
878cd8cd4d
commit
5da86f1bf0
@@ -55,7 +55,7 @@ public class HqlParserBenchmarks {
|
||||
OR p.description LIKE "cost overrun"
|
||||
""";
|
||||
|
||||
query = DeclaredQuery.ofJpql(s);
|
||||
query = DeclaredQuery.jpqlQuery(s);
|
||||
enhancer = QueryEnhancerFactory.forQuery(query).create(query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class JSqlParserQueryEnhancerBenchmarks {
|
||||
select SOME_COLUMN from SOME_OTHER_TABLE where REPORTING_DATE = :REPORTING_DATE
|
||||
union select SOME_COLUMN from SOME_OTHER_OTHER_TABLE""";
|
||||
|
||||
enhancer = new JSqlParserQueryEnhancer(DeclaredQuery.ofNative(s));
|
||||
enhancer = new JSqlParserQueryEnhancer(DeclaredQuery.nativeQuery(s));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2025 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 java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
final class BindableQuery implements DeclaredQuery {
|
||||
|
||||
private final DeclaredQuery source;
|
||||
private final String bindableQueryString;
|
||||
private final List<ParameterBinding> bindings;
|
||||
private final boolean usesJdbcStyleParameters;
|
||||
|
||||
public BindableQuery(DeclaredQuery source, String bindableQueryString, List<ParameterBinding> bindings, boolean usesJdbcStyleParameters) {
|
||||
this.source = source;
|
||||
this.bindableQueryString = bindableQueryString;
|
||||
this.bindings = bindings;
|
||||
this.usesJdbcStyleParameters = usesJdbcStyleParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeQuery() {
|
||||
return source.isNativeQuery();
|
||||
}
|
||||
|
||||
boolean hasBindings() {
|
||||
return !bindings.isEmpty();
|
||||
}
|
||||
|
||||
boolean usesJdbcStyleParameters() {
|
||||
return usesJdbcStyleParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return bindableQueryString;
|
||||
}
|
||||
|
||||
public BindableQuery unifyBindings(BindableQuery comparisonQuery) {
|
||||
if (comparisonQuery.hasBindings() && !comparisonQuery.bindings.equals(this.bindings)) {
|
||||
return new BindableQuery(source, bindableQueryString, comparisonQuery.bindings, usesJdbcStyleParameters);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<ParameterBinding> getBindings() {
|
||||
return Collections.unmodifiableList(bindings);
|
||||
}
|
||||
}
|
||||
@@ -23,33 +23,28 @@ package org.springframework.data.jpa.repository.query;
|
||||
* @author Mark Paluch
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public interface DeclaredQuery {
|
||||
public interface DeclaredQuery extends StructuredQuery {
|
||||
|
||||
/**
|
||||
* Creates a DeclaredQuery for a JPQL query.
|
||||
*
|
||||
* @param query the JPQL query string.
|
||||
* @return
|
||||
* @param jpql the JPQL query string.
|
||||
* @return new instance of {@link DeclaredQuery}.
|
||||
*/
|
||||
static DeclaredQuery ofJpql(String query) {
|
||||
return new DefaultDeclaredQuery(query, false);
|
||||
static DeclaredQuery jpqlQuery(String jpql) {
|
||||
return new JpqlQuery(jpql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DeclaredQuery for a native query.
|
||||
*
|
||||
* @param query the native query string.
|
||||
* @return
|
||||
* @param sql the native query string.
|
||||
* @return new instance of {@link DeclaredQuery}.
|
||||
*/
|
||||
static DeclaredQuery ofNative(String query) {
|
||||
return new DefaultDeclaredQuery(query, true);
|
||||
static DeclaredQuery nativeQuery(String sql) {
|
||||
return new NativeQuery(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query string.
|
||||
*/
|
||||
String getQueryString();
|
||||
|
||||
/**
|
||||
* Return whether the query is a native query of not.
|
||||
*
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class DefaultDeclaredQuery implements DeclaredQuery {
|
||||
|
||||
private final String query;
|
||||
private final boolean nativeQuery;
|
||||
|
||||
DefaultDeclaredQuery(String query, boolean nativeQuery) {
|
||||
this.query = query;
|
||||
this.nativeQuery = nativeQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeQuery() {
|
||||
return nativeQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof DefaultDeclaredQuery that)) {
|
||||
return false;
|
||||
}
|
||||
if (nativeQuery != that.nativeQuery) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(query, that.query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(query);
|
||||
result = 31 * result + (nativeQuery ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (isNativeQuery() ? "[native] " : "[JPQL] ") + getQueryString();
|
||||
}
|
||||
}
|
||||
@@ -29,13 +29,13 @@ import org.jspecify.annotations.Nullable;
|
||||
*/
|
||||
public class DefaultQueryEnhancer implements QueryEnhancer {
|
||||
|
||||
private final DeclaredQuery query;
|
||||
private final StructuredQuery query;
|
||||
private final boolean hasConstructorExpression;
|
||||
private final @Nullable String alias;
|
||||
private final String projection;
|
||||
private final Set<String> joinAliases;
|
||||
|
||||
public DefaultQueryEnhancer(DeclaredQuery query) {
|
||||
public DefaultQueryEnhancer(StructuredQuery query) {
|
||||
this.query = query;
|
||||
this.hasConstructorExpression = QueryUtils.hasConstructorExpression(query.getQueryString());
|
||||
this.alias = QueryUtils.detectAlias(query.getQueryString());
|
||||
@@ -60,7 +60,9 @@ public class DefaultQueryEnhancer implements QueryEnhancer {
|
||||
|
||||
@Override
|
||||
public String createCountQueryFor(@Nullable String countProjection) {
|
||||
return QueryUtils.createCountQueryFor(this.query.getQueryString(), countProjection, this.query.isNativeQuery());
|
||||
|
||||
boolean nativeQuery = this.query instanceof DeclaredQuery dc ? dc.isNativeQuery() : true;
|
||||
return QueryUtils.createCountQueryFor(this.query.getQueryString(), countProjection, nativeQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,7 +86,7 @@ public class DefaultQueryEnhancer implements QueryEnhancer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeclaredQuery getQuery() {
|
||||
public StructuredQuery getQuery() {
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,11 @@ class EmptyIntrospectedQuery implements EntityQuery {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParameterBinding> getParameterBindings() {
|
||||
return Collections.emptyList();
|
||||
@@ -82,4 +87,9 @@ class EmptyIntrospectedQuery implements EntityQuery {
|
||||
public boolean usesJdbcStyleParameters() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeclaredQuery getDeclaredQuery() {
|
||||
return DeclaredQuery.nativeQuery("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,13 @@ import java.util.List;
|
||||
* @author Diego Krupitza
|
||||
* @since 2.0.3
|
||||
*/
|
||||
interface IntrospectedQuery extends DeclaredQuery {
|
||||
interface IntrospectedQuery extends StructuredQuery {
|
||||
|
||||
DeclaredQuery getDeclaredQuery();
|
||||
|
||||
default String getQueryString() {
|
||||
return getDeclaredQuery().getQueryString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the underlying query has at least one named parameter.
|
||||
|
||||
@@ -74,7 +74,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class JSqlParserQueryEnhancer implements QueryEnhancer {
|
||||
|
||||
private final DeclaredQuery query;
|
||||
private final StructuredQuery query;
|
||||
private final Statement statement;
|
||||
private final ParsedType parsedType;
|
||||
private final boolean hasConstructorExpression;
|
||||
@@ -87,7 +87,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer {
|
||||
/**
|
||||
* @param query the query we want to enhance. Must not be {@literal null}.
|
||||
*/
|
||||
public JSqlParserQueryEnhancer(DeclaredQuery query) {
|
||||
public JSqlParserQueryEnhancer(StructuredQuery query) {
|
||||
|
||||
this.query = query;
|
||||
this.statement = parseStatement(query.getQueryString(), Statement.class);
|
||||
@@ -339,7 +339,7 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeclaredQuery getQuery() {
|
||||
public StructuredQuery getQuery() {
|
||||
return this.query;
|
||||
}
|
||||
|
||||
@@ -410,8 +410,8 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer {
|
||||
this.query::getQueryString);
|
||||
}
|
||||
|
||||
private static String createCountQueryFor(PlainSelect selectBody, @Nullable String countProjection,
|
||||
@Nullable String primaryAlias) {
|
||||
private static String createCountQueryFor(StructuredQuery query, PlainSelect selectBody,
|
||||
@Nullable String countProjection, @Nullable String primaryAlias) {
|
||||
|
||||
// remove order by
|
||||
selectBody.setOrderByElements(null);
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2025 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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
final class JpqlQuery implements DeclaredQuery {
|
||||
|
||||
private final String jpql;
|
||||
|
||||
JpqlQuery(String jpql) {
|
||||
this.jpql = jpql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return jpql;
|
||||
}
|
||||
}
|
||||
@@ -185,16 +185,11 @@ final class NamedQuery extends AbstractJpaQuery {
|
||||
EntityManager em = getEntityManager();
|
||||
TypedQuery<Long> countQuery;
|
||||
|
||||
String cacheKey;
|
||||
if (namedCountQueryIsPresent) {
|
||||
cacheKey = countQueryName;
|
||||
countQuery = em.createNamedQuery(countQueryName, Long.class);
|
||||
|
||||
} else {
|
||||
|
||||
String countQueryString = entityQuery.get().deriveCountQuery(countProjection).getQueryString();
|
||||
countQueryString = potentiallyRewriteQuery(countQueryString, accessor.getSort(), accessor.getPageable());
|
||||
cacheKey = countQueryString;
|
||||
countQuery = em.createQuery(countQueryString, Long.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2025 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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
final class NativeQuery implements DeclaredQuery {
|
||||
|
||||
private final String sql;
|
||||
|
||||
NativeQuery(String sql) {
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeQuery() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,6 @@ class ParameterBinderFactory {
|
||||
Assert.notNull(parser, "SpelExpressionParser must not be null");
|
||||
Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null");
|
||||
|
||||
List<ParameterBinding> bindings = query.getParameterBindings();
|
||||
QueryParameterSetterFactory expressionSetterFactory = QueryParameterSetterFactory.parsing(parser,
|
||||
evaluationContextProvider);
|
||||
|
||||
@@ -101,7 +100,8 @@ class ParameterBinderFactory {
|
||||
|
||||
boolean usesPaging = query instanceof EntityQuery eq && eq.usesPaging();
|
||||
|
||||
return new ParameterBinder(parameters, createSetters(bindings, query, expressionSetterFactory, basicSetterFactory),
|
||||
// TODO: lets maybe obtain the bindable query and pass that on to create the setters?
|
||||
return new ParameterBinder(parameters, createSetters(query.getParameterBindings(), query, expressionSetterFactory, basicSetterFactory),
|
||||
!usesPaging);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public interface QueryEnhancer {
|
||||
*
|
||||
* @return non-null {@link DeclaredQuery} that wraps the query.
|
||||
*/
|
||||
DeclaredQuery getQuery();
|
||||
StructuredQuery getQuery();
|
||||
|
||||
/**
|
||||
* Adds {@literal order by} clause to the JPQL query. Uses the first alias to bind the sorting property to.
|
||||
|
||||
@@ -57,7 +57,7 @@ public class QueryEnhancerFactories {
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryEnhancer create(DeclaredQuery query) {
|
||||
public QueryEnhancer create(StructuredQuery query) {
|
||||
return new DefaultQueryEnhancer(query);
|
||||
}
|
||||
},
|
||||
@@ -69,7 +69,7 @@ public class QueryEnhancerFactories {
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryEnhancer create(DeclaredQuery query) {
|
||||
public QueryEnhancer create(StructuredQuery query) {
|
||||
if (jSqlParserPresent) {
|
||||
return new JSqlParserQueryEnhancer(query);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public class QueryEnhancerFactories {
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryEnhancer create(DeclaredQuery query) {
|
||||
public QueryEnhancer create(StructuredQuery query) {
|
||||
return JpaQueryEnhancer.forHql(query.getQueryString());
|
||||
}
|
||||
},
|
||||
@@ -96,7 +96,7 @@ public class QueryEnhancerFactories {
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryEnhancer create(DeclaredQuery query) {
|
||||
public QueryEnhancer create(StructuredQuery query) {
|
||||
return JpaQueryEnhancer.forEql(query.getQueryString());
|
||||
}
|
||||
},
|
||||
@@ -107,7 +107,7 @@ public class QueryEnhancerFactories {
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryEnhancer create(DeclaredQuery query) {
|
||||
public QueryEnhancer create(StructuredQuery query) {
|
||||
return JpaQueryEnhancer.forJpql(query.getQueryString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public interface QueryEnhancerFactory {
|
||||
* @param query the query to be enhanced and introspected.
|
||||
* @return
|
||||
*/
|
||||
QueryEnhancer create(DeclaredQuery query);
|
||||
QueryEnhancer create(StructuredQuery query);
|
||||
|
||||
/**
|
||||
* Creates a new {@link QueryEnhancerFactory} for the given {@link DeclaredQuery}.
|
||||
|
||||
@@ -66,7 +66,7 @@ public interface QueryEnhancerSelector {
|
||||
private final QueryEnhancerFactory nativeQuery;
|
||||
private final QueryEnhancerFactory jpql;
|
||||
|
||||
public DefaultQueryEnhancerSelector() {
|
||||
DefaultQueryEnhancerSelector() {
|
||||
this(DEFAULT_NATIVE, DEFAULT_JPQL);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,11 +64,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class StringQuery implements EntityQuery {
|
||||
|
||||
private final String query;
|
||||
private final List<ParameterBinding> bindings;
|
||||
private final BindableQuery bindableQuery;
|
||||
private final boolean containsPageableInSpel;
|
||||
private final boolean usesJdbcStyleParameters;
|
||||
private final boolean isNative;
|
||||
private final QueryEnhancerFactory queryEnhancerFactory;
|
||||
private final QueryEnhancer queryEnhancer;
|
||||
private final boolean hasNamedParameters;
|
||||
@@ -78,7 +75,7 @@ class StringQuery implements EntityQuery {
|
||||
*
|
||||
* @param query must not be {@literal null} or empty.
|
||||
*/
|
||||
public StringQuery(String query, boolean isNative) {
|
||||
StringQuery(String query, boolean isNative) {
|
||||
this(query, isNative, QueryEnhancerSelector.DEFAULT_SELECTOR, it -> {});
|
||||
}
|
||||
|
||||
@@ -91,29 +88,15 @@ class StringQuery implements EntityQuery {
|
||||
|
||||
Assert.hasText(query, "Query must not be null or empty");
|
||||
|
||||
this.isNative = isNative;
|
||||
this.bindings = new ArrayList<>();
|
||||
this.containsPageableInSpel = query.contains("#pageable");
|
||||
this.queryEnhancerFactory = factory;
|
||||
|
||||
Metadata queryMeta = new Metadata();
|
||||
this.query = ParameterBindingParser.INSTANCE.parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(query,
|
||||
this.bindings, queryMeta);
|
||||
DeclaredQuery source = isNative ? DeclaredQuery.nativeQuery(query) : DeclaredQuery.jpqlQuery(query);
|
||||
this.bindableQuery = ParameterBindingParser.INSTANCE.parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(source);
|
||||
|
||||
this.usesJdbcStyleParameters = queryMeta.usesJdbcStyleParameters;
|
||||
this.queryEnhancer = factory.create(this);
|
||||
|
||||
parameterPostProcessor.accept(this.bindings);
|
||||
|
||||
boolean hasNamedParameters = false;
|
||||
for (ParameterBinding parameterBinding : getParameterBindings()) {
|
||||
if (parameterBinding.getIdentifier().hasName() && parameterBinding.getOrigin().isMethodArgument()) {
|
||||
hasNamedParameters = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.hasNamedParameters = hasNamedParameters;
|
||||
parameterPostProcessor.accept(this.bindableQuery.getBindings());
|
||||
this.queryEnhancer = factory.create(this.bindableQuery);
|
||||
this.hasNamedParameters = containsNamedParameter(this.bindableQuery.getBindings());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,29 +108,32 @@ class StringQuery implements EntityQuery {
|
||||
|
||||
Assert.hasText(query, "Query must not be null or empty");
|
||||
|
||||
this.isNative = isNative;
|
||||
this.bindings = new ArrayList<>();
|
||||
this.containsPageableInSpel = query.contains("#pageable");
|
||||
DeclaredQuery source = isNative ? DeclaredQuery.nativeQuery(query) : DeclaredQuery.jpqlQuery(query);
|
||||
|
||||
Metadata queryMeta = new Metadata();
|
||||
this.query = ParameterBindingParser.INSTANCE.parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(query,
|
||||
this.bindings, queryMeta);
|
||||
this.bindableQuery = ParameterBindingParser.INSTANCE.parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(source);
|
||||
|
||||
this.usesJdbcStyleParameters = queryMeta.usesJdbcStyleParameters;
|
||||
this.queryEnhancerFactory = selector.select(this);
|
||||
this.queryEnhancer = queryEnhancerFactory.create(this);
|
||||
|
||||
parameterPostProcessor.accept(this.bindings);
|
||||
|
||||
boolean hasNamedParameters = false;
|
||||
for (ParameterBinding parameterBinding : getParameterBindings()) {
|
||||
if (parameterBinding.getIdentifier().hasName() && parameterBinding.getOrigin().isMethodArgument()) {
|
||||
hasNamedParameters = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.queryEnhancerFactory = selector.select(source);
|
||||
this.queryEnhancer = queryEnhancerFactory.create(this.bindableQuery);
|
||||
parameterPostProcessor.accept(this.bindableQuery.getBindings());
|
||||
this.hasNamedParameters = containsNamedParameter(this.bindableQuery.getBindings());
|
||||
}
|
||||
|
||||
/**
|
||||
* internal copy constructor
|
||||
*
|
||||
* @param bindableQuery
|
||||
* @param factory
|
||||
* @param enhancer
|
||||
* @param hasNamedParameters
|
||||
* @param containsPageableInSpel
|
||||
*/
|
||||
private StringQuery(BindableQuery bindableQuery, QueryEnhancerFactory factory, QueryEnhancer enhancer, boolean hasNamedParameters, boolean containsPageableInSpel) {
|
||||
this.bindableQuery = bindableQuery;
|
||||
this.queryEnhancerFactory = factory;
|
||||
this.queryEnhancer = enhancer;
|
||||
this.hasNamedParameters = hasNamedParameters;
|
||||
this.containsPageableInSpel = containsPageableInSpel;
|
||||
}
|
||||
|
||||
QueryEnhancer getQueryEnhancer() {
|
||||
@@ -158,16 +144,21 @@ class StringQuery implements EntityQuery {
|
||||
* Returns whether we have found some like bindings.
|
||||
*/
|
||||
boolean hasParameterBindings() {
|
||||
return !bindings.isEmpty();
|
||||
return this.bindableQuery.hasBindings();
|
||||
}
|
||||
|
||||
String getProjection() {
|
||||
return this.queryEnhancer.getProjection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return bindableQuery.getQueryString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParameterBinding> getParameterBindings() {
|
||||
return bindings;
|
||||
return this.bindableQuery.getBindings();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,14 +168,14 @@ class StringQuery implements EntityQuery {
|
||||
// JPA parameter markers and not the original expressions anymore.
|
||||
|
||||
return new StringQuery(this.queryEnhancer.createCountQueryFor(countQueryProjection), //
|
||||
this.isNative, queryEnhancerFactory, derivedBindings -> {
|
||||
this.bindableQuery.isNativeQuery(), queryEnhancerFactory, derivedBindings -> {
|
||||
|
||||
// need to copy expression bindings from the declared to the derived query as JPQL query derivation only sees
|
||||
// JPA
|
||||
// parameter markers and not the original expressions anymore.
|
||||
if (this.hasParameterBindings() && !this.getParameterBindings().equals(derivedBindings)) {
|
||||
|
||||
for (ParameterBinding binding : bindings) {
|
||||
for (ParameterBinding binding : getParameterBindings()) {
|
||||
|
||||
Predicate<ParameterBinding> identifier = binding::bindsTo;
|
||||
Predicate<ParameterBinding> notCompatible = Predicate.not(binding::isCompatibleWith);
|
||||
@@ -206,12 +197,7 @@ class StringQuery implements EntityQuery {
|
||||
|
||||
@Override
|
||||
public boolean usesJdbcStyleParameters() {
|
||||
return usesJdbcStyleParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return query;
|
||||
return bindableQuery.usesJdbcStyleParameters();
|
||||
}
|
||||
|
||||
public @Nullable String getAlias() {
|
||||
@@ -239,8 +225,17 @@ class StringQuery implements EntityQuery {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeQuery() {
|
||||
return isNative;
|
||||
public DeclaredQuery getDeclaredQuery() {
|
||||
return bindableQuery;
|
||||
}
|
||||
|
||||
private static boolean containsNamedParameter(List<ParameterBinding> bindings) {
|
||||
for (ParameterBinding parameterBinding : bindings) {
|
||||
if (parameterBinding.getIdentifier().hasName() && parameterBinding.getOrigin().isMethodArgument()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,8 +371,7 @@ class StringQuery implements EntityQuery {
|
||||
* Parses {@link ParameterBinding} instances from the given query and adds them to the registered bindings. Returns
|
||||
* the cleaned up query.
|
||||
*/
|
||||
String parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(String query, List<ParameterBinding> bindings,
|
||||
Metadata queryMeta) {
|
||||
BindableQuery parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(DeclaredQuery query) {
|
||||
|
||||
IndexedParameterLabels parameterLabels = new IndexedParameterLabels(findParameterIndices(query));
|
||||
boolean parametersShouldBeAccessedByIndex = parameterLabels.hasLabels();
|
||||
@@ -385,11 +379,11 @@ class StringQuery implements EntityQuery {
|
||||
/*
|
||||
* Prefer indexed access over named parameters if only SpEL Expression parameters are present.
|
||||
*/
|
||||
if (!parametersShouldBeAccessedByIndex && query.contains("?#{")) {
|
||||
if (!parametersShouldBeAccessedByIndex && query.getQueryString().contains("?#{")) {
|
||||
parametersShouldBeAccessedByIndex = true;
|
||||
}
|
||||
|
||||
ValueExpressionQueryRewriter.ParsedQuery parsedQuery = createSpelExtractor(query,
|
||||
ValueExpressionQueryRewriter.ParsedQuery parsedQuery = createSpelExtractor(query.getQueryString(),
|
||||
parametersShouldBeAccessedByIndex, parameterLabels);
|
||||
|
||||
String resultingQuery = parsedQuery.getQueryString();
|
||||
@@ -412,14 +406,14 @@ class StringQuery implements EntityQuery {
|
||||
|
||||
String match = matcher.group(0);
|
||||
if (JDBC_STYLE_PARAM.matcher(match).find()) {
|
||||
queryMeta.usesJdbcStyleParameters = true;
|
||||
jdbcStyle = true;
|
||||
}
|
||||
|
||||
if (NUMBERED_STYLE_PARAM.matcher(match).find() || NAMED_STYLE_PARAM.matcher(match).find()) {
|
||||
usesJpaStyleParameters = true;
|
||||
}
|
||||
|
||||
if (usesJpaStyleParameters && queryMeta.usesJdbcStyleParameters) {
|
||||
if (usesJpaStyleParameters && jdbcStyle) {
|
||||
throw new IllegalArgumentException("Mixing of ? parameters and other forms like ?1 is not supported");
|
||||
}
|
||||
|
||||
@@ -467,7 +461,7 @@ class StringQuery implements EntityQuery {
|
||||
}
|
||||
|
||||
replacement = targetBinding.hasName() ? ":" + targetBinding.getName()
|
||||
: ((!usesJpaStyleParameters && queryMeta.usesJdbcStyleParameters) ? "?"
|
||||
: ((!usesJpaStyleParameters && jdbcStyle) ? "?"
|
||||
: "?" + targetBinding.getPosition());
|
||||
String result;
|
||||
String substring = matcher.group(2);
|
||||
@@ -484,7 +478,7 @@ class StringQuery implements EntityQuery {
|
||||
resultingQuery = result;
|
||||
}
|
||||
|
||||
return resultingQuery;
|
||||
return new BindableQuery(query, resultingQuery, bindings, jdbcStyle);
|
||||
}
|
||||
|
||||
private static ValueExpressionQueryRewriter.ParsedQuery createSpelExtractor(String queryWithSpel,
|
||||
@@ -592,9 +586,7 @@ class StringQuery implements EntityQuery {
|
||||
}
|
||||
}
|
||||
|
||||
static class Metadata {
|
||||
private boolean usesJdbcStyleParameters = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility to create unique parameter bindings for LIKE that refer to the same underlying method parameter but are
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2025 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;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public interface StructuredQuery {
|
||||
|
||||
String getQueryString();
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class DefaultQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
@Test // GH-3546
|
||||
void shouldApplySorting() {
|
||||
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.ofNative("SELECT e FROM Employee e"));
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.nativeQuery("SELECT e FROM Employee e"));
|
||||
|
||||
String sql = enhancer.applySorting(Sort.by("foo", "bar"));
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ class ExpressionBasedStringQueryUnitTests {
|
||||
+ "AND (n.updatedAt >= ?#{#networkRequest.updatedTime.startDateTime}) AND (n.updatedAt <=?#{#networkRequest.updatedTime.endDateTime})",
|
||||
metadata, CONFIG.getValueExpressionDelegate().getValueExpressionParser(), false, CONFIG.getSelector());
|
||||
|
||||
assertThat(query.isNativeQuery()).isFalse();
|
||||
assertThat(query.getDeclaredQuery().isNativeQuery()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -120,7 +120,7 @@ class ExpressionBasedStringQueryUnitTests {
|
||||
StringQuery query = new ExpressionBasedStringQuery("select n from #{#entityName} n", metadata,
|
||||
CONFIG.getValueExpressionDelegate().getValueExpressionParser(), true, CONFIG.getSelector());
|
||||
|
||||
assertThat(query.isNativeQuery()).isFalse();
|
||||
assertThat(query.getDeclaredQuery().isNativeQuery()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,7 +129,7 @@ class ExpressionBasedStringQueryUnitTests {
|
||||
StringQuery query = new ExpressionBasedStringQuery("select u from User u", metadata,
|
||||
CONFIG.getValueExpressionDelegate().getValueExpressionParser(), true, CONFIG.getSelector());
|
||||
|
||||
assertThat(query.isNativeQuery()).isTrue();
|
||||
assertThat(query.getDeclaredQuery().isNativeQuery()).isTrue();
|
||||
}
|
||||
|
||||
@Test // GH-3041
|
||||
|
||||
@@ -46,7 +46,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
@Test // GH-3546
|
||||
void shouldApplySorting() {
|
||||
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.ofJpql("SELECT e FROM Employee e"));
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.jpqlQuery("SELECT e FROM Employee e"));
|
||||
|
||||
String sql = enhancer.applySorting(Sort.by("foo", "bar"));
|
||||
|
||||
@@ -56,7 +56,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
@Test // GH-3886
|
||||
void shouldApplySortingWithNullsPrecedence() {
|
||||
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.of("SELECT e FROM Employee e", true));
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.jpqlQuery("SELECT e FROM Employee e"));
|
||||
|
||||
String sql = enhancer.rewrite(new DefaultQueryRewriteInformation(
|
||||
Sort.by(Sort.Order.asc("foo").with(Sort.NullHandling.NULLS_LAST),
|
||||
@@ -69,7 +69,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
@Test // GH-3707
|
||||
void countQueriesShouldConsiderPrimaryTableAlias() {
|
||||
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.ofNative("""
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.nativeQuery("""
|
||||
SELECT DISTINCT a.*, b.b1
|
||||
FROM TableA a
|
||||
JOIN TableB b ON a.b = b.b
|
||||
@@ -98,7 +98,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
+ "select SOME_COLUMN from SOME_OTHER_TABLE where REPORTING_DATE = :REPORTING_DATE";
|
||||
|
||||
StringQuery stringQuery = new StringQuery(setQuery, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(stringQuery.getAlias()).isNullOrEmpty();
|
||||
assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
|
||||
@@ -121,7 +121,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
+ "union select SOME_COLUMN from SOME_OTHER_OTHER_TABLE";
|
||||
|
||||
StringQuery stringQuery = new StringQuery(setQuery, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(stringQuery.getAlias()).isNullOrEmpty();
|
||||
assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("SOME_COLUMN");
|
||||
@@ -148,7 +148,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
+ "\t;";
|
||||
|
||||
StringQuery stringQuery = new StringQuery(setQuery, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(stringQuery.getAlias()).isNullOrEmpty();
|
||||
assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("CustomerID");
|
||||
@@ -168,7 +168,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
String setQuery = "VALUES (1, 2, 'test')";
|
||||
|
||||
StringQuery stringQuery = new StringQuery(setQuery, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(stringQuery.getAlias()).isNullOrEmpty();
|
||||
assertThat(stringQuery.getProjection()).isNullOrEmpty();
|
||||
@@ -189,7 +189,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
+ "select day, value from sample_data as a";
|
||||
|
||||
StringQuery stringQuery = new StringQuery(setQuery, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(stringQuery.getAlias()).isEqualToIgnoringCase("a");
|
||||
assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("day, value");
|
||||
@@ -212,7 +212,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
+ "select day, value from sample_data as a";
|
||||
|
||||
StringQuery stringQuery = new StringQuery(setQuery, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(stringQuery.getAlias()).isEqualToIgnoringCase("a");
|
||||
assertThat(stringQuery.getProjection()).isEqualToIgnoringCase("day, value");
|
||||
@@ -232,7 +232,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
void truncateStatementShouldWork() {
|
||||
|
||||
StringQuery stringQuery = new StringQuery("TRUNCATE TABLE foo", true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(stringQuery.getAlias()).isNull();
|
||||
assertThat(stringQuery.getProjection()).isEmpty();
|
||||
@@ -250,7 +250,7 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests {
|
||||
void mergeStatementWorksWithJSqlParser(String query, String alias) {
|
||||
|
||||
StringQuery stringQuery = new StringQuery(query, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery);
|
||||
|
||||
assertThat(queryEnhancer.detectAlias()).isEqualTo(alias);
|
||||
assertThat(QueryUtils.detectAlias(query)).isNull();
|
||||
|
||||
@@ -89,7 +89,7 @@ class NamedOrIndexedQueryParameterSetterUnitTests {
|
||||
|
||||
softly
|
||||
.assertThatThrownBy(
|
||||
() -> setter.setParameter(BindableQuery.from(query), methodArguments, STRICT)) //
|
||||
() -> setter.setParameter(QueryParameterSetter.BindableQuery.from(query), methodArguments, STRICT)) //
|
||||
.describedAs("p-type: %s, p-name: %s, p-position: %s, temporal: %s", //
|
||||
parameter.getClass(), //
|
||||
parameter.getName(), //
|
||||
@@ -118,7 +118,7 @@ class NamedOrIndexedQueryParameterSetterUnitTests {
|
||||
|
||||
softly
|
||||
.assertThatCode(
|
||||
() -> setter.setParameter(BindableQuery.from(query), methodArguments, LENIENT)) //
|
||||
() -> setter.setParameter(QueryParameterSetter.BindableQuery.from(query), methodArguments, LENIENT)) //
|
||||
.describedAs("p-type: %s, p-name: %s, p-position: %s, temporal: %s", //
|
||||
parameter.getClass(), //
|
||||
parameter.getName(), //
|
||||
@@ -149,7 +149,7 @@ class NamedOrIndexedQueryParameterSetterUnitTests {
|
||||
temporalType //
|
||||
);
|
||||
|
||||
setter.setParameter(BindableQuery.from(query), methodArguments, LENIENT);
|
||||
setter.setParameter(QueryParameterSetter.BindableQuery.from(query), methodArguments, LENIENT);
|
||||
|
||||
if (temporalType == null) {
|
||||
verify(query).setParameter(eq(11), any(Date.class));
|
||||
@@ -179,7 +179,7 @@ class NamedOrIndexedQueryParameterSetterUnitTests {
|
||||
temporalType //
|
||||
);
|
||||
|
||||
setter.setParameter(BindableQuery.from(query), methodArguments, LENIENT);
|
||||
setter.setParameter(QueryParameterSetter.BindableQuery.from(query), methodArguments, LENIENT);
|
||||
|
||||
if (temporalType == null) {
|
||||
verify(query, never()).setParameter(anyInt(), any(Date.class));
|
||||
|
||||
@@ -34,7 +34,7 @@ class QueryEnhancerFactoryUnitTests {
|
||||
|
||||
StringQuery query = new StringQuery("select new com.example.User(u.firstname) from User u", false);
|
||||
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(query).create(query);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(query.getDeclaredQuery()).create(query);
|
||||
|
||||
assertThat(queryEnhancer) //
|
||||
.isInstanceOf(JpaQueryEnhancer.class);
|
||||
@@ -49,7 +49,7 @@ class QueryEnhancerFactoryUnitTests {
|
||||
|
||||
StringQuery query = new StringQuery("select * from User", true);
|
||||
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(query).create(query);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(query.getDeclaredQuery()).create(query);
|
||||
|
||||
assertThat(queryEnhancer) //
|
||||
.isInstanceOf(JSqlParserQueryEnhancer.class);
|
||||
|
||||
@@ -35,7 +35,7 @@ abstract class QueryEnhancerTckTests {
|
||||
@MethodSource("nativeCountQueries") // GH-2773
|
||||
void shouldDeriveNativeCountQuery(String query, String expected) {
|
||||
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.ofNative(query));
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.nativeQuery(query));
|
||||
String countQueryFor = enhancer.createCountQueryFor();
|
||||
|
||||
// lenient cleanup to allow for rendering variance
|
||||
@@ -119,7 +119,7 @@ abstract class QueryEnhancerTckTests {
|
||||
@MethodSource("jpqlCountQueries")
|
||||
void shouldDeriveJpqlCountQuery(String query, String expected) {
|
||||
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.ofJpql(query));
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.jpqlQuery(query));
|
||||
String countQueryFor = enhancer.createCountQueryFor(null);
|
||||
|
||||
assertThat(countQueryFor).isEqualToIgnoringCase(expected);
|
||||
@@ -178,7 +178,7 @@ abstract class QueryEnhancerTckTests {
|
||||
@MethodSource("nativeQueriesWithVariables")
|
||||
void shouldDeriveNativeCountQueryWithVariable(String query, String expected) {
|
||||
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.ofNative(query));
|
||||
QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.nativeQuery(query));
|
||||
String countQueryFor = enhancer.createCountQueryFor();
|
||||
|
||||
assertThat(countQueryFor).isEqualToIgnoringCase(expected);
|
||||
@@ -205,7 +205,7 @@ abstract class QueryEnhancerTckTests {
|
||||
|
||||
StringQuery query = new StringQuery("select x, frommage, y from t", true);
|
||||
|
||||
assertThat(createQueryEnhancer(query).getProjection()).isEqualTo("x, frommage, y");
|
||||
assertThat(createQueryEnhancer(query.getDeclaredQuery()).getProjection()).isEqualTo("x, frommage, y");
|
||||
}
|
||||
|
||||
abstract QueryEnhancer createQueryEnhancer(DeclaredQuery query);
|
||||
|
||||
@@ -632,7 +632,7 @@ class QueryEnhancerUnitTests {
|
||||
assertThat(modiQuery.hasConstructorExpression()).isEqualTo(constructorExpressionNotConsideringQueryType);
|
||||
|
||||
assertThat(countQueryForNotConsiderQueryType).isEqualToIgnoringCase(modifyingQuery);
|
||||
assertThat(QueryEnhancerFactory.forQuery(modiQuery).create(modiQuery).createCountQueryFor())
|
||||
assertThat(QueryEnhancerFactory.forQuery(modiQuery.getDeclaredQuery()).create(modiQuery.getDeclaredQuery()).createCountQueryFor())
|
||||
.isEqualToIgnoringCase(modifyingQuery);
|
||||
}
|
||||
|
||||
@@ -641,7 +641,7 @@ class QueryEnhancerUnitTests {
|
||||
void insertStatementIsProcessedSameAsDefault(String insertQuery) {
|
||||
|
||||
StringQuery stringQuery = new StringQuery(insertQuery, true);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery).create(stringQuery);
|
||||
QueryEnhancer queryEnhancer = QueryEnhancerFactory.forQuery(stringQuery.getDeclaredQuery()).create(stringQuery.getDeclaredQuery());
|
||||
|
||||
Sort sorting = Sort.by("day").descending();
|
||||
|
||||
@@ -697,7 +697,7 @@ class QueryEnhancerUnitTests {
|
||||
}
|
||||
|
||||
private static QueryEnhancer getEnhancer(IntrospectedQuery query) {
|
||||
return QueryEnhancerFactory.forQuery(query).create(query);
|
||||
return QueryEnhancerFactory.forQuery(query.getDeclaredQuery()).create(query.getDeclaredQuery());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,6 +28,7 @@ import org.springframework.data.jpa.repository.query.ParameterBinding.InParamete
|
||||
import org.springframework.data.jpa.repository.query.ParameterBinding.LikeParameterBinding;
|
||||
import org.springframework.data.jpa.repository.query.ParameterBinding.MethodInvocationArgument;
|
||||
import org.springframework.data.jpa.repository.query.ParameterBinding.ParameterOrigin;
|
||||
import org.springframework.data.jpa.repository.query.StringQuery.ParameterBindingParser;
|
||||
import org.springframework.data.repository.query.parser.Part.Type;
|
||||
|
||||
/**
|
||||
@@ -926,11 +926,10 @@ class StringQueryUnitTests {
|
||||
|
||||
private void checkHasNamedParameter(String query, boolean expected, String label) {
|
||||
|
||||
List<ParameterBinding> bindings = new ArrayList<>();
|
||||
StringQuery.ParameterBindingParser.INSTANCE.parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(query,
|
||||
bindings, new StringQuery.Metadata());
|
||||
DeclaredQuery source = nativeQuery ? DeclaredQuery.nativeQuery(query) : DeclaredQuery.jpqlQuery(query);
|
||||
BindableQuery bindableQuery = ParameterBindingParser.INSTANCE.parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(source);
|
||||
|
||||
assertThat(bindings.stream().anyMatch(it -> it.getIdentifier().hasName())) //
|
||||
assertThat(bindableQuery.getBindings().stream().anyMatch(it -> it.getIdentifier().hasName())) //
|
||||
.describedAs(String.format("<%s> (%s)", query, label)) //
|
||||
.isEqualTo(expected);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user