Skip to content

Commit 9fe8472

Browse files
committed
Check for _ID and _CAS as well as __id and __cas being projected from query and analytics. (#1390)
Closes #1389.
1 parent baf198c commit 9fe8472

File tree

5 files changed

+62
-8
lines changed

5 files changed

+62
-8
lines changed

src/main/java/org/springframework/data/couchbase/core/ReactiveFindByAnalyticsOperationSupport.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,27 @@ public Flux<T> all() {
118118
}
119119
}).flatMapMany(ReactiveAnalyticsResult::rowsAsObject).flatMap(row -> {
120120
String id = "";
121-
long cas = 0;
122-
if (row.getString(TemplateUtils.SELECT_ID) == null) {
121+
Long cas = Long.valueOf(0);
122+
if (row.getString(TemplateUtils.SELECT_ID) == null && row.getString(TemplateUtils.SELECT_ID_3x) == null) {
123123
return Flux.error(new CouchbaseException("analytics query did not project " + TemplateUtils.SELECT_ID
124124
+ ". Either use #{#n1ql.selectEntity} or project " + TemplateUtils.SELECT_ID + " and "
125125
+ TemplateUtils.SELECT_CAS + " : " + statement));
126126
}
127127
id = row.getString(TemplateUtils.SELECT_ID);
128-
if (row.getLong(TemplateUtils.SELECT_CAS) == null) {
128+
if (id == null) {
129+
id = row.getString(TemplateUtils.SELECT_ID_3x);
130+
row.removeKey(TemplateUtils.SELECT_ID_3x);
131+
}
132+
if (row.getLong(TemplateUtils.SELECT_CAS) == null && row.getLong(TemplateUtils.SELECT_CAS_3x) == null) {
129133
return Flux.error(new CouchbaseException("analytics query did not project " + TemplateUtils.SELECT_CAS
130134
+ ". Either use #{#n1ql.selectEntity} or project " + TemplateUtils.SELECT_ID + " and "
131135
+ TemplateUtils.SELECT_CAS + " : " + statement));
132136
}
133137
cas = row.getLong(TemplateUtils.SELECT_CAS);
138+
if (cas == null) {
139+
cas = row.getLong(TemplateUtils.SELECT_CAS_3x);
140+
row.removeKey(TemplateUtils.SELECT_CAS_3x);
141+
}
134142
row.removeKey(TemplateUtils.SELECT_ID);
135143
row.removeKey(TemplateUtils.SELECT_CAS);
136144
return support.decodeEntity(id, row.toString(), cas, returnType, null, null);

src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static class ReactiveFindByQuerySupport<T> implements ReactiveFindByQuery<T> {
9090
public FindByQueryWithQuery<T> matching(Query query) {
9191
QueryScanConsistency scanCons;
9292
if (query.getScanConsistency() != null) { // redundant, since buildQueryOptions() will use
93-
// query.getScanConsistency()
93+
// query.getScanConsistency()
9494
scanCons = query.getScanConsistency();
9595
} else {
9696
scanCons = scanConsistency;
@@ -185,20 +185,28 @@ public Flux<T> all() {
185185
}
186186
}).flatMapMany(ReactiveQueryResult::rowsAsObject).flatMap(row -> {
187187
String id = "";
188-
long cas = 0;
188+
Long cas = Long.valueOf(0);
189189
if (!query.isDistinct() && distinctFields == null) {
190-
if (row.getString(TemplateUtils.SELECT_ID) == null) {
190+
if (row.getString(TemplateUtils.SELECT_ID) == null && row.getString(TemplateUtils.SELECT_ID_3x) == null) {
191191
return Flux.error(new CouchbaseException(
192192
"query did not project " + TemplateUtils.SELECT_ID + ". Either use #{#n1ql.selectEntity} or project "
193193
+ TemplateUtils.SELECT_ID + " and " + TemplateUtils.SELECT_CAS + " : " + statement));
194194
}
195195
id = row.getString(TemplateUtils.SELECT_ID);
196-
if (row.getLong(TemplateUtils.SELECT_CAS) == null) {
196+
if (id == null) {
197+
id = row.getString(TemplateUtils.SELECT_ID_3x);
198+
row.removeKey(TemplateUtils.SELECT_ID_3x);
199+
}
200+
if (row.getLong(TemplateUtils.SELECT_CAS) == null && row.getLong(TemplateUtils.SELECT_CAS_3x) == null) {
197201
return Flux.error(new CouchbaseException(
198202
"query did not project " + TemplateUtils.SELECT_CAS + ". Either use #{#n1ql.selectEntity} or project "
199203
+ TemplateUtils.SELECT_ID + " and " + TemplateUtils.SELECT_CAS + " : " + statement));
200204
}
201205
cas = row.getLong(TemplateUtils.SELECT_CAS);
206+
if (cas == null) {
207+
cas = row.getLong(TemplateUtils.SELECT_CAS_3x);
208+
row.removeKey(TemplateUtils.SELECT_CAS_3x);
209+
}
202210
row.removeKey(TemplateUtils.SELECT_ID);
203211
row.removeKey(TemplateUtils.SELECT_CAS);
204212
}

src/main/java/org/springframework/data/couchbase/core/support/TemplateUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
public class TemplateUtils {
3333
public static final String SELECT_ID = "__id";
3434
public static final String SELECT_CAS = "__cas";
35+
public static final String SELECT_ID_3x = "_ID";
36+
public static final String SELECT_CAS_3x = "_CAS";
3537
public static final String SELECT_COUNT = CountFragment.COUNT_ALIAS;
3638
private static PersistenceExceptionTranslator exceptionTranslator = new CouchbaseExceptionTranslator();
3739

src/test/java/org/springframework/data/couchbase/domain/AirlineRepository.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public interface AirlineRepository extends PagingAndSortingRepository<Airline, S
3333
QuerydslPredicateExecutor<Airline>, DynamicProxyable<AirlineRepository> {
3434

3535
@Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and (name = $1)")
36-
List<User> getByName(@Param("airline_name") String airlineName);
36+
List<Airline> getByName(@Param("airline_name") String airlineName);
37+
38+
@Query("select meta().id as _ID, meta().cas as _CAS, #{#n1ql.bucket}.* from #{#n1ql.bucket} where #{#n1ql.filter} and (name = $1)")
39+
List<Airline> getByName_3x(@Param("airline_name") String airlineName);
3740

3841
}

src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,39 @@ queryMethod, converter, config().bucketname(), new SpelExpressionParser(),
116116
}
117117
}
118118

119+
@Test
120+
@IgnoreWhen(missesCapabilities = Capabilities.QUERY, clusterTypes = ClusterType.MOCKED)
121+
void findUsingStringNq1l_3x_projection_id_cas() throws Exception {
122+
Airline airline = new Airline(UUID.randomUUID().toString(), "Continental", "USA");
123+
try {
124+
Airline modified = couchbaseTemplate.upsertById(Airline.class).one(airline);
125+
126+
String input = "getByName_3x";
127+
Method method = AirlineRepository.class.getMethod(input, String.class);
128+
129+
CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method,
130+
new DefaultRepositoryMetadata(AirlineRepository.class), new SpelAwareProxyProjectionFactory(),
131+
converter.getMappingContext());
132+
133+
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Continental"),
134+
queryMethod, converter, config().bucketname(), new SpelExpressionParser(),
135+
QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
136+
137+
Query query = creator.createQuery();
138+
139+
ExecutableFindByQuery q = (ExecutableFindByQuery) couchbaseTemplate.findByQuery(Airline.class)
140+
.withConsistency(QueryScanConsistency.REQUEST_PLUS).matching(query);
141+
142+
Optional<Airline> al = q.one();
143+
assertEquals(airline.toString(), al.get().toString());
144+
} catch (Exception e) {
145+
e.printStackTrace();
146+
throw e;
147+
} finally {
148+
couchbaseTemplate.removeById().one(airline.getId());
149+
}
150+
}
151+
119152
private ParameterAccessor getAccessor(Parameters<?, ?> params, Object... values) {
120153
return new ParametersParameterAccessor(params, values);
121154
}

0 commit comments

Comments
 (0)