|
|
|
@ -38,6 +38,7 @@ import com.mongodb.util.JSON; |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Christoph Strobl |
|
|
|
* @author Christoph Strobl |
|
|
|
* @author Thomas Darimont |
|
|
|
* @author Thomas Darimont |
|
|
|
|
|
|
|
* @author Oliver Gierke |
|
|
|
* @since 1.9 |
|
|
|
* @since 1.9 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
class ExpressionEvaluatingParameterBinder { |
|
|
|
class ExpressionEvaluatingParameterBinder { |
|
|
|
@ -62,13 +63,13 @@ class ExpressionEvaluatingParameterBinder { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Bind values provided by {@link MongoParameterAccessor} to placeholders in {@literal raw} while consisdering |
|
|
|
* Bind values provided by {@link MongoParameterAccessor} to placeholders in {@literal raw} while considering |
|
|
|
* potential conversions and parameter types. |
|
|
|
* potential conversions and parameter types. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param raw |
|
|
|
* @param raw can be {@literal null} or empty. |
|
|
|
* @param accessor |
|
|
|
* @param accessor must not be {@literal null}. |
|
|
|
* @param bindingContext |
|
|
|
* @param bindingContext must not be {@literal null}. |
|
|
|
* @return {@literal null} if given {@literal raw} value is empty. |
|
|
|
* @return {@literal null} if given {@code raw} value is empty. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public String bind(String raw, MongoParameterAccessor accessor, BindingContext bindingContext) { |
|
|
|
public String bind(String raw, MongoParameterAccessor accessor, BindingContext bindingContext) { |
|
|
|
|
|
|
|
|
|
|
|
@ -80,12 +81,11 @@ class ExpressionEvaluatingParameterBinder { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Replaced the parameter place-holders with the actual parameter values from the given {@link ParameterBinding}s. |
|
|
|
* Replaced the parameter placeholders with the actual parameter values from the given {@link ParameterBinding}s. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param input |
|
|
|
* @param input must not be {@literal null} or empty. |
|
|
|
* @param accessor |
|
|
|
* @param accessor must not be {@literal null}. |
|
|
|
* @param parameters |
|
|
|
* @param bindings must not be {@literal null}. |
|
|
|
* @param bindings |
|
|
|
|
|
|
|
* @return |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private String replacePlaceholders(String input, MongoParameterAccessor accessor, BindingContext bindingContext) { |
|
|
|
private String replacePlaceholders(String input, MongoParameterAccessor accessor, BindingContext bindingContext) { |
|
|
|
@ -95,7 +95,6 @@ class ExpressionEvaluatingParameterBinder { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
boolean isCompletlyParameterizedQuery = input.matches("^\\?\\d+$"); |
|
|
|
boolean isCompletlyParameterizedQuery = input.matches("^\\?\\d+$"); |
|
|
|
|
|
|
|
|
|
|
|
StringBuilder result = new StringBuilder(input); |
|
|
|
StringBuilder result = new StringBuilder(input); |
|
|
|
|
|
|
|
|
|
|
|
for (ParameterBinding binding : bindingContext.getBindings()) { |
|
|
|
for (ParameterBinding binding : bindingContext.getBindings()) { |
|
|
|
@ -103,32 +102,31 @@ class ExpressionEvaluatingParameterBinder { |
|
|
|
String parameter = binding.getParameter(); |
|
|
|
String parameter = binding.getParameter(); |
|
|
|
int idx = result.indexOf(parameter); |
|
|
|
int idx = result.indexOf(parameter); |
|
|
|
|
|
|
|
|
|
|
|
if (idx != -1) { |
|
|
|
if (idx == -1) { |
|
|
|
String valueForBinding = getParameterValueForBinding(accessor, bindingContext.getParameters(), binding); |
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// if the value to bind is an object literal we need to remove the quoting around
|
|
|
|
String valueForBinding = getParameterValueForBinding(accessor, bindingContext.getParameters(), binding); |
|
|
|
// the expression insertion point.
|
|
|
|
|
|
|
|
boolean shouldPotentiallyRemoveQuotes = valueForBinding.startsWith("{") && !isCompletlyParameterizedQuery; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int start = idx; |
|
|
|
int start = idx; |
|
|
|
int end = idx + parameter.length(); |
|
|
|
int end = idx + parameter.length(); |
|
|
|
|
|
|
|
|
|
|
|
if (shouldPotentiallyRemoveQuotes) { |
|
|
|
// If the value to bind is an object literal we need to remove the quoting around the expression insertion point.
|
|
|
|
|
|
|
|
if (valueForBinding.startsWith("{") && !isCompletlyParameterizedQuery) { |
|
|
|
|
|
|
|
|
|
|
|
// is the insertion point actually surrounded by quotes?
|
|
|
|
// Is the insertion point actually surrounded by quotes?
|
|
|
|
char beforeStart = result.charAt(start - 1); |
|
|
|
char beforeStart = result.charAt(start - 1); |
|
|
|
char afterEnd = result.charAt(end); |
|
|
|
char afterEnd = result.charAt(end); |
|
|
|
|
|
|
|
|
|
|
|
if ((beforeStart == '\'' || beforeStart == '"') && (afterEnd == '\'' || afterEnd == '"')) { |
|
|
|
if ((beforeStart == '\'' || beforeStart == '"') && (afterEnd == '\'' || afterEnd == '"')) { |
|
|
|
|
|
|
|
|
|
|
|
// skip preceeding and following quote
|
|
|
|
// Skip preceding and following quote
|
|
|
|
start -= 1; |
|
|
|
start -= 1; |
|
|
|
end += 1; |
|
|
|
end += 1; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
result.replace(start, end, valueForBinding); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.replace(start, end, valueForBinding); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result.toString(); |
|
|
|
return result.toString(); |
|
|
|
@ -137,16 +135,17 @@ class ExpressionEvaluatingParameterBinder { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the serialized value to be used for the given {@link ParameterBinding}. |
|
|
|
* Returns the serialized value to be used for the given {@link ParameterBinding}. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param accessor |
|
|
|
* @param accessor must not be {@literal null}. |
|
|
|
* @param parameters |
|
|
|
* @param parameters |
|
|
|
* @param binding |
|
|
|
* @param binding must not be {@literal null}. |
|
|
|
* @return |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private String getParameterValueForBinding(MongoParameterAccessor accessor, MongoParameters parameters, |
|
|
|
private String getParameterValueForBinding(MongoParameterAccessor accessor, MongoParameters parameters, |
|
|
|
ParameterBinding binding) { |
|
|
|
ParameterBinding binding) { |
|
|
|
|
|
|
|
|
|
|
|
Object value = binding.isExpression() ? evaluateExpression(binding.getExpression(), parameters, |
|
|
|
Object value = binding.isExpression() |
|
|
|
accessor.getValues()) : accessor.getBindableValue(binding.getParameterIndex()); |
|
|
|
? evaluateExpression(binding.getExpression(), parameters, accessor.getValues()) |
|
|
|
|
|
|
|
: accessor.getBindableValue(binding.getParameterIndex()); |
|
|
|
|
|
|
|
|
|
|
|
if (value instanceof String && binding.isQuoted()) { |
|
|
|
if (value instanceof String && binding.isQuoted()) { |
|
|
|
return (String) value; |
|
|
|
return (String) value; |
|
|
|
@ -155,9 +154,11 @@ class ExpressionEvaluatingParameterBinder { |
|
|
|
if (value instanceof byte[]) { |
|
|
|
if (value instanceof byte[]) { |
|
|
|
|
|
|
|
|
|
|
|
String base64representation = DatatypeConverter.printBase64Binary((byte[]) value); |
|
|
|
String base64representation = DatatypeConverter.printBase64Binary((byte[]) value); |
|
|
|
|
|
|
|
|
|
|
|
if (!binding.isQuoted()) { |
|
|
|
if (!binding.isQuoted()) { |
|
|
|
return "{ '$binary' : '" + base64representation + "', '$type' : " + BSON.B_GENERAL + "}"; |
|
|
|
return "{ '$binary' : '" + base64representation + "', '$type' : " + BSON.B_GENERAL + "}"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return base64representation; |
|
|
|
return base64representation; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -167,9 +168,9 @@ class ExpressionEvaluatingParameterBinder { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* Evaluates the given {@code expressionString}. |
|
|
|
* Evaluates the given {@code expressionString}. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param expressionString |
|
|
|
* @param expressionString must not be {@literal null} or empty. |
|
|
|
* @param parameters |
|
|
|
* @param parameters must not be {@literal null}. |
|
|
|
* @param parameterValues |
|
|
|
* @param parameterValues must not be {@literal null}. |
|
|
|
* @return |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private Object evaluateExpression(String expressionString, MongoParameters parameters, Object[] parameterValues) { |
|
|
|
private Object evaluateExpression(String expressionString, MongoParameters parameters, Object[] parameterValues) { |
|
|
|
|