From e9e841180d9f6c92263e9e81135563e6e6c94c38 Mon Sep 17 00:00:00 2001 From: mikereiche Date: Mon, 3 May 2021 15:13:35 -0400 Subject: [PATCH] Add override of toN1qlRemoveString() to StringQuery. Closes #1131. Original pull request: #1135. --- ...ReactiveRemoveByQueryOperationSupport.java | 6 +---- .../data/couchbase/core/query/Query.java | 10 +++++-- .../couchbase/core/query/StringQuery.java | 12 +++++++++ .../data/couchbase/domain/Airport.java | 22 ++++++++++++--- .../couchbase/domain/AirportRepository.java | 27 +++++++++++++------ ...chbaseRepositoryQueryIntegrationTests.java | 16 +++++++++-- 6 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java index 3a76a2817..262234760 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java @@ -80,11 +80,7 @@ public Flux all() { } private QueryOptions buildQueryOptions() { - final QueryOptions options = QueryOptions.queryOptions(); - if (scanConsistency != null) { - options.scanConsistency(scanConsistency); - } - return options; + return query.buildQueryOptions(scanConsistency); } @Override 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 82eda0969..740e97306 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 @@ -323,7 +323,10 @@ StringBasedN1qlQueryParser.N1qlSpelValues getN1qlSpelValues(ReactiveCouchbaseTem * @return QueryOptions */ public QueryOptions buildQueryOptions(QueryScanConsistency scanConsistency) { - final QueryOptions options = QueryOptions.queryOptions(); + QueryOptions options = QueryOptions.queryOptions(); + if (options == null) { // add/override what we got from PseudoArgs + options = QueryOptions.queryOptions(); + } if (getParameters() != null) { if (getParameters() instanceof JsonArray) { options.parameters((JsonArray) getParameters()); @@ -331,10 +334,13 @@ public QueryOptions buildQueryOptions(QueryScanConsistency scanConsistency) { options.parameters((JsonObject) getParameters()); } } + if (scanConsistency == null + || scanConsistency == QueryScanConsistency.NOT_BOUNDED && getScanConsistency() != null) { + scanConsistency = getScanConsistency(); + } if (scanConsistency != null) { options.scanConsistency(scanConsistency); } - return options; } 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 9b326aa47..95417b57f 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 @@ -73,4 +73,16 @@ public String toN1qlSelectString(ReactiveCouchbaseTemplate template, String coll appendSkipAndLimit(statement); return statement.toString(); } + + /** + * toN1qlRemoveString - use toN1qlSelectString + * + * @param template + * @param collectionName + * @param domainClass + */ + @Override + public String toN1qlRemoveString(ReactiveCouchbaseTemplate template, String collectionName, Class domainClass) { + return toN1qlSelectString(template, collectionName, domainClass, domainClass, false, null); + } } diff --git a/src/test/java/org/springframework/data/couchbase/domain/Airport.java b/src/test/java/org/springframework/data/couchbase/domain/Airport.java index d920c9b26..e73a81804 100644 --- a/src/test/java/org/springframework/data/couchbase/domain/Airport.java +++ b/src/test/java/org/springframework/data/couchbase/domain/Airport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,9 +38,9 @@ public class Airport extends ComparableEntity { String icao; - @CreatedBy private String createdBy; + @Version Number version; - @Version long version; + @CreatedBy private String createdBy; @PersistenceConstructor @@ -62,6 +62,22 @@ public String getIcao() { return icao; } + public Airport withId(String id) { + return new Airport(id, this.iata, this.icao); + } + + public Airport withIcao(String icao) { + return new Airport(this.getId(), this.iata, icao); + } + + public Airport withIata(String iata) { + return new Airport(this.getId(), iata, this.icao); + } + + public Airport clearVersion() { + version = Long.valueOf(0); + return this; + } public String getCreatedBy() { return createdBy; } diff --git a/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java b/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java index 06464583d..d849d32e3 100644 --- a/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java +++ b/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,32 +17,35 @@ package org.springframework.data.couchbase.domain; import java.util.List; +import java.util.Optional; +import org.springframework.data.couchbase.core.RemoveResult; +import org.springframework.data.couchbase.repository.CouchbaseRepository; import org.springframework.data.couchbase.repository.Query; import org.springframework.data.couchbase.repository.ScanConsistency; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import com.couchbase.client.java.query.QueryScanConsistency; /** - * template class for Reactive Couchbase operations + * Airport repository for testing
+ * The DynamicProxyable interface exposes airportRepository.withScope(scope), withCollection() and withOptions() It's + * necessary on the repository object itself because the withScope() etc methods need to return an object of type + * AirportRepository so that one can code... airportRepository = airportRepository.withScope(scopeName) without having + * to cast the result. * * @author Michael Nitschinger * @author Michael Reiche */ @Repository -public interface AirportRepository extends PagingAndSortingRepository { +public interface AirportRepository extends CouchbaseRepository { @Override @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - Iterable findAll(); - - @Override - Airport save(Airport airport); + List findAll(); @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) List findAllByIata(String iata); @@ -57,6 +60,10 @@ public interface AirportRepository extends PagingAndSortingRepository getAllByIata(String iata); + @Query("#{#n1ql.delete} WHERE #{#n1ql.filter} and iata = $1 #{#n1ql.returning}") + @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) + List deleteByIata(String iata); + @Query("SELECT __cas, * from `#{#n1ql.bucket}` where iata = $1") @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) List getAllByIataNoID(String iata); @@ -86,4 +93,8 @@ Long countFancyExpression(@Param("projectIds") List projectIds, @Param(" @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) Page findAllByIataNot(String iata, Pageable pageable); + + @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) + Optional findByIdAndIata(String id, String iata); + } 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 4532a4e48..135b4e548 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java @@ -198,7 +198,7 @@ void findByEnum() { vie = new Airport("airports::vie", "vie", "loww"); vie = airportRepository.save(vie); Airport airport2 = airportRepository.findByIata(Iata.vie); - assertNotNull(airport2, "should have found "+vie); + assertNotNull(airport2, "should have found " + vie); assertEquals(airport2.getId(), vie.getId()); } finally { airportRepository.delete(vie); @@ -310,6 +310,19 @@ void stringQueryTest() throws Exception { } } + @Test + void stringDeleteTest() throws Exception { + Airport airport = new Airport("airports::vie", "vie", "lowx"); + Airport otherAirport = new Airport("airports::xxx", "xxx", "lxxx"); + try { + airportRepository.save(airport); + airportRepository.save(otherAirport); + assertEquals(1, airportRepository.deleteByIata("vie").size()); // gets exactly one with no exception + } finally { + airportRepository.deleteById(otherAirport.getId()); + } + } + @Test void threadSafeStringParametersTest() throws Exception { String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" }; @@ -397,7 +410,6 @@ void findBySimplePropertyAudited() { } } - private void sleep(int millis) { try { Thread.sleep(millis); // so they are executed out-of-order