Skip to content

Commit 03cacc3

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 66fc163 commit 03cacc3

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
@@ -27,6 +27,9 @@
2727
public interface AirlineRepository extends PagingAndSortingRepository<Airline, String> {
2828

2929
@Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and (name = $1)")
30-
List<User> getByName(@Param("airline_name")String airlineName);
30+
List<Airline> getByName(@Param("airline_name") String airlineName);
31+
32+
@Query("select meta().id as _ID, meta().cas as _CAS, #{#n1ql.bucket}.* from #{#n1ql.bucket} where #{#n1ql.filter} and (name = $1)")
33+
List<Airline> getByName_3x(@Param("airline_name") String airlineName);
3134

3235
}

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
@@ -112,6 +112,39 @@ queryMethod, converter, config().bucketname(), new SpelExpressionParser(),
112112
}
113113
}
114114

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

0 commit comments

Comments
 (0)