Skip to content

Commit 7854edd

Browse files
committed
Specific message for string queries that do not project __id and __cas.
com.couchbase.client.core.error.CouchbaseException: query did not project __id. Either use #{#n1ql.selectEntity} or project __id and __cas : SELECT __cas, * from `b406ab45-ef95-441f-a318-76b8e8af2d76` where iata = $1 Closes #1097. Original pull request: #1114.
1 parent 4a900b8 commit 7854edd

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

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

+18-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import reactor.core.publisher.Mono;
2020

2121
import org.springframework.data.couchbase.core.query.AnalyticsQuery;
22+
import org.springframework.data.couchbase.core.support.TemplateUtils;
2223

24+
import com.couchbase.client.core.error.CouchbaseException;
2325
import com.couchbase.client.java.analytics.AnalyticsOptions;
2426
import com.couchbase.client.java.analytics.AnalyticsScanConsistency;
2527
import com.couchbase.client.java.analytics.ReactiveAnalyticsResult;
@@ -92,10 +94,22 @@ public Flux<T> all() {
9294
return throwable;
9395
}
9496
}).flatMapMany(ReactiveAnalyticsResult::rowsAsObject).map(row -> {
95-
String id = row.getString("__id");
96-
long cas = row.getLong("__cas");
97-
row.removeKey("__id");
98-
row.removeKey("__cas");
97+
String id = "";
98+
long cas = 0;
99+
if (row.getString(TemplateUtils.SELECT_ID) == null) {
100+
throw new CouchbaseException("query did not project " + TemplateUtils.SELECT_ID
101+
+ ". Either use #{#n1ql.selectEntity} or project " + TemplateUtils.SELECT_ID + " and "
102+
+ TemplateUtils.SELECT_CAS + " : " + statement);
103+
}
104+
id = row.getString(TemplateUtils.SELECT_ID);
105+
if (row.getLong(TemplateUtils.SELECT_CAS) == null) {
106+
throw new CouchbaseException("query did not project " + TemplateUtils.SELECT_CAS
107+
+ ". Either use #{#n1ql.selectEntity} or project " + TemplateUtils.SELECT_ID + " and "
108+
+ TemplateUtils.SELECT_CAS + " : " + statement);
109+
}
110+
cas = row.getLong(TemplateUtils.SELECT_CAS);
111+
row.removeKey(TemplateUtils.SELECT_ID);
112+
row.removeKey(TemplateUtils.SELECT_CAS);
99113
return template.support().decodeEntity(id, row.toString(), cas, domainType);
100114
});
101115
});

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

+11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.data.couchbase.core.support.TemplateUtils;
2323
import org.springframework.util.Assert;
2424

25+
import com.couchbase.client.core.error.CouchbaseException;
2526
import com.couchbase.client.java.query.QueryScanConsistency;
2627
import com.couchbase.client.java.query.ReactiveQueryResult;
2728

@@ -147,7 +148,17 @@ public Flux<T> all() {
147148
String id = "";
148149
long cas = 0;
149150
if (distinctFields == null) {
151+
if (row.getString(TemplateUtils.SELECT_ID) == null) {
152+
throw new CouchbaseException(
153+
"query did not project " + TemplateUtils.SELECT_ID + ". Either use #{#n1ql.selectEntity} or project "
154+
+ TemplateUtils.SELECT_ID + " and " + TemplateUtils.SELECT_CAS + " : " + statement);
155+
}
150156
id = row.getString(TemplateUtils.SELECT_ID);
157+
if (row.getLong(TemplateUtils.SELECT_CAS) == null) {
158+
throw new CouchbaseException(
159+
"query did not project " + TemplateUtils.SELECT_CAS + ". Either use #{#n1ql.selectEntity} or project "
160+
+ TemplateUtils.SELECT_ID + " and " + TemplateUtils.SELECT_CAS + " : " + statement);
161+
}
151162
cas = row.getLong(TemplateUtils.SELECT_CAS);
152163
row.removeKey(TemplateUtils.SELECT_ID);
153164
row.removeKey(TemplateUtils.SELECT_CAS);

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

+8
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ public interface AirportRepository extends PagingAndSortingRepository<Airport, S
5757
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
5858
List<Airport> getAllByIata(String iata);
5959

60+
@Query("SELECT __cas, * from `#{#n1ql.bucket}` where iata = $1")
61+
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
62+
List<Airport> getAllByIataNoID(String iata);
63+
64+
@Query("SELECT __id, * from `#{#n1ql.bucket}` where iata = $1")
65+
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
66+
List<Airport> getAllByIataNoCAS(String iata);
67+
6068
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
6169
long countByIataIn(String... iata);
6270

src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import java.util.concurrent.Future;
3535
import java.util.stream.Collectors;
3636

37-
import com.couchbase.client.java.query.QueryScanConsistency;
3837
import org.junit.jupiter.api.BeforeEach;
3938
import org.junit.jupiter.api.Test;
4039
import org.springframework.beans.factory.annotation.Autowired;
@@ -66,7 +65,9 @@
6665
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
6766
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
6867

68+
import com.couchbase.client.core.error.CouchbaseException;
6969
import com.couchbase.client.core.error.IndexExistsException;
70+
import com.couchbase.client.java.query.QueryScanConsistency;
7071

7172
/**
7273
* Repository tests
@@ -180,6 +181,7 @@ void findByEnum() {
180181
airportRepository.delete(vie);
181182
}
182183
}
184+
183185
@Test
184186
public void testCas() {
185187
User user = new User("1", "Dave", "Wilson");
@@ -271,6 +273,19 @@ void threadSafeParametersTest() throws Exception {
271273
}
272274
}
273275

276+
@Test
277+
void stringQueryTest() throws Exception {
278+
Airport airport = new Airport("airports::vie", "vie", "lowx");
279+
try {
280+
airportRepository.save(airport);
281+
airportRepository.getAllByIata("vie").get(0); // gets at least one with no exception
282+
assertThrows(CouchbaseException.class, () -> airportRepository.getAllByIataNoID("vie"));
283+
assertThrows(CouchbaseException.class, () -> airportRepository.getAllByIataNoCAS("vie"));
284+
} finally {
285+
airportRepository.deleteById(airport.getId());
286+
}
287+
}
288+
274289
@Test
275290
void threadSafeStringParametersTest() throws Exception {
276291
String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" };
@@ -332,14 +347,15 @@ void deleteAllById() {
332347
void couchbaseRepositoryQuery() throws Exception {
333348
User user = new User("1", "Dave", "Wilson");
334349
userRepository.save(user);
335-
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).matching(QueryCriteria.where("firstname").is("Dave").and("`1`").is("`1`")).all();
350+
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
351+
.matching(QueryCriteria.where("firstname").is("Dave").and("`1`").is("`1`")).all();
336352
String input = "findByFirstname";
337353
Method method = UserRepository.class.getMethod(input, String.class);
338354
CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method,
339355
new DefaultRepositoryMetadata(UserRepository.class), new SpelAwareProxyProjectionFactory(),
340356
couchbaseTemplate.getConverter().getMappingContext());
341357
CouchbaseRepositoryQuery query = new CouchbaseRepositoryQuery(couchbaseTemplate, queryMethod, null);
342-
List<User> users = (List<User>)query.execute(new String[] { "Dave" });
358+
List<User> users = (List<User>) query.execute(new String[] { "Dave" });
343359
assertEquals(user, users.get(0));
344360
}
345361

0 commit comments

Comments
 (0)