DATACOUCH-413 Use parameterized queries for Query derivation
Changes ------- - N1ql query creators implement an interface which provides the place holder values. - The query creator uses a position index counter to inject place holders in the statement created and caches the place holder values in an array. - Repository query constructor passes the generated query statement and place holder values to query through the SDK. - Cleanup N1ql integration tests for count validation and also add couple of more tests Results ------- The testing for changes are already covered under the modified existing tests in N1qlQueryCreator and Repository.
This commit is contained in:
@@ -101,6 +101,7 @@ public abstract class AbstractN1qlBasedQuery implements RepositoryQuery {
|
||||
|
||||
//prepare a count query
|
||||
Statement countStatement = getCount(accessor, parameters);
|
||||
//the place holder values are the same for the count query as well
|
||||
N1qlQuery countQuery = buildQuery(countStatement, queryPlaceholderValues,
|
||||
getCouchbaseOperations().getDefaultConsistency().n1qlConsistency());
|
||||
return processor.processResult(executeDependingOnType(query, countQuery, queryMethod, accessor.getPageable(), typeToRead));
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.document.json.JsonValue;
|
||||
import com.couchbase.client.java.query.dsl.Expression;
|
||||
import com.couchbase.client.java.query.dsl.path.*;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
@@ -35,11 +39,13 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
*
|
||||
* @author Subhashni Balakrishnan
|
||||
*/
|
||||
public class N1qlMutateQueryCreator extends AbstractQueryCreator<MutateLimitPath, Expression> {
|
||||
public class N1qlMutateQueryCreator extends AbstractQueryCreator<MutateLimitPath, Expression> implements PartTreeN1qlQueryCreator {
|
||||
private final MutateWherePath mutateFrom;
|
||||
private final CouchbaseConverter converter;
|
||||
private final CouchbaseQueryMethod queryMethod;
|
||||
private final ParameterAccessor accessor;
|
||||
private final JsonArray placeHolderValues;
|
||||
private final AtomicInteger position;
|
||||
|
||||
public N1qlMutateQueryCreator(PartTree tree, ParameterAccessor parameters, MutateWherePath mutateFrom,
|
||||
CouchbaseConverter converter, CouchbaseQueryMethod queryMethod) {
|
||||
@@ -48,11 +54,13 @@ public class N1qlMutateQueryCreator extends AbstractQueryCreator<MutateLimitPath
|
||||
this.converter = converter;
|
||||
this.queryMethod = queryMethod;
|
||||
this.accessor = parameters;
|
||||
this.placeHolderValues = JsonArray.create();
|
||||
this.position = new AtomicInteger(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression create(Part part, Iterator<Object> iterator) {
|
||||
return N1qlQueryCreatorUtils.prepareExpression(this.converter, part, iterator);
|
||||
return N1qlQueryCreatorUtils.prepareExpression(this.converter, part, iterator, this.position, this.placeHolderValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,4 +82,9 @@ public class N1qlMutateQueryCreator extends AbstractQueryCreator<MutateLimitPath
|
||||
Expression whereCriteria = N1qlUtils.createWhereFilterForEntity(criteria, this.converter, this.queryMethod.getEntityInformation());
|
||||
return mutateFrom.where(whereCriteria);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonValue getPlaceHolderValues() {
|
||||
return this.placeHolderValues;
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.document.json.JsonValue;
|
||||
import com.couchbase.client.java.query.dsl.Expression;
|
||||
import com.couchbase.client.java.query.dsl.path.LimitPath;
|
||||
import com.couchbase.client.java.query.dsl.path.OrderByPath;
|
||||
@@ -83,12 +85,13 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class N1qlQueryCreator extends AbstractQueryCreator<LimitPath, Expression> {
|
||||
|
||||
public class N1qlQueryCreator extends AbstractQueryCreator<LimitPath, Expression> implements PartTreeN1qlQueryCreator {
|
||||
private final WherePath selectFrom;
|
||||
private final CouchbaseConverter converter;
|
||||
private final CouchbaseQueryMethod queryMethod;
|
||||
private final ParameterAccessor accessor;
|
||||
private final JsonArray placeHolderValues;
|
||||
private final AtomicInteger position;
|
||||
|
||||
public N1qlQueryCreator(PartTree tree, ParameterAccessor parameters, WherePath selectFrom,
|
||||
CouchbaseConverter converter, CouchbaseQueryMethod queryMethod) {
|
||||
@@ -97,11 +100,13 @@ public class N1qlQueryCreator extends AbstractQueryCreator<LimitPath, Expression
|
||||
this.converter = converter;
|
||||
this.queryMethod = queryMethod;
|
||||
this.accessor = parameters;
|
||||
this.placeHolderValues = JsonArray.create();
|
||||
this.position = new AtomicInteger(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression create(Part part, Iterator<Object> iterator) {
|
||||
return N1qlQueryCreatorUtils.prepareExpression(converter, part, iterator);
|
||||
return N1qlQueryCreatorUtils.prepareExpression(converter, part, iterator, this.position, this.placeHolderValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,4 +142,8 @@ public class N1qlQueryCreator extends AbstractQueryCreator<LimitPath, Expression
|
||||
return selectFromWhere;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonValue getPlaceHolderValues() {
|
||||
return this.placeHolderValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.couchbase.client.java.query.dsl.Expression.i;
|
||||
import static com.couchbase.client.java.query.dsl.functions.AggregateFunctions.count;
|
||||
import static org.springframework.data.couchbase.repository.query.support.N1qlUtils.createReturningExpressionForDelete;
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.document.json.JsonObject;
|
||||
import com.couchbase.client.java.document.json.JsonValue;
|
||||
import com.couchbase.client.java.query.Statement;
|
||||
import com.couchbase.client.java.query.dsl.Expression;
|
||||
@@ -49,6 +50,7 @@ import org.springframework.util.Assert;
|
||||
public class PartTreeN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
|
||||
private final PartTree partTree;
|
||||
private JsonValue placeHolderValues;
|
||||
|
||||
public PartTreeN1qlBasedQuery(CouchbaseQueryMethod queryMethod, CouchbaseOperations couchbaseOperations) {
|
||||
super(queryMethod, couchbaseOperations);
|
||||
@@ -57,7 +59,7 @@ public class PartTreeN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
|
||||
@Override
|
||||
protected JsonValue getPlaceholderValues(ParameterAccessor accessor) {
|
||||
return JsonArray.empty();
|
||||
return this.placeHolderValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,10 +67,13 @@ public class PartTreeN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
Expression bucket = i(getCouchbaseOperations().getCouchbaseBucket().name());
|
||||
WherePath countFrom = select(count("*").as(CountFragment.COUNT_ALIAS)).from(bucket);
|
||||
|
||||
N1qlQueryCreator queryCreator = new N1qlCountQueryCreator(partTree, accessor, countFrom,
|
||||
N1qlCountQueryCreator queryCountCreator = new N1qlCountQueryCreator(partTree, accessor, countFrom,
|
||||
getCouchbaseOperations().getConverter(), getQueryMethod());
|
||||
return queryCreator.createQuery();
|
||||
Statement statement = queryCountCreator.createQuery();
|
||||
this.placeHolderValues = queryCountCreator.getPlaceHolderValues();
|
||||
return statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Statement getStatement(ParameterAccessor accessor, Object[] runtimeParameters, ReturnedType returnedType) {
|
||||
String bucketName = getCouchbaseOperations().getCouchbaseBucket().name();
|
||||
@@ -76,8 +81,10 @@ public class PartTreeN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
|
||||
if (partTree.isDelete()) {
|
||||
DeleteUsePath deleteUsePath = deleteFrom(bucket);
|
||||
N1qlMutateQueryCreator queryCreator = new N1qlMutateQueryCreator(partTree, accessor, deleteUsePath, getCouchbaseOperations().getConverter(), getQueryMethod());
|
||||
MutateLimitPath mutateFromWhereOrderBy = queryCreator.createQuery();
|
||||
N1qlMutateQueryCreator mutateQueryCreator = new N1qlMutateQueryCreator(partTree, accessor, deleteUsePath, getCouchbaseOperations().getConverter(), getQueryMethod());
|
||||
MutateLimitPath mutateFromWhereOrderBy = mutateQueryCreator.createQuery();
|
||||
this.placeHolderValues = mutateQueryCreator.getPlaceHolderValues();
|
||||
|
||||
if (partTree.isLimiting()) {
|
||||
return mutateFromWhereOrderBy.limit(partTree.getMaxResults());
|
||||
} else {
|
||||
@@ -94,6 +101,7 @@ public class PartTreeN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
N1qlQueryCreator queryCreator = new N1qlQueryCreator(partTree, accessor, selectFrom,
|
||||
getCouchbaseOperations().getConverter(), getQueryMethod());
|
||||
LimitPath selectFromWhereOrderBy = queryCreator.createQuery();
|
||||
this.placeHolderValues = queryCreator.getPlaceHolderValues();
|
||||
|
||||
if (queryMethod.isPageQuery()) {
|
||||
Pageable pageable = accessor.getPageable();
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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.couchbase.repository.query;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonValue;
|
||||
|
||||
/**
|
||||
* A Part Tree Query creator for Couchbase
|
||||
*
|
||||
* @author Subhashni Balakrishnan
|
||||
*/
|
||||
public interface PartTreeN1qlQueryCreator {
|
||||
|
||||
/** Get the named placeholder values */
|
||||
JsonValue getPlaceHolderValues();
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import static com.couchbase.client.java.query.Select.select;
|
||||
import static com.couchbase.client.java.query.dsl.functions.AggregateFunctions.count;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.document.json.JsonObject;
|
||||
import com.couchbase.client.java.document.json.JsonValue;
|
||||
import com.couchbase.client.java.query.Statement;
|
||||
import com.couchbase.client.java.query.dsl.Expression;
|
||||
@@ -41,6 +42,7 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
public class ReactivePartTreeN1qlBasedQuery extends ReactiveAbstractN1qlBasedQuery {
|
||||
|
||||
private final PartTree partTree;
|
||||
private JsonValue placeHolderValues;
|
||||
|
||||
public ReactivePartTreeN1qlBasedQuery(CouchbaseQueryMethod queryMethod, RxJavaCouchbaseOperations operations) {
|
||||
super(queryMethod, operations);
|
||||
@@ -49,7 +51,7 @@ public class ReactivePartTreeN1qlBasedQuery extends ReactiveAbstractN1qlBasedQue
|
||||
|
||||
@Override
|
||||
protected JsonValue getPlaceholderValues(ParameterAccessor accessor) {
|
||||
return JsonArray.empty();
|
||||
return this.placeHolderValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,6 +70,7 @@ public class ReactivePartTreeN1qlBasedQuery extends ReactiveAbstractN1qlBasedQue
|
||||
N1qlQueryCreator queryCreator = new N1qlQueryCreator(partTree, accessor, selectFrom,
|
||||
getCouchbaseOperations().getConverter(), getQueryMethod());
|
||||
LimitPath selectFromWhereOrderBy = queryCreator.createQuery();
|
||||
this.placeHolderValues = queryCreator.getPlaceHolderValues();
|
||||
if (partTree.isLimiting()) {
|
||||
return selectFromWhereOrderBy.limit(partTree.getMaxResults());
|
||||
} else {
|
||||
|
||||
@@ -18,9 +18,13 @@ package org.springframework.data.couchbase.repository.query.support;
|
||||
|
||||
import static com.couchbase.client.java.query.dsl.Expression.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonObject;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.couchbase.repository.query.ConvertingIterator;
|
||||
@@ -38,7 +42,7 @@ import com.couchbase.client.java.query.dsl.functions.StringFunctions;
|
||||
* @author Subhashni Balakrishnan
|
||||
*/
|
||||
public class N1qlQueryCreatorUtils {
|
||||
public static Expression prepareExpression(CouchbaseConverter converter, Part part, Iterator<Object> iterator) {
|
||||
public static Expression prepareExpression(CouchbaseConverter converter, Part part, Iterator<Object> iterator, AtomicInteger position, JsonArray placeHolderValues) {
|
||||
PersistentPropertyPath<CouchbasePersistentProperty> path = N1qlUtils.getPathWithAlternativeFieldNames(
|
||||
converter, part.getProperty());
|
||||
ConvertingIterator parameterValues = new ConvertingIterator(iterator, converter);
|
||||
@@ -59,68 +63,116 @@ public class N1qlQueryCreatorUtils {
|
||||
ignoreCase = true;
|
||||
}
|
||||
|
||||
return createExpression(part.getType(), fieldNamePath, ignoreCase, parameterValues);
|
||||
return createExpression(part.getType(), fieldNamePath, ignoreCase, parameterValues, position, placeHolderValues);
|
||||
}
|
||||
|
||||
|
||||
public static Expression createExpression(Part.Type partType, String fieldNamePath, boolean ignoreCase, Iterator<Object> parameterValues) {
|
||||
public static Expression createExpression(Part.Type partType, String fieldNamePath, boolean ignoreCase,
|
||||
Iterator<Object> parameterValues, AtomicInteger position, JsonArray placeHolderValues) {
|
||||
//create the left hand side of the expression, taking ignoreCase into account
|
||||
Expression left = ignoreCase ? StringFunctions.lower(x(fieldNamePath)) : x(fieldNamePath);
|
||||
|
||||
Expression left = ignoreCase ? StringFunctions.lower(x(fieldNamePath)) : x(fieldNamePath);
|
||||
Expression exp;
|
||||
switch (partType) {
|
||||
case BETWEEN:
|
||||
return left.between(leftAndRight(parameterValues, ignoreCase));
|
||||
exp = left.between(x(getPlaceHolder(position, ignoreCase)).and(x(getPlaceHolder(position, ignoreCase))));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case IS_NOT_NULL:
|
||||
return left.isNotNull();
|
||||
exp = left.isNotNull();
|
||||
break;
|
||||
case IS_NULL:
|
||||
return left.isNull();
|
||||
exp = left.isNull();
|
||||
break;
|
||||
case NEGATING_SIMPLE_PROPERTY:
|
||||
return left.ne(right(parameterValues, ignoreCase));
|
||||
exp = left.ne(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case SIMPLE_PROPERTY:
|
||||
return left.eq(right(parameterValues, ignoreCase));
|
||||
exp = left.eq(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case BEFORE:
|
||||
case LESS_THAN:
|
||||
return left.lt(right(parameterValues, ignoreCase));
|
||||
exp = left.lt(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case LESS_THAN_EQUAL:
|
||||
return left.lte(right(parameterValues, ignoreCase));
|
||||
exp = left.lte(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case GREATER_THAN_EQUAL:
|
||||
return left.gte(right(parameterValues, ignoreCase));
|
||||
exp = left.gte(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case AFTER:
|
||||
case GREATER_THAN:
|
||||
return left.gt(right(parameterValues, ignoreCase));
|
||||
exp = left.gt(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case NOT_LIKE:
|
||||
return left.notLike(right(parameterValues, ignoreCase));
|
||||
exp = left.notLike(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case LIKE:
|
||||
return left.like(right(parameterValues, ignoreCase));
|
||||
exp = left.like(getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case STARTING_WITH:
|
||||
return left.like(like(parameterValues, ignoreCase, false, true));
|
||||
exp = left.like(getPlaceHolder(position, ignoreCase) + " || '%'");
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case ENDING_WITH:
|
||||
return left.like(like(parameterValues, ignoreCase, true, false));
|
||||
exp = left.like("'%' || " + getPlaceHolder(position, ignoreCase));
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case NOT_CONTAINING:
|
||||
return left.notLike(like(parameterValues, ignoreCase, true, true));
|
||||
exp = left.notLike("'%' || " + getPlaceHolder(position, ignoreCase) + " || '%'");
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case CONTAINING:
|
||||
return left.like(like(parameterValues, ignoreCase, true, true));
|
||||
exp = left.like("'%' || " + getPlaceHolder(position, ignoreCase) + " || '%'");
|
||||
placeHolderValues.add(getValue(parameterValues));
|
||||
break;
|
||||
case NOT_IN:
|
||||
return left.notIn(rightArray(parameterValues));
|
||||
exp = left.notIn(getPlaceHolder(position, false));
|
||||
placeHolderValues.add(getArray(parameterValues));
|
||||
break;
|
||||
case IN:
|
||||
return left.in(rightArray(parameterValues));
|
||||
exp = left.in(getPlaceHolder(position, false));
|
||||
placeHolderValues.add(getArray(parameterValues));
|
||||
break;
|
||||
case TRUE:
|
||||
return left.eq(true);
|
||||
exp = left.eq(true);
|
||||
break;
|
||||
case FALSE:
|
||||
return left.eq(false);
|
||||
exp = left.eq(false);
|
||||
break;
|
||||
case REGEX:
|
||||
return regexp(fieldNamePath, parameterValues);
|
||||
exp = x("REGEXP_LIKE(" + left.toString() + ", " + getPlaceHolder(position, false) + ")");
|
||||
placeHolderValues.add(getValueAsString(parameterValues));
|
||||
break;
|
||||
case EXISTS:
|
||||
return left.isNotMissing();
|
||||
exp = left.isNotMissing();
|
||||
break;
|
||||
case WITHIN:
|
||||
case NEAR:
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported keyword in N1QL query derivation");
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
protected static String getPlaceHolder(AtomicInteger position, boolean ignoreCase) {
|
||||
String placeHolder = "$" + position.getAndIncrement();
|
||||
if (ignoreCase) {
|
||||
placeHolder = StringFunctions.lower(x(placeHolder)).toString();
|
||||
}
|
||||
return placeHolder;
|
||||
}
|
||||
|
||||
protected static Expression regexp(String left, Iterator<Object> parameterValues) {
|
||||
protected static String getValueAsString(Iterator<Object> parameterValues) {
|
||||
Object next = parameterValues.next();
|
||||
|
||||
String pattern;
|
||||
@@ -129,11 +181,7 @@ public class N1qlQueryCreatorUtils {
|
||||
} else {
|
||||
pattern = String.valueOf(next);
|
||||
}
|
||||
return PatternMatchingFunctions.regexpLike(left, pattern);
|
||||
}
|
||||
|
||||
protected static Expression leftAndRight(Iterator<Object> parameterValues, boolean ignoreCase) {
|
||||
return right(parameterValues, ignoreCase).and(right(parameterValues, ignoreCase));
|
||||
return pattern;
|
||||
}
|
||||
|
||||
protected static Expression like(Iterator<Object> parameterValues, boolean ignoreCase,
|
||||
@@ -164,28 +212,15 @@ public class N1qlQueryCreatorUtils {
|
||||
return converted;
|
||||
}
|
||||
|
||||
protected static Expression right(Iterator<Object> parameterValues, boolean ignoreCase) {
|
||||
protected static Object getValue(Iterator<Object> parameterValues) {
|
||||
Object next = parameterValues.next();
|
||||
if (next == null) {
|
||||
return Expression.NULL();
|
||||
if (next instanceof Enum) {
|
||||
next = String.valueOf(next);
|
||||
}
|
||||
|
||||
Expression converted;
|
||||
if (next instanceof String) {
|
||||
converted = s((String) next);
|
||||
} else if (next instanceof Enum) {
|
||||
converted = s(String.valueOf(next));
|
||||
} else {
|
||||
converted = x(String.valueOf(next));
|
||||
}
|
||||
|
||||
if (ignoreCase) {
|
||||
return StringFunctions.lower(converted);
|
||||
}
|
||||
return converted;
|
||||
return next;
|
||||
}
|
||||
|
||||
protected static JsonArray rightArray(Iterator<Object> parameterValues) {
|
||||
protected static JsonArray getArray(Iterator<Object> parameterValues) {
|
||||
Object next = parameterValues.next();
|
||||
|
||||
Object[] values;
|
||||
@@ -198,4 +233,4 @@ public class N1qlQueryCreatorUtils {
|
||||
}
|
||||
return JsonArray.from(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user