DATACOUCH-603 Do not cast query parameters in N1qlQueryCreator.

For IN and NOT_IN - they can take varargs, an array or a JsonArray
Don't cast query criteria parameters, let parameter accessor handle that.
Fixed conversion of query criteria values to parameters
Cleaned up QueryCriteria

Co-authored-by: mikereiche <michael.reiche@couchbase.com>
This commit is contained in:
Michael Reiche
2020-10-09 14:59:16 -07:00
committed by GitHub
parent e72cdba6ee
commit 1b5c32150e
10 changed files with 354 additions and 178 deletions

View File

@@ -26,6 +26,7 @@ import com.couchbase.client.java.json.JsonValue;
import com.couchbase.client.java.query.QueryOptions;
import com.couchbase.client.java.query.QueryScanConsistency;
import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate;
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity;
import org.springframework.data.couchbase.repository.query.StringBasedN1qlQueryParser;
import org.springframework.data.couchbase.repository.support.MappingCouchbaseEntityInformation;
@@ -189,7 +190,7 @@ public class Query {
sb.deleteCharAt(sb.length() - 1);
}
public void appendWhere(final StringBuilder sb, int[] paramIndexPtr) {
public void appendWhere(final StringBuilder sb, int[] paramIndexPtr, CouchbaseConverter converter) {
if (!criteria.isEmpty()) {
appendWhereOrAnd(sb);
boolean first = true;
@@ -199,16 +200,11 @@ public class Query {
} else {
sb.append(" AND ");
}
sb.append(c.export(paramIndexPtr));
sb.append(c.export(paramIndexPtr, parameters, converter));
}
}
}
public void appendCriteria(StringBuilder sb, QueryCriteria criteria) {
appendWhereOrAnd(sb);
sb.append(criteria.export());
}
public void appendWhereString(StringBuilder sb, String whereString) {
appendWhereOrAnd(sb);
sb.append(whereString);
@@ -257,9 +253,9 @@ public class Query {
return true; // is not quoted
}
public String export() {
public String export(int[]... paramIndexPtrHolder) { // used only by tests
StringBuilder sb = new StringBuilder();
appendWhere(sb, null);
appendWhere(sb, paramIndexPtrHolder.length > 0 ? paramIndexPtrHolder[0] : null, null);
appendSort(sb);
appendSkipAndLimit(sb);
return sb.toString();
@@ -270,7 +266,7 @@ public class Query {
final StringBuilder statement = new StringBuilder();
appendString(statement, n1ql.selectEntity); // select ...
appendWhereString(statement, n1ql.filter); // typeKey = typeValue
appendWhere(statement, new int[] { 0 }); // criteria on this Query
appendWhere(statement, new int[] { 0 }, template.getConverter()); // criteria on this Query
appendSort(statement);
appendSkipAndLimit(statement);
return statement.toString();

View File

@@ -20,6 +20,11 @@ import java.util.Formatter;
import java.util.LinkedList;
import java.util.List;
import com.couchbase.client.core.error.InvalidArgumentException;
import com.couchbase.client.java.json.JsonArray;
import com.couchbase.client.java.json.JsonObject;
import com.couchbase.client.java.json.JsonValue;
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
import org.springframework.lang.Nullable;
/**
@@ -60,6 +65,10 @@ public class QueryCriteria implements QueryCriteriaDefinition {
this.format = format;
}
Object[] getValue() {
return value;
}
/**
* Static factory method to create a Criteria using the provided key.
*/
@@ -68,8 +77,8 @@ public class QueryCriteria implements QueryCriteriaDefinition {
}
private static QueryCriteria wrap(QueryCriteria criteria) {
QueryCriteria qc = new QueryCriteria(new LinkedList<QueryCriteria>(), criteria.key, criteria.value, null,
criteria.operator, criteria.format);
QueryCriteria qc = new QueryCriteria(new LinkedList<>(), criteria.key, criteria.value, null, criteria.operator,
criteria.format);
return qc;
}
@@ -167,7 +176,7 @@ public class QueryCriteria implements QueryCriteriaDefinition {
public QueryCriteria notContaining(@Nullable Object o) {
value = new QueryCriteria[] { wrap(containing(o)) };
operator = "NOT";
format = format = "not( %3$s )";
format = "not( %3$s )";
return this;
}
@@ -196,7 +205,7 @@ public class QueryCriteria implements QueryCriteriaDefinition {
operator = "IS_NOT_NULL";
value = null;
format = "%1$s is not null";
return (QueryCriteria) this;
return this;
}
public QueryCriteria isMissing() {
@@ -210,7 +219,7 @@ public class QueryCriteria implements QueryCriteriaDefinition {
operator = "IS_NOT_MiSSING";
value = null;
format = "%1$s is not missing";
return (QueryCriteria) this;
return this;
}
public QueryCriteria isValued() {
@@ -224,68 +233,74 @@ public class QueryCriteria implements QueryCriteriaDefinition {
operator = "IS_NOT_VALUED";
value = null;
format = "%1$s is not valued";
return (QueryCriteria) this;
return this;
}
public QueryCriteria within(@Nullable Object o) {
operator = "WITHIN";
value = new Object[] { o };
format = "%1$s within $3$s";
return (QueryCriteria) this;
format = "%1$s within %3$s";
return this;
}
public QueryCriteria between(@Nullable Object o1, @Nullable Object o2) {
operator = "BETWEEN";
value = new Object[] { o1, o2 };
format = "%1$s between %3$s and %4$s";
return (QueryCriteria) this;
return this;
}
public QueryCriteria in(@Nullable Object... o) {
operator = "IN";
value = o;
StringBuilder sb = new StringBuilder("%1$s in ( [ ");
for (int i = 1; i <= value.length; i++) { // format indices start at 1
if (i > 1)
sb.append(", ");
sb.append("%" + (i + 2) + "$s"); // the first is fieldName, second is operator, args start at 3
format = "%1$s in ( %3$s )";
// IN takes a single argument that is a list
if (o.length > 0) {
if (o[0] instanceof JsonArray || o[0] instanceof List || o[0] instanceof Object[]) {
if (o.length != 1) {
throw new RuntimeException("IN cannot take multiple lists");
}
value = o;
} else {
value = new Object[1];
value[0] = o; // JsonArray.from(o);
}
}
format = sb.append(" ] )").toString();
return (QueryCriteria) this;
return this;
}
public QueryCriteria notIn(@Nullable Object... o) {
value = new QueryCriteria[] { wrap(in(o)) };
operator = "NOT";
format = format = "not( %3$s )"; // field = 1$, operator = 2$, value=$3, $4, ...
return (QueryCriteria) this;
format = "not( %3$s )"; // field = 1$, operator = 2$, value=$3, $4, ...
return this;
}
public QueryCriteria TRUE() { // true/false are reserved, use TRUE/FALSE
value = null;
operator = null;
format = format = "%1$s"; // field = 1$, operator = 2$, value=$3, $4, ...
return (QueryCriteria) this;
format = "%1$s"; // field = 1$, operator = 2$, value=$3, $4, ...
return this;
}
public QueryCriteria FALSE() {
value = new QueryCriteria[] { wrap(TRUE()) };
operator = "not";
format = format = "not( %3$s )";
return (QueryCriteria) this;
format = "not( %3$s )";
return this;
}
/**
* This exports the query criteria into a string to be appended to the beginning of an N1QL statement
* This exports the query criteria chain into a string to be appended to the beginning of an N1QL statement
*
* @param paramIndexPtr - this is a reference to the parameter index to be used for positional parameters
* There may already be positional parameters in the beginning of the statement,
* so it may not always start at 1. If it has the value -1, the query is using
* named parameters. If the pointer is null, the query is not using parameters.
* @param paramIndexPtr - this is a reference to the parameter index to be used for positional parameters There may
* already be positional parameters in the beginning of the statement, so it may not always start at 1. If it
* has the value -1, the query is using named parameters. If the pointer is null, the query is not using
* parameters.
* @param parameters - parameters of the query. If operands are parameterized, their values are added to parameters
* @return string containing part of N1QL query
*/
@Override
public String export(int[] paramIndexPtr) {
public String export(int[] paramIndexPtr, JsonValue parameters, CouchbaseConverter converter) {
StringBuilder output = new StringBuilder();
boolean first = true;
for (QueryCriteria c : this.criteriaChain) {
@@ -298,7 +313,7 @@ public class QueryCriteria implements QueryCriteriaDefinition {
} else {
first = false;
}
c.exportSingle(output, paramIndexPtr);
c.exportSingle(output, paramIndexPtr, parameters, converter);
}
return output.toString();
@@ -310,12 +325,24 @@ public class QueryCriteria implements QueryCriteriaDefinition {
* @return string containing part of N1QL query
*/
@Override
public String export() {
return export(null);
public String export() { // used only by tests
return export(null, null, null);
}
private StringBuilder exportSingle(StringBuilder sb, int[] paramIndexPtr) {
/**
* Appends the query criteria to a StringBuilder which will be appended to a N1QL statement
*
* @param sb - the string builder
* @param paramIndexPtr - this is a reference to the parameter index to be used for positional parameters There may
* already be positional parameters in the beginning of the statement, so it may not always start at 1. If it
* has the value -1, the query is using named parameters. If the pointer is null, the query is not using
* parameters.
* @param parameters - parameters of the query. If operands are parameterized, their values are added to parameters
* @return string containing part of N1QL query
*/
private StringBuilder exportSingle(StringBuilder sb, int[] paramIndexPtr, JsonValue parameters,
CouchbaseConverter converter) {
String fieldName = maybeQuote(key);
int valueLen = value == null ? 0 : value.length;
Object[] v = new Object[valueLen + 2];
@@ -323,9 +350,9 @@ public class QueryCriteria implements QueryCriteriaDefinition {
v[1] = operator;
for (int i = 0; i < valueLen; i++) {
if (value[i] instanceof QueryCriteria) {
v[i + 2] = "(" + ((QueryCriteria) value[i]).export(paramIndexPtr) + ")";
v[i + 2] = "(" + ((QueryCriteria) value[i]).export(paramIndexPtr, parameters, converter) + ")";
} else {
v[i + 2] = maybeWrapValue(key, value[i], paramIndexPtr);
v[i + 2] = maybeWrapValue(key, value[i], paramIndexPtr, parameters, converter);
}
}
@@ -340,24 +367,84 @@ public class QueryCriteria implements QueryCriteriaDefinition {
return sb;
}
private String maybeWrapValue(String key, Object value, int[] paramIndexPtr) {
/**
* Possibly convert an operand to a positional or named parameter
*
* @param paramIndexPtr - this is a reference to the parameter index to be used for positional parameters There may
* already be positional parameters in the beginning of the statement, so it may not always start at 1. If it
* has the value -1, the query is using named parameters. If the pointer is null, the query is not using
* parameters.
* @param parameters - parameters of the query. If operands are parameterized, their values are added to parameters
* @return string containing part of N1QL query
*/
private String maybeWrapValue(String key, Object value, int[] paramIndexPtr, JsonValue parameters,
CouchbaseConverter converter) {
if (paramIndexPtr != null) {
if (paramIndexPtr[0] >= 0) {
JsonArray params = (JsonArray) parameters;
// from StringBasedN1qlQueryParser.getPositionalPlaceholderValues()
try {
params.add(convert(converter, value));
} catch (InvalidArgumentException iae) {
if (value instanceof Object[]) {
addAsArray(params, value, converter);
} else {
throw iae;
}
}
return "$" + (++paramIndexPtr[0]); // these are generated in order
} else {
JsonObject params = (JsonObject) parameters;
// from StringBasedN1qlQueryParser.getNamedPlaceholderValues()
try {
params.put(key, convert(converter, value));
} catch (InvalidArgumentException iae) {
if (value instanceof Object[]) {
params.put(key, JsonArray.from((Object[]) value));
} else {
throw iae;
}
}
return "$" + key;
}
}
// Did not convert to a parameter. Add quotes or whatever it might need.
if (value instanceof String) {
return "\"" + value + "\"";
} else if (value == null) {
return "null";
} else if (value instanceof Object[]) { // convert array into sequence of comma-separated values
StringBuffer l = new StringBuffer();
l.append("[");
Object[] array = (Object[]) value;
for (int i = 0; i < array.length; i++) {
if (i > 0) {
l.append(",");
}
l.append(maybeWrapValue(null, array[i], null, null, converter));
}
l.append("]");
return l.toString();
} else {
return value.toString();
}
}
private static Object convert(CouchbaseConverter converter, Object value) {
return converter != null ? converter.convertForWriteIfNeeded(value) : value;
}
private void addAsArray(JsonArray posValues, Object o, CouchbaseConverter converter) {
Object[] array = (Object[]) o;
JsonArray ja = JsonValue.ja();
for (Object e : array) {
ja.add(String.valueOf(convert(converter, e)));
}
posValues.add(ja);
}
private String maybeQuote(String value) {
if (value == null || (value.startsWith("\"") && value.endsWith("\""))) {
return value;

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.data.couchbase.core.query;
import com.couchbase.client.java.json.JsonValue;
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
/**
* @author Oliver Gierke
* @author Christoph Strobl
@@ -25,13 +28,15 @@ public interface QueryCriteriaDefinition {
/**
* This exports the query criteria into a string to be appended to the beginning of an N1QL statement
*
* @param paramIndexPtr - this is a reference to the parameter index to be used for positional parameters
* There may already be positional parameters in the beginning of the statement,
* so it may not always start at 1. If it has the value -1, the query is using
* named parameters. If the pointer is null, the query is not using parameters.
* @param paramIndexPtr - this is a reference to the parameter index to be used for positional parameters There may
* already be positional parameters in the beginning of the statement, so it may not always start at 1. If it
* has the value -1, the query is using named parameters. If the pointer is null, the query is not using
* parameters.
* @param parameters - query parameters. Criteria values that are converted to arguments are added to parameters
* @param converter - converter to use for converting criteria values
* @return string containing part of N1QL query
*/
String export(int[] paramIndexPtr);
String export(int[] paramIndexPtr, JsonValue parameters, CouchbaseConverter converter);
/**
* Export the query criteria to a string without using positional or named parameters.

View File

@@ -66,7 +66,8 @@ public class StringQuery extends Query {
} else { // named parameters or no parameters, no index required
paramIndexPtr = new int[] { -1 };
}
appendWhere(statement, paramIndexPtr); // criteria on this Query - should be empty for StringQuery
appendWhere(statement, paramIndexPtr, template.getConverter()); // criteria on this Query - should be empty for
// StringQuery
appendSort(statement);
appendSkipAndLimit(statement);
return statement.toString();

View File

@@ -17,12 +17,8 @@ package org.springframework.data.couchbase.repository.query;
import static org.springframework.data.couchbase.core.query.QueryCriteria.*;
import java.lang.reflect.Array;
import java.util.Iterator;
import com.couchbase.client.core.error.InvalidArgumentException;
import com.couchbase.client.java.json.JsonArray;
import com.couchbase.client.java.json.JsonValue;
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
import org.springframework.data.couchbase.core.query.Query;
@@ -30,7 +26,6 @@ import org.springframework.data.couchbase.core.query.QueryCriteria;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
@@ -59,8 +54,7 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
@Override
protected QueryCriteria create(final Part part, final Iterator<Object> iterator) {
PersistentPropertyPath<CouchbasePersistentProperty> path = context.getPersistentPropertyPath(
part.getProperty());
PersistentPropertyPath<CouchbasePersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
CouchbasePersistentProperty property = path.getLeafProperty();
return from(part, property, where(path.toDotPath()), iterator);
}
@@ -71,8 +65,7 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
return create(part, iterator);
}
PersistentPropertyPath<CouchbasePersistentProperty> path = context.getPersistentPropertyPath(
part.getProperty());
PersistentPropertyPath<CouchbasePersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
CouchbasePersistentProperty property = path.getLeafProperty();
return from(part, property, base.and(path.toDotPath()), iterator);
@@ -85,92 +78,70 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
@Override
protected Query complete(QueryCriteria criteria, Sort sort) {
JsonArray params = (JsonArray) getPositionalPlaceholderValues(accessor);
return (criteria == null ? new Query() : new Query().addCriteria(criteria)).with(sort).setPositionalParameters(
params);
return (criteria == null ? new Query() : new Query().addCriteria(criteria)).with(sort);
}
private QueryCriteria from(final Part part, final CouchbasePersistentProperty property,
final QueryCriteria criteria, final Iterator<Object> parameters) {
private QueryCriteria from(final Part part, final CouchbasePersistentProperty property, final QueryCriteria criteria,
final Iterator<Object> parameters) {
final Part.Type type = part.getType();
/*
NEAR(new String[]{"IsNear", "Near"}),
*/
switch (type) {
case GREATER_THAN:
case AFTER:
return criteria.gt(parameters.next());
case GREATER_THAN_EQUAL:
return criteria.gte(parameters.next());
case LESS_THAN:
case BEFORE:
return criteria.lt(parameters.next());
case LESS_THAN_EQUAL:
return criteria.lte(parameters.next());
case SIMPLE_PROPERTY:
return criteria.eq(parameters.next());
case NEGATING_SIMPLE_PROPERTY:
return criteria.ne(parameters.next());
case CONTAINING:
return criteria.containing(parameters.next());
case NOT_CONTAINING:
return criteria.notContaining(parameters.next());
case STARTING_WITH:
return criteria.startingWith(parameters.next());
case ENDING_WITH:
return criteria.endingWith(parameters.next());
case LIKE:
return criteria.like(parameters.next());
case NOT_LIKE:
return criteria.notLike(parameters.next());
case WITHIN:
return criteria.within(parameters.next());
case IS_NULL:
return criteria.isNull(/*parameters.next()*/);
case IS_NOT_NULL:
return criteria.isNotNull(/*parameters.next()*/);
case IS_EMPTY:
return criteria.isNotValued(/*parameters.next()*/);
case IS_NOT_EMPTY:
return criteria.isValued(/*parameters.next()*/);
case EXISTS:
return criteria.isNotMissing(/*parameters.next()*/);
case REGEX:
return criteria.regex(parameters.next());
case BETWEEN:
return criteria.between(parameters.next(), parameters.next());
case IN:
return criteria.in((Object[]) parameters.next());
case NOT_IN:
return criteria.notIn((Object[]) parameters.next());
case TRUE:
return criteria.TRUE();
case FALSE:
return criteria.FALSE();
default:
throw new IllegalArgumentException("Unsupported keyword!");
case GREATER_THAN:
case AFTER:
return criteria.gt(parameters.next());
case GREATER_THAN_EQUAL:
return criteria.gte(parameters.next());
case LESS_THAN:
case BEFORE:
return criteria.lt(parameters.next());
case LESS_THAN_EQUAL:
return criteria.lte(parameters.next());
case SIMPLE_PROPERTY:
return criteria.eq(parameters.next());
case NEGATING_SIMPLE_PROPERTY:
return criteria.ne(parameters.next());
case CONTAINING:
return criteria.containing(parameters.next());
case NOT_CONTAINING:
return criteria.notContaining(parameters.next());
case STARTING_WITH:
return criteria.startingWith(parameters.next());
case ENDING_WITH:
return criteria.endingWith(parameters.next());
case LIKE:
return criteria.like(parameters.next());
case NOT_LIKE:
return criteria.notLike(parameters.next());
case WITHIN:
return criteria.within(parameters.next());
case IS_NULL:
return criteria.isNull(/*parameters.next()*/);
case IS_NOT_NULL:
return criteria.isNotNull(/*parameters.next()*/);
case IS_EMPTY:
return criteria.isNotValued(/*parameters.next()*/);
case IS_NOT_EMPTY:
return criteria.isValued(/*parameters.next()*/);
case EXISTS:
return criteria.isNotMissing(/*parameters.next()*/);
case REGEX:
return criteria.regex(parameters.next());
case BETWEEN:
return criteria.between(parameters.next(), parameters.next());
case IN:
return criteria.in(parameters.next());
case NOT_IN:
return criteria.notIn(parameters.next());
case TRUE:
return criteria.TRUE();
case FALSE:
return criteria.FALSE();
default:
throw new IllegalArgumentException("Unsupported keyword!");
}
}
// from StringN1qlQueryParser
private JsonValue getPositionalPlaceholderValues(ParameterAccessor accessor) {
JsonArray posValues = JsonArray.create();
if (queryMethod == null)
return posValues;
for (Parameter parameter : this.queryMethod.getParameters().getBindableParameters()) {
try {
posValues.add(converter.convertForWriteIfNeeded(accessor.getBindableValue(parameter.getIndex())));
} catch (InvalidArgumentException iae) {
Object o = accessor.getBindableValue(parameter.getIndex());
if (o instanceof Object[]) {
Object[] array = (Object[]) o;
for (Object e : array) {
posValues.add(converter.convertForWriteIfNeeded(e));
}
}
}
}
return posValues;
}
}

View File

@@ -189,14 +189,14 @@ public class StringBasedN1qlQueryParser {
if (checkNotQuoted(placeholder, namedMatcher.start(), namedMatcher.end(), quotes)) {
LOGGER.trace("{}: Found named placeholder {}", this.queryMethod.getName(), placeholder);
namedCount++;
parameterNames.add(placeholder.substring(1));//save without the leading $
parameterNames.add(placeholder.substring(1));// save without the leading $
}
}
if (posCount > 0 && namedCount > 0) { // actual values from parameterNames might be more useful
throw new IllegalArgumentException("Using both named (" + namedCount + ") and positional (" + posCount
+ ") placeholders is not supported, please choose one over the other in "
+ queryMethod.getClass().getName() + "." + this.queryMethod.getName() + "()");
+ ") placeholders is not supported, please choose one over the other in " + queryMethod.getClass().getName()
+ "." + this.queryMethod.getName() + "()");
}
if (posCount > 0) {
@@ -211,8 +211,7 @@ public class StringBasedN1qlQueryParser {
private boolean checkNotQuoted(String item, int start, int end, List<int[]> quotes) {
for (int[] quote : quotes) {
if (quote[0] <= start && quote[1] >= end) {
LOGGER.trace("{}: potential placeholder {} is inside quotes, ignored", this.queryMethod.getName(),
item);
LOGGER.trace("{}: potential placeholder {} is inside quotes, ignored", this.queryMethod.getName(), item);
return false;
}
}
@@ -220,7 +219,7 @@ public class StringBasedN1qlQueryParser {
}
/**
* Get Postional argument placeholders to use for parameters. $1, $2 etc.
* Get Postional argument placeholders to use for parameters. $1, $2 etc.
*
* @param accessor
* @return - JsonValue holding parameters.
@@ -230,7 +229,7 @@ public class StringBasedN1qlQueryParser {
for (Parameter parameter : this.queryMethod.getParameters().getBindableParameters()) {
Object rawValue = accessor.getBindableValue(parameter.getIndex());
Object value = couchbaseConverter.convertForWriteIfNeeded(rawValue);
putPositionalValue(accessor, parameter, posValues, value);
putPositionalValue(posValues, value);
}
return posValues;
}
@@ -251,22 +250,20 @@ public class StringBasedN1qlQueryParser {
if (placeholder != null && placeholder.charAt(0) == ':') {
placeholder = placeholder.replaceFirst(":", "");
putNamedValue(accessor, parameter, namedValues, placeholder, value);
putNamedValue(namedValues, placeholder, value);
if (pNames.contains(placeholder)) {
pNames.remove(placeholder);
} else {
throw new RuntimeException(
"parameter named " + placeholder + " does not match any named parameter " + parameterNames
+ " in " + statement);
throw new RuntimeException("parameter named " + placeholder + " does not match any named parameter "
+ parameterNames + " in " + statement);
}
} else {
if (parameter.getName().isPresent()) {
putNamedValue(accessor, parameter, namedValues, parameter.getName().get(), value);
putNamedValue(namedValues, parameter.getName().get(), value);
} else {
throw new RuntimeException(
"cannot determine argument for named parameter. " + "Argument " + parameter.getIndex()
+ " to " + queryMethod.getClass().getName() + "." + queryMethod.getName()
+ "() needs @Param(\"name\") that matches a named parameter in " + statement);
throw new RuntimeException("cannot determine argument for named parameter. " + "Argument "
+ parameter.getIndex() + " to " + queryMethod.getClass().getName() + "." + queryMethod.getName()
+ "() needs @Param(\"name\") that matches a named parameter in " + statement);
}
}
}
@@ -278,18 +275,17 @@ public class StringBasedN1qlQueryParser {
protected JsonValue getPlaceholderValues(ParameterAccessor accessor) {
switch (this.placeHolderType) {
case NAMED:
return getNamedPlaceholderValues(accessor);
case POSITIONAL:
return getPositionalPlaceholderValues(accessor);
case NONE:
default:
return JsonArray.create();
case NAMED:
return getNamedPlaceholderValues(accessor);
case POSITIONAL:
return getPositionalPlaceholderValues(accessor);
case NONE:
default:
return JsonArray.create();
}
}
private void putPositionalValue(ParameterAccessor accessor, Parameter parameter, JsonArray posValues,
Object value) {
private void putPositionalValue(JsonArray posValues, Object value) {
try {
posValues.add(value);
} catch (InvalidArgumentException iae) {
@@ -310,8 +306,7 @@ public class StringBasedN1qlQueryParser {
posValues.add(ja);
}
private void putNamedValue(ParameterAccessor accessor, Parameter parameter, JsonObject namedValues,
String placeholder, Object value) {
private void putNamedValue(JsonObject namedValues, String placeholder, Object value) {
try {
namedValues.put(placeholder, value);
} catch (InvalidArgumentException iae) {

View File

@@ -145,7 +145,7 @@ public class StringN1qlQueryCreator extends AbstractQueryCreator<Query, QueryCri
final Part.Type type = part.getType();
switch (type) {
case SIMPLE_PROPERTY:
return criteria; //.eq(parameters.next()); // this will be the dummy from PartTree
return criteria; // this will be the dummy from PartTree
default:
throw new IllegalArgumentException("Unsupported keyword!");
}