diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java index f8647066a..5388027bc 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java @@ -229,7 +229,7 @@ public Flux all() { public QueryOptions buildOptions(QueryOptions options) { QueryScanConsistency qsc = scanConsistency != null ? scanConsistency : template.getConsistency(); - return query.buildQueryOptions(options, qsc); + return query.buildQueryOptions(options, qsc).readonly(query.isReadonly()); } private TransactionQueryOptions buildTransactionOptions(QueryOptions options) { diff --git a/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java b/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java index c7ac56878..dcdf29c62 100644 --- a/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java +++ b/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java @@ -48,6 +48,11 @@ public JsonObject n1ql() { return query; } + @Override + public boolean isReadonly() { + return options.build().readonly(); + } + @Override public String toN1qlSelectString(CouchbaseConverter template, String bucketName, String scopeName, String collectionName, Class domainClass, Class returnClass, boolean isCount, String[] distinctFields, diff --git a/src/main/java/org/springframework/data/couchbase/core/query/Query.java b/src/main/java/org/springframework/data/couchbase/core/query/Query.java index 48dd8fb81..59da4a487 100644 --- a/src/main/java/org/springframework/data/couchbase/core/query/Query.java +++ b/src/main/java/org/springframework/data/couchbase/core/query/Query.java @@ -418,6 +418,10 @@ public Meta getMeta() { return meta; } + public boolean isReadonly() { + return true; + } + public boolean equals(Object o) { if (!o.getClass().isAssignableFrom(getClass())) { return false; diff --git a/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java b/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java index 7c294d092..b90dc32d6 100644 --- a/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java +++ b/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java @@ -131,6 +131,14 @@ scopeName, collectionName, converter, typeKey, typeValue, parameterAccessor, new return sbnqp; } + @Override + public boolean isReadonly() { + if (this.queryMethod.hasN1qlAnnotation()) { + return this.queryMethod.getN1qlAnnotation().readonly(); + } + return false; + } + /** * toN1qlRemoveString - use toN1qlSelectString * diff --git a/src/main/java/org/springframework/data/couchbase/repository/Query.java b/src/main/java/org/springframework/data/couchbase/repository/Query.java index 46d417dec..bf9234cf6 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/Query.java +++ b/src/main/java/org/springframework/data/couchbase/repository/Query.java @@ -58,4 +58,11 @@ */ String value() default ""; + /** + * Mark query as readonly + * + * @see com.couchbase.client.java.query.QueryOptions#readonly(boolean) + */ + boolean readonly() default false; + } diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/BasicQuery.java b/src/main/java/org/springframework/data/couchbase/repository/support/BasicQuery.java index d3294d38c..419eee039 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/BasicQuery.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/BasicQuery.java @@ -104,6 +104,11 @@ private boolean querySettingsEquals(BasicQuery that) { return super.equals(that); } + @Override + public boolean isReadonly() { + return true; + } + /* * (non-Javadoc) */ diff --git a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryCollectionIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryCollectionIntegrationTests.java index 29c4068b3..5a9d469b9 100644 --- a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryCollectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryCollectionIntegrationTests.java @@ -698,7 +698,7 @@ public void findByIdOptions() { // 3 @Test public void findByQueryOptions() { // 4 QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofNanos(10)); - assertThrows(AmbiguousTimeoutException.class, () -> couchbaseTemplate.findByQuery(Airport.class) + assertThrows(UnambiguousTimeoutException.class, () -> couchbaseTemplate.findByQuery(Airport.class) .withConsistency(REQUEST_PLUS).inScope(otherScope).inCollection(otherCollection).withOptions(options).all()); } diff --git a/src/test/java/org/springframework/data/couchbase/core/query/ReactiveCouchbaseTemplateQueryCollectionIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/query/ReactiveCouchbaseTemplateQueryCollectionIntegrationTests.java index 70ef366d5..f26a54707 100644 --- a/src/test/java/org/springframework/data/couchbase/core/query/ReactiveCouchbaseTemplateQueryCollectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/query/ReactiveCouchbaseTemplateQueryCollectionIntegrationTests.java @@ -689,7 +689,7 @@ public void findByIdOptions() { // 3 @Test public void findByQueryOptions() { // 4 QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofNanos(10)); - assertThrows(AmbiguousTimeoutException.class, + assertThrows(UnambiguousTimeoutException.class, () -> template.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).inScope(otherScope) .inCollection(otherCollection).withOptions(options).all().collectList().block()); } diff --git a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java index cdc7cd35e..76e976b7c 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java @@ -30,6 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.data.couchbase.config.BeanNames.COUCHBASE_TEMPLATE; +import com.couchbase.client.core.error.UnambiguousTimeoutException; import jakarta.validation.ConstraintViolationException; import junit.framework.AssertionFailedError; @@ -644,7 +645,7 @@ void findBySimplePropertyWithOptions() { try { Airport saved = airportRepository.save(vie); // Duration of 1 nano-second will cause timeout - assertThrows(AmbiguousTimeoutException.class, + assertThrows(UnambiguousTimeoutException.class, () -> airportRepository.withOptions(queryOptions().timeout(Duration.ofNanos(1))).iata(vie.getIata())); Airport airport3 = airportRepository