Collection support for predicates on meta fields. (#1338)
When a derived query is being created and there is a predicate on a meta-field ( meta().id, cas, expiry), translate that field (i.e. id -> meta().id) *without* the bucket or collection name, as it might apply to a collelction which we do not know yet (for instance, if there is a withCollection() specified).. This is fine, because in a derived query, meta() without the bucket or collection name is unambigous.
This commit is contained in:
committed by
Michael Reiche
parent
9048c7ca82
commit
6ebb0dd20e
@@ -76,7 +76,7 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
|
|||||||
protected QueryCriteria create(final Part part, final Iterator<Object> iterator) {
|
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();
|
CouchbasePersistentProperty property = path.getLeafProperty();
|
||||||
return from(part, property, where(addMetaIfRequired(bucketName, path, property, entity)), iterator);
|
return from(part, property, where(addMetaIfRequired(null, path, property, entity)), iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -187,17 +187,28 @@ public class N1qlQueryCreator extends AbstractQueryCreator<Query, QueryCriteria>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate meta-fields to META(bucketName).id, cas, expiry.<br>
|
||||||
|
* If bucketName is null, META().id etc, <br>
|
||||||
|
* If not a meta-field, just create the corresponding path
|
||||||
|
*
|
||||||
|
* @param bucketName
|
||||||
|
* @param persistentPropertyPath
|
||||||
|
* @param property
|
||||||
|
* @param entity
|
||||||
|
* @return N1QLExpression
|
||||||
|
*/
|
||||||
public static N1QLExpression addMetaIfRequired(String bucketName,
|
public static N1QLExpression addMetaIfRequired(String bucketName,
|
||||||
final PersistentPropertyPath<CouchbasePersistentProperty> persistentPropertyPath,
|
final PersistentPropertyPath<CouchbasePersistentProperty> persistentPropertyPath,
|
||||||
final CouchbasePersistentProperty property, final PersistentEntity entity) {
|
final CouchbasePersistentProperty property, final PersistentEntity entity) {
|
||||||
if (entity != null && property == entity.getIdProperty()) {
|
if (entity != null && property == entity.getIdProperty()) {
|
||||||
return path(meta(i(bucketName)), i(META_ID_PROPERTY));
|
return path(meta(bucketName != null ? i(bucketName) : x("")), i(META_ID_PROPERTY));
|
||||||
}
|
}
|
||||||
if (property == entity.getVersionProperty()) {
|
if (property == entity.getVersionProperty()) {
|
||||||
return path(meta(i(bucketName)), i(META_CAS_PROPERTY));
|
return path(meta(bucketName != null ? i(bucketName) : x("")), i(META_CAS_PROPERTY));
|
||||||
}
|
}
|
||||||
if (property.isExpirationProperty()) {
|
if (property.isExpirationProperty()) {
|
||||||
return path(meta(i(bucketName)), i(META_EXPIRATION_PROPERTY));
|
return path(meta(bucketName != null ? i(bucketName) : x("")), i(META_EXPIRATION_PROPERTY));
|
||||||
}
|
}
|
||||||
return x(persistentPropertyPath.toDotPath(cvtr));
|
return x(persistentPropertyPath.toDotPath(cvtr));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors
|
* Copyright 2012-2022 the original author or authors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -40,10 +40,13 @@ public interface UserColRepository extends CouchbaseRepository<UserCol, String>,
|
|||||||
|
|
||||||
// CouchbaseRepositoryQueryCollectionIntegrationTests.testScopeCollectionAnnotationSwap() relies on this
|
// CouchbaseRepositoryQueryCollectionIntegrationTests.testScopeCollectionAnnotationSwap() relies on this
|
||||||
// being commented out.
|
// being commented out.
|
||||||
//<S extends UserCol> S save(S var1);
|
// <S extends UserCol> S save(S var1);
|
||||||
|
|
||||||
List<UserCol> findByFirstname(String firstname);
|
List<UserCol> findByFirstname(String firstname);
|
||||||
|
|
||||||
|
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
|
||||||
|
UserCol getById(String id);
|
||||||
|
|
||||||
List<UserCol> findByFirstnameIn(String... firstnames);
|
List<UserCol> findByFirstnameIn(String... firstnames);
|
||||||
|
|
||||||
List<UserCol> findByFirstnameIn(JsonArray firstnames);
|
List<UserCol> findByFirstnameIn(JsonArray firstnames);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2021 the original author or authors.
|
* Copyright 2017-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -91,6 +91,16 @@ public class CouchbaseRepositoryQueryCollectionIntegrationTests extends Collecti
|
|||||||
super.afterEach();
|
super.afterEach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void findByKey() {
|
||||||
|
UserCol userCol = new UserCol("101", "userColFirst", "userColLast");
|
||||||
|
userColRepository.save(userCol);
|
||||||
|
UserCol found = userColRepository.getById(userCol.getId());
|
||||||
|
System.err.println("found: " + found);
|
||||||
|
assertEquals(userCol, found);
|
||||||
|
userColRepository.delete(found);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void myTest() {
|
public void myTest() {
|
||||||
|
|
||||||
|
|||||||
@@ -189,8 +189,8 @@ class N1qlQueryCreatorTests {
|
|||||||
converter, bucketName);
|
converter, bucketName);
|
||||||
Query query = creator.createQuery();
|
Query query = creator.createQuery();
|
||||||
|
|
||||||
assertEquals(query.export(),
|
assertEquals(" WHERE " + where(x("META().`id`")).isNotNull().and(i("firstname")).is("Oliver").export(),
|
||||||
" WHERE " + where(x("META(`" + bucketName + "`).`id`")).isNotNull().and(i("firstname")).is("Oliver").export());
|
query.export());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // https://github.com/spring-projects/spring-data-couchbase/issues/1072
|
@Test // https://github.com/spring-projects/spring-data-couchbase/issues/1072
|
||||||
@@ -204,8 +204,9 @@ class N1qlQueryCreatorTests {
|
|||||||
getAccessor(getParameters(method), 1611287177404088320L, "Oliver"), queryMethod, converter, bucketName);
|
getAccessor(getParameters(method), 1611287177404088320L, "Oliver"), queryMethod, converter, bucketName);
|
||||||
Query query = creator.createQuery();
|
Query query = creator.createQuery();
|
||||||
|
|
||||||
assertEquals(query.export(), " WHERE " + where(x("META(`" + bucketName + "`).`cas`")).is(1611287177404088320L)
|
assertEquals(
|
||||||
.and(i("firstname")).is("Oliver").export());
|
" WHERE " + where(x("META().`cas`")).is(1611287177404088320L).and(i("firstname")).is("Oliver").export(),
|
||||||
|
query.export());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ParameterAccessor getAccessor(Parameters<?, ?> params, Object... values) {
|
private ParameterAccessor getAccessor(Parameters<?, ?> params, Object... values) {
|
||||||
|
|||||||
Reference in New Issue
Block a user