Skip to content

DATAMONGO-1603 - Fix Placeholder not replaced correctly in @Query. #441

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 5 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-mongodb-parent</artifactId>
<version>1.11.0.BUILD-SNAPSHOT</version>
<version>1.11.0.DATAMONGO-1603-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data MongoDB</name>
Expand Down
4 changes: 2 additions & 2 deletions spring-data-mongodb-cross-store/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.11.0.BUILD-SNAPSHOT</version>
<version>1.11.0.DATAMONGO-1603-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down Expand Up @@ -48,7 +48,7 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.11.0.BUILD-SNAPSHOT</version>
<version>1.11.0.DATAMONGO-1603-SNAPSHOT</version>
</dependency>

<dependency>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.11.0.BUILD-SNAPSHOT</version>
<version>1.11.0.DATAMONGO-1603-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-log4j/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.11.0.BUILD-SNAPSHOT</version>
<version>1.11.0.DATAMONGO-1603-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.11.0.BUILD-SNAPSHOT</version>
<version>1.11.0.DATAMONGO-1603-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
/**
* {@link ExpressionEvaluatingParameterBinder} allows to evaluate, convert and bind parameters to placeholders within a
* {@link String}.
*
*
* @author Christoph Strobl
* @author Thomas Darimont
* @author Oliver Gierke
Expand All @@ -59,7 +59,7 @@ class ExpressionEvaluatingParameterBinder {

/**
* Creates new {@link ExpressionEvaluatingParameterBinder}
*
*
* @param expressionParser must not be {@literal null}.
* @param evaluationContextProvider must not be {@literal null}.
*/
Expand All @@ -76,7 +76,7 @@ public ExpressionEvaluatingParameterBinder(SpelExpressionParser expressionParser
/**
* Bind values provided by {@link MongoParameterAccessor} to placeholders in {@literal raw} while considering
* potential conversions and parameter types.
*
*
* @param raw can be {@literal null} or empty.
* @param accessor must not be {@literal null}.
* @param bindingContext must not be {@literal null}.
Expand All @@ -93,7 +93,7 @@ public String bind(String raw, MongoParameterAccessor accessor, BindingContext b

/**
* Replaced the parameter placeholders with the actual parameter values from the given {@link ParameterBinding}s.
*
*
* @param input must not be {@literal null} or empty.
* @param accessor must not be {@literal null}.
* @param bindingContext must not be {@literal null}.
Expand Down Expand Up @@ -126,7 +126,7 @@ private String replacePlaceholders(String input, MongoParameterAccessor accessor
buffer.append(placeholder.getSuffix());
}

if (binding.isQuoted() || placeholder.isQuoted()) {
if (placeholder.isQuoted()) {
postProcessQuotedBinding(buffer, valueForBinding,
!binding.isExpression() ? accessor.getBindableValue(binding.getParameterIndex()) : null,
binding.isExpression());
Expand Down Expand Up @@ -247,7 +247,8 @@ private Pattern createReplacementPattern(List<ParameterBinding> bindings) {

regex.append("|");
regex.append("(" + Pattern.quote(binding.getParameter()) + ")");
regex.append("(\\W?['\"])?"); // potential quotation char (as in { foo : '?0' }).
regex.append("([\\w.]*");
regex.append("(\\W?['\"]|\\w*')?)");
}

return Pattern.compile(regex.substring(1));
Expand All @@ -263,30 +264,34 @@ private Pattern createReplacementPattern(List<ParameterBinding> bindings) {
*/
private Placeholder extractPlaceholder(int parameterIndex, Matcher matcher) {

if (matcher.groupCount() > 1) {

String rawPlaceholder = matcher.group(parameterIndex * 2 + 1);
String suffix = matcher.group(parameterIndex * 2 + 2);
String rawPlaceholder = matcher.group(parameterIndex * 3 + 1);
String suffix = matcher.group(parameterIndex * 3 + 2);

if (!StringUtils.hasText(rawPlaceholder)) {
if (!StringUtils.hasText(rawPlaceholder)) {

rawPlaceholder = matcher.group();
suffix = "" + rawPlaceholder.charAt(rawPlaceholder.length() - 1);
if (QuotedString.endsWithQuote(rawPlaceholder)) {
rawPlaceholder = QuotedString.unquoteSuffix(rawPlaceholder);
rawPlaceholder = matcher.group();
if (rawPlaceholder.matches(".*\\d$")) {
suffix = "";
} else {
int index = rawPlaceholder.replaceAll("[^\\?0-9]*$", "").length() - 1;
if (index > 0 && rawPlaceholder.length() > index) {
suffix = rawPlaceholder.substring(index + 1);
}
}
if (QuotedString.endsWithQuote(rawPlaceholder)) {
rawPlaceholder = rawPlaceholder.substring(0,
rawPlaceholder.length() - (StringUtils.hasText(suffix) ? suffix.length() : 1));
}
}

if (StringUtils.hasText(suffix)) {
if (StringUtils.hasText(suffix)) {

boolean quoted = QuotedString.endsWithQuote(suffix);
boolean quoted = QuotedString.endsWithQuote(suffix);

return Placeholder.of(parameterIndex, rawPlaceholder, quoted,
quoted ? QuotedString.unquoteSuffix(suffix) : suffix);
}
return Placeholder.of(parameterIndex, rawPlaceholder, quoted,
quoted ? QuotedString.unquoteSuffix(suffix) : suffix);
}

return Placeholder.of(parameterIndex, matcher.group(), false, null);
return Placeholder.of(parameterIndex, rawPlaceholder, false, null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2016 the original author or authors.
* Copyright 2011-2017 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.
Expand Down Expand Up @@ -38,7 +38,7 @@

/**
* Query to use a plain JSON String to create the {@link Query} to actually execute.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Thomas Darimont
Expand All @@ -61,7 +61,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {

/**
* Creates a new {@link StringBasedMongoQuery} for the given {@link MongoQueryMethod} and {@link MongoOperations}.
*
*
* @param method must not be {@literal null}.
* @param mongoOperations must not be {@literal null}.
* @param expressionParser must not be {@literal null}.
Expand Down Expand Up @@ -99,7 +99,6 @@ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperati

this.parameterBinder = new ExpressionEvaluatingParameterBinder(expressionParser, evaluationContextProvider);


if (method.hasAnnotatedQuery()) {

org.springframework.data.mongodb.repository.Query queryAnnotation = method.getQueryAnnotation();
Expand Down Expand Up @@ -127,10 +126,10 @@ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperati
@Override
protected Query createQuery(ConvertingParameterAccessor accessor) {

String queryString = parameterBinder.bind(this.query, accessor, new BindingContext(getQueryMethod()
.getParameters(), queryParameterBindings));
String fieldsString = parameterBinder.bind(this.fieldSpec, accessor, new BindingContext(getQueryMethod()
.getParameters(), fieldSpecParameterBindings));
String queryString = parameterBinder.bind(this.query, accessor,
new BindingContext(getQueryMethod().getParameters(), queryParameterBindings));
String fieldsString = parameterBinder.bind(this.fieldSpec, accessor,
new BindingContext(getQueryMethod().getParameters(), fieldSpecParameterBindings));

Query query = new BasicQuery(queryString, fieldsString).with(accessor.getSort());

Expand All @@ -141,7 +140,7 @@ protected Query createQuery(ConvertingParameterAccessor accessor) {
return query;
}

/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery#isCountQuery()
*/
Expand All @@ -168,7 +167,8 @@ protected boolean isDeleteQuery() {
return this.isDeleteQuery;
}

private static boolean hasAmbiguousProjectionFlags(boolean isCountQuery, boolean isExistsQuery, boolean isDeleteQuery) {
private static boolean hasAmbiguousProjectionFlags(boolean isCountQuery, boolean isExistsQuery,
boolean isDeleteQuery) {
return countBooleanValues(isCountQuery, isExistsQuery, isDeleteQuery) > 1;
}

Expand All @@ -188,7 +188,7 @@ private static int countBooleanValues(boolean... values) {

/**
* A parser that extracts the parameter bindings from a given query string.
*
*
* @author Thomas Darimont
*/
private enum ParameterBindingParser {
Expand All @@ -211,7 +211,7 @@ private enum ParameterBindingParser {
/**
* Returns a list of {@link ParameterBinding}s found in the given {@code input} or an
* {@link Collections#emptyList()}.
*
*
* @param input can be {@literal null} or empty.
* @param bindings must not be {@literal null}.
* @return
Expand Down Expand Up @@ -306,7 +306,7 @@ private static void collectParameterReferencesIntoBindings(List<ParameterBinding
int paramIndex = Integer.parseInt(valueMatcher.group(PARAMETER_INDEX_GROUP));

/*
* The pattern is used as a direct parameter replacement, e.g. 'field': ?1,
* The pattern is used as a direct parameter replacement, e.g. 'field': ?1,
* therefore we treat it as not quoted to remain backwards compatible.
*/
boolean quoted = !string.equals(PARAMETER_PREFIX + paramIndex);
Expand Down Expand Up @@ -339,8 +339,7 @@ private static void potentiallyAddBinding(String source, List<ParameterBinding>
while (valueMatcher.find()) {

int paramIndex = Integer.parseInt(valueMatcher.group(PARAMETER_INDEX_GROUP));
boolean quoted = (source.startsWith("'") && source.endsWith("'"))
|| (source.startsWith("\"") && source.endsWith("\""));
boolean quoted = source.startsWith("'") || source.startsWith("\"");

bindings.add(new ParameterBinding(paramIndex, quoted));
}
Expand All @@ -357,7 +356,7 @@ private static int getIndexOfExpressionParameter(String input, int position) {

/**
* A generic parameter binding with name or position information.
*
*
* @author Thomas Darimont
*/
static class ParameterBinding {
Expand All @@ -368,7 +367,7 @@ static class ParameterBinding {

/**
* Creates a new {@link ParameterBinding} with the given {@code parameterIndex} and {@code quoted} information.
*
*
* @param parameterIndex
* @param quoted whether or not the parameter is already quoted.
*/
Expand Down
Loading