DATACOUCH-1066 - Make QueryCriteria key a N1qlExpression. (#1082)
This is a merge of mmonti's changeset into master. The changeset was made on top of 4.1.x instead of master so it has a little catching up to do. Co-authored-by: mikereiche <michael.reiche@couchbase.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -15,25 +15,29 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.core.query;
|
||||
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.x;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Michael Nitschinger
|
||||
* @author Michael Reiche
|
||||
* @author Mauro Monti
|
||||
*/
|
||||
public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
|
||||
private final String key;
|
||||
private final N1QLExpression key;
|
||||
/**
|
||||
* Holds the chain itself, the current operator being always the last one.
|
||||
*/
|
||||
@@ -46,16 +50,16 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
private Object[] value;
|
||||
private String format;
|
||||
|
||||
QueryCriteria(List<QueryCriteria> chain, String key, Object[] value, ChainOperator chainOperator) {
|
||||
QueryCriteria(List<QueryCriteria> chain, N1QLExpression key, Object[] value, ChainOperator chainOperator) {
|
||||
this(chain, key, value, chainOperator, null, null);
|
||||
}
|
||||
|
||||
QueryCriteria(List<QueryCriteria> chain, String key, Object value, ChainOperator chainOperator) {
|
||||
QueryCriteria(List<QueryCriteria> chain, N1QLExpression key, Object value, ChainOperator chainOperator) {
|
||||
this(chain, key, new Object[] { value }, chainOperator, null, null);
|
||||
}
|
||||
|
||||
QueryCriteria(List<QueryCriteria> chain, String key, Object[] value, ChainOperator chainOperator, String operator,
|
||||
String format) {
|
||||
QueryCriteria(List<QueryCriteria> chain, N1QLExpression key, Object[] value, ChainOperator chainOperator,
|
||||
String operator, String format) {
|
||||
this.criteriaChain = chain;
|
||||
criteriaChain.add(this);
|
||||
this.key = key;
|
||||
@@ -70,9 +74,16 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method to create a Criteria using the provided key.
|
||||
* Static factory method to create a Criteria using the provided String key.
|
||||
*/
|
||||
public static QueryCriteria where(String key) {
|
||||
return where(x(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method to create a Criteria using the provided N1QLExpression key.
|
||||
*/
|
||||
public static QueryCriteria where(N1QLExpression key) {
|
||||
return new QueryCriteria(new ArrayList<>(), key, null, null);
|
||||
}
|
||||
|
||||
@@ -83,6 +94,10 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
}
|
||||
|
||||
public QueryCriteria and(String key) {
|
||||
return and(x(key));
|
||||
}
|
||||
|
||||
public QueryCriteria and(N1QLExpression key) {
|
||||
return new QueryCriteria(this.criteriaChain, key, null, ChainOperator.AND);
|
||||
}
|
||||
|
||||
@@ -90,14 +105,18 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
return new QueryCriteria(this.criteriaChain, null, criteria, ChainOperator.AND);
|
||||
}
|
||||
|
||||
public QueryCriteria or(QueryCriteria criteria) {
|
||||
return new QueryCriteria(this.criteriaChain, null, criteria, ChainOperator.OR);
|
||||
public QueryCriteria or(String key) {
|
||||
return or(x(key));
|
||||
}
|
||||
|
||||
public QueryCriteria or(String key) {
|
||||
public QueryCriteria or(N1QLExpression key) {
|
||||
return new QueryCriteria(this.criteriaChain, key, null, ChainOperator.OR);
|
||||
}
|
||||
|
||||
public QueryCriteria or(QueryCriteria criteria) {
|
||||
return new QueryCriteria(this.criteriaChain, null, criteria, ChainOperator.OR);
|
||||
}
|
||||
|
||||
public QueryCriteria eq(@Nullable Object o) {
|
||||
return is(o);
|
||||
}
|
||||
@@ -343,7 +362,7 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
*/
|
||||
private StringBuilder exportSingle(StringBuilder sb, int[] paramIndexPtr, JsonValue parameters,
|
||||
CouchbaseConverter converter) {
|
||||
String fieldName = maybeBackTic(key);
|
||||
String fieldName = key == null ? null : key.toString(); // maybeBackTic(key);
|
||||
int valueLen = value == null ? 0 : value.length;
|
||||
Object[] v = new Object[valueLen + 2];
|
||||
v[0] = fieldName;
|
||||
@@ -377,7 +396,7 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
* @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,
|
||||
private String maybeWrapValue(N1QLExpression key, Object value, int[] paramIndexPtr, JsonValue parameters,
|
||||
CouchbaseConverter converter) {
|
||||
if (paramIndexPtr != null) {
|
||||
if (paramIndexPtr[0] >= 0) {
|
||||
@@ -397,10 +416,10 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
JsonObject params = (JsonObject) parameters;
|
||||
// from StringBasedN1qlQueryParser.getNamedPlaceholderValues()
|
||||
try {
|
||||
params.put(key, convert(converter, value));
|
||||
params.put(key.toString(), convert(converter, value));
|
||||
} catch (InvalidArgumentException iae) {
|
||||
if (value instanceof Object[]) {
|
||||
params.put(key, JsonArray.from((Object[]) value));
|
||||
params.put(key.toString(), JsonArray.from((Object[]) value));
|
||||
} else {
|
||||
throw iae;
|
||||
}
|
||||
@@ -416,7 +435,7 @@ public class QueryCriteria implements QueryCriteriaDefinition {
|
||||
} else if (value == null) {
|
||||
return "null";
|
||||
} else if (value instanceof Object[]) { // convert array into sequence of comma-separated values
|
||||
StringBuffer l = new StringBuffer();
|
||||
StringBuilder l = new StringBuilder();
|
||||
l.append("[");
|
||||
Object[] array = (Object[]) value;
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
|
||||
@@ -118,6 +118,11 @@ public class N1qlCountQueryCreator extends OldN1qlQueryCreator {
|
||||
return delegate.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pageable withPage(int i) {
|
||||
return new CountPageable(delegate.withPage(i));
|
||||
}
|
||||
|
||||
public boolean hasPrevious() {
|
||||
return delegate.hasPrevious();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -15,6 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.i;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.meta;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.path;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.x;
|
||||
import static org.springframework.data.couchbase.core.query.QueryCriteria.where;
|
||||
|
||||
import java.util.Iterator;
|
||||
@@ -22,6 +26,7 @@ import java.util.Iterator;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.couchbase.core.query.N1QLExpression;
|
||||
import org.springframework.data.couchbase.core.query.Query;
|
||||
import org.springframework.data.couchbase.core.query.QueryCriteria;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -36,33 +41,39 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
/**
|
||||
* @author Michael Nitschinger
|
||||
* @author Michael Reiche
|
||||
* @author Mauro Monti
|
||||
*/
|
||||
public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria> {
|
||||
|
||||
private static final String META_ID_PROPERTY = "id";
|
||||
private static final String META_CAS_PROPERTY = "cas";
|
||||
|
||||
private final ParameterAccessor accessor;
|
||||
private final MappingContext<?, CouchbasePersistentProperty> context;
|
||||
private final QueryMethod queryMethod;
|
||||
private final CouchbaseConverter converter;
|
||||
private final String bucketName;
|
||||
|
||||
public N1qlQueryCreator(final PartTree tree, final ParameterAccessor accessor, QueryMethod queryMethod,
|
||||
CouchbaseConverter converter) {
|
||||
public N1qlQueryCreator(final PartTree tree, final ParameterAccessor accessor, final QueryMethod queryMethod,
|
||||
final CouchbaseConverter converter, final String bucketName) {
|
||||
super(tree, accessor);
|
||||
this.accessor = accessor;
|
||||
this.context = converter.getMappingContext();
|
||||
this.queryMethod = queryMethod;
|
||||
this.converter = converter;
|
||||
this.bucketName = bucketName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryCriteria create(final Part part, final Iterator<Object> iterator) {
|
||||
PersistentPropertyPath<CouchbasePersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
|
||||
CouchbasePersistentProperty property = path.getLeafProperty();
|
||||
return from(part, property, where(path.toDotPath(cvtr)), iterator);
|
||||
return from(part, property, where(addMetaIfRequired(path, property)), iterator);
|
||||
}
|
||||
|
||||
static Converter<? super CouchbasePersistentProperty, String> cvtr = (
|
||||
source) -> new StringBuilder(source.getName().length() + 2).append('`').append(source.getName()).append('`')
|
||||
.toString();
|
||||
source) -> new StringBuilder(source.getFieldName().length() + 2).append('`').append(source.getFieldName())
|
||||
.append('`').toString();
|
||||
|
||||
@Override
|
||||
protected QueryCriteria and(final Part part, final QueryCriteria base, final Iterator<Object> iterator) {
|
||||
@@ -73,7 +84,7 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
|
||||
PersistentPropertyPath<CouchbasePersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
|
||||
CouchbasePersistentProperty property = path.getLeafProperty();
|
||||
|
||||
return from(part, property, base.and(path.toDotPath()), iterator);
|
||||
return from(part, property, base.and(addMetaIfRequired(path, property)), iterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,4 +160,16 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
|
||||
}
|
||||
}
|
||||
|
||||
private N1QLExpression addMetaIfRequired(
|
||||
final PersistentPropertyPath<CouchbasePersistentProperty> persistentPropertyPath,
|
||||
final CouchbasePersistentProperty property) {
|
||||
if (property.isIdProperty()) {
|
||||
return path(meta(i(bucketName)), i(META_ID_PROPERTY));
|
||||
}
|
||||
if (property.isVersionProperty()) {
|
||||
return path(meta(i(bucketName)), i(META_CAS_PROPERTY));
|
||||
}
|
||||
return x(persistentPropertyPath.toDotPath(cvtr));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class N1qlRepositoryQueryExecutor {
|
||||
SPEL_PARSER, evaluationContextProvider, namedQueries).createQuery();
|
||||
} else {
|
||||
final PartTree tree = new PartTree(queryMethod.getName(), domainClass);
|
||||
query = new N1qlQueryCreator(tree, accessor, queryMethod, operations.getConverter()).createQuery();
|
||||
query = new N1qlQueryCreator(tree, accessor, queryMethod, operations.getConverter(), operations.getBucketName()).createQuery();
|
||||
}
|
||||
|
||||
ExecutableFindByQueryOperation.ExecutableFindByQuery<?> operation = (ExecutableFindByQueryOperation.ExecutableFindByQuery<?>) operations
|
||||
|
||||
@@ -72,7 +72,8 @@ public class PartTreeCouchbaseQuery extends AbstractCouchbaseQuery {
|
||||
@Override
|
||||
protected Query createQuery(ParametersParameterAccessor accessor) {
|
||||
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter);
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter,
|
||||
getOperations().getBucketName());
|
||||
Query query = creator.createQuery();
|
||||
|
||||
if (tree.isLimiting()) {
|
||||
@@ -88,7 +89,8 @@ public class PartTreeCouchbaseQuery extends AbstractCouchbaseQuery {
|
||||
*/
|
||||
@Override
|
||||
protected Query createCountQuery(ParametersParameterAccessor accessor) {
|
||||
return new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter).createQuery();
|
||||
return new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter, getOperations().getBucketName())
|
||||
.createQuery();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -73,7 +73,8 @@ public class ReactivePartTreeCouchbaseQuery extends AbstractReactiveCouchbaseQue
|
||||
@Override
|
||||
protected Query createQuery(ParametersParameterAccessor accessor) {
|
||||
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter);
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter,
|
||||
getOperations().getBucketName());
|
||||
Query query = creator.createQuery();
|
||||
|
||||
if (tree.isLimiting()) {
|
||||
@@ -91,7 +92,8 @@ public class ReactivePartTreeCouchbaseQuery extends AbstractReactiveCouchbaseQue
|
||||
*/
|
||||
@Override
|
||||
protected Query createCountQuery(ParametersParameterAccessor accessor) {
|
||||
Query query = new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter).createQuery();
|
||||
Query query = new N1qlQueryCreator(tree, accessor, getQueryMethod(), converter, getOperations().getBucketName())
|
||||
.createQuery();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Created query {} for * fields.", query.export());
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ public class ReactiveStringBasedCouchbaseQuery extends AbstractReactiveCouchbase
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(accessor, getQueryMethod(),
|
||||
getOperations().getConverter(), getOperations().getBucketName(), expressionParser, evaluationContextProvider,
|
||||
namedQueries);
|
||||
|
||||
Query query = creator.createQuery();
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors
|
||||
* Copyright 2021 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.
|
||||
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
import com.couchbase.client.java.json.JsonObject;
|
||||
import com.couchbase.client.java.json.JsonValue;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.x;
|
||||
import static org.springframework.data.couchbase.core.query.QueryCriteria.where;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.couchbase.core.query.N1QLExpression;
|
||||
@@ -36,12 +38,13 @@ import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import static org.springframework.data.couchbase.core.query.QueryCriteria.where;
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
import com.couchbase.client.java.json.JsonObject;
|
||||
import com.couchbase.client.java.json.JsonValue;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
* @author Mauro Monti
|
||||
*/
|
||||
public class StringN1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria> {
|
||||
|
||||
@@ -98,10 +101,9 @@ public class StringN1qlQueryCreator extends AbstractQueryCreator<Query, QueryCri
|
||||
|
||||
@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);
|
||||
return from(part, property, where(x(path.toDotPath())), iterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,11 +112,10 @@ public class StringN1qlQueryCreator extends AbstractQueryCreator<Query, QueryCri
|
||||
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);
|
||||
return from(part, property, base.and(x(path.toDotPath())), iterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,10 +140,10 @@ public class StringN1qlQueryCreator extends AbstractQueryCreator<Query, QueryCri
|
||||
|
||||
final Part.Type type = part.getType();
|
||||
switch (type) {
|
||||
case SIMPLE_PROPERTY:
|
||||
return criteria; // this will be the dummy from PartTree
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported keyword!");
|
||||
case SIMPLE_PROPERTY:
|
||||
return criteria; // this will be the dummy from PartTree
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported keyword!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.springframework.data.couchbase.config.BeanNames.COUCHBASE_TEMPLATE;
|
||||
import static org.springframework.data.couchbase.config.BeanNames.REACTIVE_COUCHBASE_TEMPLATE;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.i;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
@@ -60,6 +61,7 @@ import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
* @author Michael Nitschinger
|
||||
* @author Michael Reiche
|
||||
* @author Haris Alesevic
|
||||
* @author Mauro Monti
|
||||
*/
|
||||
@IgnoreWhen(missesCapabilities = Capabilities.QUERY, clusterTypes = ClusterType.MOCKED)
|
||||
class CouchbaseTemplateQueryIntegrationTests extends JavaIntegrationTests {
|
||||
@@ -124,7 +126,7 @@ class CouchbaseTemplateQueryIntegrationTests extends JavaIntegrationTests {
|
||||
|
||||
couchbaseTemplate.upsertById(User.class).all(Arrays.asList(user1, user2, specialUser));
|
||||
|
||||
Query specialUsers = new Query(QueryCriteria.where("firstname").like("special"));
|
||||
Query specialUsers = new Query(QueryCriteria.where(i("firstname")).like("special"));
|
||||
final List<User> foundUsers = couchbaseTemplate.findByQuery(User.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).matching(specialUsers).all();
|
||||
|
||||
@@ -206,7 +208,7 @@ class CouchbaseTemplateQueryIntegrationTests extends JavaIntegrationTests {
|
||||
assertTrue(couchbaseTemplate.existsById().one(user2.getId()));
|
||||
assertTrue(couchbaseTemplate.existsById().one(specialUser.getId()));
|
||||
|
||||
Query nonSpecialUsers = new Query(QueryCriteria.where("firstname").notLike("special"));
|
||||
Query nonSpecialUsers = new Query(QueryCriteria.where(i("firstname")).notLike("special"));
|
||||
|
||||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.matching(nonSpecialUsers).all();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2021 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.
|
||||
@@ -16,57 +16,56 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.query;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.springframework.data.couchbase.core.query.QueryCriteria.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.i;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.meta;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.path;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.x;
|
||||
import static org.springframework.data.couchbase.core.query.QueryCriteria.where;
|
||||
import static org.springframework.data.couchbase.repository.query.support.N1qlUtils.escapedBucket;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
import com.couchbase.client.java.json.JsonObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.couchbase.domain.User;
|
||||
import org.springframework.data.couchbase.domain.UserRepository;
|
||||
import org.springframework.data.couchbase.repository.query.N1qlQueryCreator;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Mauro Monti
|
||||
*/
|
||||
class QueryCriteriaTests {
|
||||
|
||||
@Test
|
||||
void testSimpleCriteria() {
|
||||
QueryCriteria c = where("name").is("Bubba");
|
||||
QueryCriteria c = where(i("name")).is("Bubba");
|
||||
assertEquals("`name` = \"Bubba\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullValue() {
|
||||
QueryCriteria c = where("name").is(null);
|
||||
QueryCriteria c = where(i("name")).is(null);
|
||||
assertEquals("`name` = null", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleNumber() {
|
||||
QueryCriteria c = where("name").is(5);
|
||||
QueryCriteria c = where(i("name")).is(5);
|
||||
assertEquals("`name` = 5", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotEqualCriteria() {
|
||||
QueryCriteria c = where("name").ne("Bubba");
|
||||
QueryCriteria c = where(i("name")).ne("Bubba");
|
||||
assertEquals("`name` != \"Bubba\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChainedCriteria() {
|
||||
QueryCriteria c = where("name").is("Bubba").and("age").lt(21).or("country").is("Austria");
|
||||
QueryCriteria c = where(i("name")).is("Bubba").and(i("age")).lt(21).or(i("country")).is("Austria");
|
||||
assertEquals("`name` = \"Bubba\" and `age` < 21 or `country` = \"Austria\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNestedAndCriteria() {
|
||||
QueryCriteria c = where("name").is("Bubba").and(where("age").gt(12).or("country").is("Austria"));
|
||||
QueryCriteria c = where(i("name")).is("Bubba").and(where(i("age")).gt(12).or(i("country")).is("Austria"));
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("`name` = $1 and (`age` > $2 or `country` = $3)", c.export(new int[1], parameters, null));
|
||||
assertEquals("[\"Bubba\",12,\"Austria\"]", parameters.toString());
|
||||
@@ -74,7 +73,7 @@ class QueryCriteriaTests {
|
||||
|
||||
@Test
|
||||
void testNestedOrCriteria() {
|
||||
QueryCriteria c = where("name").is("Bubba").or(where("age").gt(12).or("country").is("Austria"));
|
||||
QueryCriteria c = where(i("name")).is("Bubba").or(where(i("age")).gt(12).or(i("country")).is("Austria"));
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("`name` = $1 or (`age` > $2 or `country` = $3)", c.export(new int[1], parameters, null));
|
||||
assertEquals("[\"Bubba\",12,\"Austria\"]", parameters.toString());
|
||||
@@ -82,45 +81,45 @@ class QueryCriteriaTests {
|
||||
|
||||
@Test
|
||||
void testNestedNotIn() {
|
||||
QueryCriteria c = where("name").is("Bubba").or(where("age").gt(12).or("country").is("Austria"))
|
||||
.and(where("state").notIn(new String[] { "Alabama", "Florida" }));
|
||||
QueryCriteria c = where(i("name")).is("Bubba").or(where(i("age")).gt(12).or(i("country")).is("Austria"))
|
||||
.and(where(i("state")).notIn(new String[] { "Alabama", "Florida" }));
|
||||
assertEquals("`name` = \"Bubba\" or (`age` > 12 or `country` = \"Austria\") and "
|
||||
+ "(not( (`state` in ( [\"Alabama\",\"Florida\"] )) ))", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLt() {
|
||||
QueryCriteria c = where("name").lt("Couch");
|
||||
QueryCriteria c = where(i("name")).lt("Couch");
|
||||
assertEquals("`name` < \"Couch\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLte() {
|
||||
QueryCriteria c = where("name").lte("Couch");
|
||||
QueryCriteria c = where(i("name")).lte("Couch");
|
||||
assertEquals("`name` <= \"Couch\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGt() {
|
||||
QueryCriteria c = where("name").gt("Couch");
|
||||
QueryCriteria c = where(i("name")).gt("Couch");
|
||||
assertEquals("`name` > \"Couch\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGte() {
|
||||
QueryCriteria c = where("name").gte("Couch");
|
||||
QueryCriteria c = where(i("name")).gte("Couch");
|
||||
assertEquals("`name` >= \"Couch\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNe() {
|
||||
QueryCriteria c = where("name").ne("Couch");
|
||||
QueryCriteria c = where(i("name")).ne("Couch");
|
||||
assertEquals("`name` != \"Couch\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStartingWith() {
|
||||
QueryCriteria c = where("name").startingWith("Cou");
|
||||
QueryCriteria c = where(i("name")).startingWith("Cou");
|
||||
assertEquals("`name` like (\"Cou\"||\"%\")", c.export());
|
||||
}
|
||||
|
||||
@@ -128,99 +127,99 @@ class QueryCriteriaTests {
|
||||
* startingWith() cannot be a QueryCriteria
|
||||
@Test
|
||||
void testStartingWithExpr() {
|
||||
QueryCriteria c = where("name").startingWith(where("name").plus("xxx"));
|
||||
QueryCriteria c = where(i("name")).startingWith(where(i("name")).plus("xxx"));
|
||||
assertEquals("`name` like (((`name` || "xxx") || ""%""))", c.export());
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
void testEndingWith() {
|
||||
QueryCriteria c = where("name").endingWith("ouch");
|
||||
QueryCriteria c = where(i("name")).endingWith("ouch");
|
||||
assertEquals("`name` like (\"%\"||\"ouch\")", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEndingWithExpr() {
|
||||
QueryCriteria c = where("name").endingWith(where("name").plus("xxx"));
|
||||
QueryCriteria c = where(i("name")).endingWith(where(i("name")).plus("xxx"));
|
||||
assertEquals("`name` like (\"%\"||((`name` || \"xxx\")))", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegex() {
|
||||
QueryCriteria c = where("name").regex("C.*h");
|
||||
QueryCriteria c = where(i("name")).regex("C.*h");
|
||||
assertEquals("regexp_like(`name`, \"C.*h\")", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContaining() {
|
||||
QueryCriteria c = where("name").containing("ouch");
|
||||
QueryCriteria c = where(i("name")).containing("ouch");
|
||||
assertEquals("contains(`name`, \"ouch\")", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotContaining() {
|
||||
QueryCriteria c = where("name").notContaining("Elvis");
|
||||
QueryCriteria c = where(i("name")).notContaining("Elvis");
|
||||
assertEquals("not( (contains(`name`, \"Elvis\")) )", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLike() {
|
||||
QueryCriteria c = where("name").like("%ouch%");
|
||||
QueryCriteria c = where(i("name")).like("%ouch%");
|
||||
assertEquals("`name` like \"%ouch%\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotLike() {
|
||||
QueryCriteria c = where("name").notLike("%Elvis%");
|
||||
QueryCriteria c = where(i("name")).notLike("%Elvis%");
|
||||
assertEquals("not(`name` like \"%Elvis%\")", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsNull() {
|
||||
QueryCriteria c = where("name").isNull();
|
||||
QueryCriteria c = where(i("name")).isNull();
|
||||
assertEquals("`name` is null", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsNotNull() {
|
||||
QueryCriteria c = where("name").isNotNull();
|
||||
QueryCriteria c = where(i("name")).isNotNull();
|
||||
assertEquals("`name` is not null", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsMissing() {
|
||||
QueryCriteria c = where("name").isMissing();
|
||||
QueryCriteria c = where(i("name")).isMissing();
|
||||
assertEquals("`name` is missing", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsNotMissing() {
|
||||
QueryCriteria c = where("name").isNotMissing();
|
||||
QueryCriteria c = where(i("name")).isNotMissing();
|
||||
assertEquals("`name` is not missing", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsValued() {
|
||||
QueryCriteria c = where("name").isValued();
|
||||
QueryCriteria c = where(i("name")).isValued();
|
||||
assertEquals("`name` is valued", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsNotValued() {
|
||||
QueryCriteria c = where("name").isNotValued();
|
||||
QueryCriteria c = where(i("name")).isNotValued();
|
||||
assertEquals("`name` is not valued", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBetween() {
|
||||
QueryCriteria c = where("name").between("Davis", "Gump");
|
||||
QueryCriteria c = where(i("name")).between("Davis", "Gump");
|
||||
assertEquals("`name` between \"Davis\" and \"Gump\"", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIn() {
|
||||
String[] args = new String[] { "gump", "davis" };
|
||||
QueryCriteria c = where("name").in(args);
|
||||
QueryCriteria c = where(i("name")).in(args);
|
||||
assertEquals("`name` in ( [\"gump\",\"davis\"] )", c.export());
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("`name` in ( $1 )", c.export(new int[1], parameters, null));
|
||||
@@ -230,7 +229,7 @@ class QueryCriteriaTests {
|
||||
@Test
|
||||
void testNotIn() {
|
||||
String[] args = new String[] { "gump", "davis" };
|
||||
QueryCriteria c = where("name").notIn(args);
|
||||
QueryCriteria c = where(i("name")).notIn(args);
|
||||
assertEquals("not( (`name` in ( [\"gump\",\"davis\"] )) )", c.export());
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("not( (`name` in ( $1 )) )", c.export(new int[1], parameters, null));
|
||||
@@ -239,16 +238,32 @@ class QueryCriteriaTests {
|
||||
|
||||
@Test
|
||||
void testTrue() {
|
||||
QueryCriteria c = where("name").TRUE();
|
||||
QueryCriteria c = where(i("name")).TRUE();
|
||||
assertEquals("`name`", c.export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFalse() {
|
||||
QueryCriteria c = where("name").FALSE();
|
||||
QueryCriteria c = where(i("name")).FALSE();
|
||||
assertEquals("not( (`name`) )", c.export());
|
||||
}
|
||||
|
||||
@Test // https://github.com/spring-projects/spring-data-couchbase/issues/1066
|
||||
void testCriteriaCorrectlyEscapedWhenUsingMetaOnLHS() {
|
||||
final String bucketName = "sample-bucket";
|
||||
final String version = "1611287177404088320";
|
||||
QueryCriteria criteria = QueryCriteria.where(path(meta(escapedBucket(bucketName)), "cas")).eq(x(version));
|
||||
assertEquals("META(`" + bucketName + "`).cas = " + x(version), criteria.export());
|
||||
}
|
||||
|
||||
@Test // https://github.com/spring-projects/spring-data-couchbase/issues/1066
|
||||
void testCriteriaCorrectlyEscapedWhenUsingMetaOnRHS() {
|
||||
final String bucketName = "sample-bucket";
|
||||
final String version = "1611287177404088320";
|
||||
QueryCriteria criteria = QueryCriteria.where(x(version)).eq(path(meta(escapedBucket(bucketName)), "cas"));
|
||||
assertEquals(x(version) + " = META(`" + bucketName + "`).cas", criteria.export());
|
||||
}
|
||||
|
||||
private String arrayToString(Object[] array) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (array != null) {
|
||||
|
||||
@@ -19,12 +19,12 @@ package org.springframework.data.couchbase.domain;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.couchbase.repository.CouchbaseRepository;
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
import org.springframework.data.couchbase.repository.Query;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
|
||||
/**
|
||||
* User Repository for tests
|
||||
*
|
||||
@@ -47,4 +47,8 @@ public interface UserRepository extends CouchbaseRepository<User, String> {
|
||||
|
||||
@Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and (firstname = $first or lastname = $last)")
|
||||
List<User> getByFirstnameOrLastname(@Param("first") String firstname, @Param("last") String lastname);
|
||||
|
||||
List<User> findByIdIsNotNullAndFirstnameEquals(String firstname);
|
||||
|
||||
List<User> findByVersionEqualsAndFirstnameEquals(Long version, String firstname);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package org.springframework.data.couchbase.repository;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -49,14 +52,12 @@ import org.springframework.data.couchbase.util.Capabilities;
|
||||
import org.springframework.data.couchbase.util.ClusterAwareIntegrationTests;
|
||||
import org.springframework.data.couchbase.util.ClusterType;
|
||||
import org.springframework.data.couchbase.util.IgnoreWhen;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import com.couchbase.client.core.error.IndexExistsException;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* Repository tests
|
||||
@@ -173,7 +174,9 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
|
||||
try {
|
||||
|
||||
airportRepository.saveAll( Arrays.stream(iatas).map((iata) -> new Airport("airports::"+iata, iata, iata.toLowerCase(Locale.ROOT))).collect(Collectors.toSet()));
|
||||
airportRepository.saveAll(
|
||||
Arrays.stream(iatas).map((iata) -> new Airport("airports::" + iata, iata, iata.toLowerCase(Locale.ROOT)))
|
||||
.collect(Collectors.toSet()));
|
||||
Long count = airportRepository.countFancyExpression(asList("JFK"), asList("jfk"), false);
|
||||
assertEquals(1, count);
|
||||
|
||||
@@ -198,7 +201,8 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
assertEquals(0, airportCount);
|
||||
|
||||
} finally {
|
||||
airportRepository.deleteAllById(Arrays.stream(iatas).map((iata) -> "airports::"+iata).collect(Collectors.toSet()));
|
||||
airportRepository
|
||||
.deleteAllById(Arrays.stream(iatas).map((iata) -> "airports::" + iata).collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +299,6 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
|
||||
airportRepository.deleteAllById(asList(vienna.getId(), losAngeles.getId()));
|
||||
|
||||
|
||||
assertThat(airportRepository.findAll()).containsExactly(frankfurt);
|
||||
} finally {
|
||||
airportRepository.deleteAll();
|
||||
@@ -305,9 +308,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
private void sleep(int millis) {
|
||||
try {
|
||||
Thread.sleep(millis); // so they are executed out-of-order
|
||||
} catch (InterruptedException ie) {
|
||||
;
|
||||
}
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2021 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.
|
||||
@@ -15,17 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.springframework.data.couchbase.core.query.QueryCriteria.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.i;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.x;
|
||||
import static org.springframework.data.couchbase.core.query.QueryCriteria.where;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
import com.couchbase.client.java.json.JsonObject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
@@ -37,22 +35,31 @@ import org.springframework.data.couchbase.core.query.Query;
|
||||
import org.springframework.data.couchbase.domain.User;
|
||||
import org.springframework.data.couchbase.domain.UserRepository;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.query.*;
|
||||
import org.springframework.data.repository.query.DefaultParameters;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
import com.couchbase.client.java.json.JsonObject;
|
||||
|
||||
/**
|
||||
* @author Michael Nitschinger
|
||||
* @author Michael Reiche
|
||||
* @author Mauro Monti
|
||||
*/
|
||||
class N1qlQueryCreatorTests {
|
||||
|
||||
MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> context;
|
||||
CouchbaseConverter converter;
|
||||
String bucketName;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
context = new CouchbaseMappingContext();
|
||||
converter = new MappingCouchbaseConverter(context);
|
||||
bucketName = "sample-bucket";
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -61,11 +68,11 @@ class N1qlQueryCreatorTests {
|
||||
PartTree tree = new PartTree(input, User.class);
|
||||
Method method = UserRepository.class.getMethod(input, String.class);
|
||||
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), "Oliver"), null,
|
||||
converter);
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), "Oliver"), null, converter,
|
||||
bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
assertEquals(query.export(), " WHERE " + where("firstname").is("Oliver").export());
|
||||
assertEquals(query.export(), " WHERE " + where(i("firstname")).is("Oliver").export());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,9 +80,10 @@ class N1qlQueryCreatorTests {
|
||||
String input = "findByFirstnameIn";
|
||||
PartTree tree = new PartTree(input, User.class);
|
||||
Method method = UserRepository.class.getMethod(input, String[].class);
|
||||
Query expected = (new Query()).addCriteria(where("firstname").in("Oliver", "Charles"));
|
||||
Query expected = (new Query()).addCriteria(where(i("firstname")).in("Oliver", "Charles"));
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree,
|
||||
getAccessor(getParameters(method), new Object[] { new Object[] { "Oliver", "Charles" } }), null, converter);
|
||||
getAccessor(getParameters(method), new Object[] { new Object[] { "Oliver", "Charles" } }), null, converter,
|
||||
bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
// Query expected = (new Query()).addCriteria(where("firstname").in("Oliver", "Charles"));
|
||||
@@ -97,10 +105,10 @@ class N1qlQueryCreatorTests {
|
||||
jsonArray.add("Oliver");
|
||||
jsonArray.add("Charles");
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), jsonArray), null,
|
||||
converter);
|
||||
converter, bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
Query expected = (new Query()).addCriteria(where("firstname").in("Oliver", "Charles"));
|
||||
Query expected = (new Query()).addCriteria(where(i("firstname")).in("Oliver", "Charles"));
|
||||
assertEquals(expected.export(new int[1]), query.export(new int[1]));
|
||||
JsonObject expectedOptions = JsonObject.create();
|
||||
expected.buildQueryOptions(null).build().injectParams(expectedOptions);
|
||||
@@ -118,10 +126,10 @@ class N1qlQueryCreatorTests {
|
||||
list.add("Oliver");
|
||||
list.add("Charles");
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), new Object[] { list }),
|
||||
null, converter);
|
||||
null, converter, bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
Query expected = (new Query()).addCriteria(where("firstname").in("Oliver", "Charles"));
|
||||
Query expected = (new Query()).addCriteria(where(i("firstname")).in("Oliver", "Charles"));
|
||||
|
||||
assertEquals(expected.export(new int[1]), query.export(new int[1]));
|
||||
JsonObject expectedOptions = JsonObject.create();
|
||||
@@ -137,10 +145,38 @@ class N1qlQueryCreatorTests {
|
||||
PartTree tree = new PartTree(input, User.class);
|
||||
Method method = UserRepository.class.getMethod(input, String.class, String.class);
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), "John", "Doe"), null,
|
||||
converter);
|
||||
converter, bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
assertEquals(" WHERE " + where("firstname").is("John").and("lastname").is("Doe").export(), query.export());
|
||||
assertEquals(" WHERE " + where(i("firstname")).is("John").and(i("lastname")).is("Doe").export(), query.export());
|
||||
}
|
||||
|
||||
@Test // https://github.com/spring-projects/spring-data-couchbase/issues/1072
|
||||
void createsQueryFindByIdIsNotNullAndFirstname() throws Exception {
|
||||
String input = "findByIdIsNotNullAndFirstnameEquals";
|
||||
PartTree tree = new PartTree(input, User.class);
|
||||
Method method = UserRepository.class.getMethod(input, String.class);
|
||||
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), "Oliver"), null, converter,
|
||||
bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
assertEquals(query.export(),
|
||||
" WHERE " + where(x("META(`" + bucketName + "`).`id`")).isNotNull().and(i("firstname")).is("Oliver").export());
|
||||
}
|
||||
|
||||
@Test // https://github.com/spring-projects/spring-data-couchbase/issues/1072
|
||||
void createsQueryFindByVersionEqualsAndAndFirstname() throws Exception {
|
||||
String input = "findByVersionEqualsAndFirstnameEquals";
|
||||
PartTree tree = new PartTree(input, User.class);
|
||||
Method method = UserRepository.class.getMethod(input, Long.class, String.class);
|
||||
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree,
|
||||
getAccessor(getParameters(method), 1611287177404088320L, "Oliver"), null, converter, bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
assertEquals(query.export(), " WHERE " + where(x("META(`" + bucketName + "`).`cas`")).is(1611287177404088320L)
|
||||
.and(i("firstname")).is("Oliver").export());
|
||||
}
|
||||
|
||||
private ParameterAccessor getAccessor(Parameters<?, ?> params, Object... values) {
|
||||
|
||||
Reference in New Issue
Block a user