From 5c0a0a2112cc2d33ecc300618f0694846d0f0f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mathieu?= Date: Thu, 7 May 2020 11:11:16 +0200 Subject: [PATCH] Allow to add a collation to a query Fixes #9081 --- .../quarkus/mongodb/panache/PanacheQuery.java | 10 ++ .../reactive/ReactivePanacheQuery.java | 10 ++ .../runtime/ReactivePanacheQueryImpl.java | 18 ++++ .../panache/runtime/PanacheQueryImpl.java | 14 +++ .../it/mongodb/panache/test/TestResource.java | 91 +++++++++++++++++++ 5 files changed, 143 insertions(+) diff --git a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/PanacheQuery.java b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/PanacheQuery.java index 001d4ee689d0c..ea7b9104a74c9 100644 --- a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/PanacheQuery.java +++ b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/PanacheQuery.java @@ -4,6 +4,8 @@ import java.util.Optional; import java.util.stream.Stream; +import com.mongodb.client.model.Collation; + import io.quarkus.panache.common.Page; /** @@ -134,6 +136,14 @@ public interface PanacheQuery { */ public PanacheQuery range(int startIndex, int lastIndex); + /** + * Define the collation used for this query. + * + * @param collation the collation to be used for this query. + * @return this query, modified + */ + public PanacheQuery withCollation(Collation collation); + // Results /** diff --git a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/ReactivePanacheQuery.java b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/ReactivePanacheQuery.java index 923a270108dda..1fbf709e70dda 100644 --- a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/ReactivePanacheQuery.java +++ b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/ReactivePanacheQuery.java @@ -4,6 +4,8 @@ import java.util.Optional; import java.util.stream.Stream; +import com.mongodb.client.model.Collation; + import io.quarkus.panache.common.Page; import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; @@ -136,6 +138,14 @@ public interface ReactivePanacheQuery { */ public ReactivePanacheQuery range(int startIndex, int lastIndex); + /** + * Define the collation used for this query. + * + * @param collation the collation to be used for this query. + * @return this query, modified + */ + public ReactivePanacheQuery withCollation(Collation collation); + // Results /** diff --git a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/runtime/ReactivePanacheQueryImpl.java b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/runtime/ReactivePanacheQueryImpl.java index 6a652147f6821..8a1af460d8792 100644 --- a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/runtime/ReactivePanacheQueryImpl.java +++ b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/reactive/runtime/ReactivePanacheQueryImpl.java @@ -7,6 +7,8 @@ import org.bson.Document; import org.bson.conversions.Bson; +import com.mongodb.client.model.Collation; + import io.quarkus.mongodb.FindOptions; import io.quarkus.mongodb.panache.reactive.ReactivePanacheQuery; import io.quarkus.mongodb.panache.runtime.MongoPropertyUtil; @@ -28,6 +30,8 @@ public class ReactivePanacheQueryImpl implements ReactivePanacheQuery collection, Bson mongoQuery, Bson sort) { this.collection = collection; this.mongoQuery = mongoQuery; @@ -41,6 +45,8 @@ private ReactivePanacheQueryImpl(ReactivePanacheQueryImpl previousQuery, Bson pr this.projections = projections; this.page = previousQuery.page; this.count = previousQuery.count; + this.range = previousQuery.range; + this.collation = previousQuery.collation; } // Builder @@ -144,6 +150,12 @@ public ReactivePanacheQuery range(int startIndex, int last return (ReactivePanacheQuery) this; } + @Override + public ReactivePanacheQuery withCollation(Collation collation) { + this.collation = collation; + return (ReactivePanacheQuery) this; + } + // Results @Override @@ -220,6 +232,9 @@ private FindOptions buildOptions() { if (projections != null) { options.projection(this.projections); } + if (this.collation != null) { + options.collation(collation); + } return options; } @@ -235,6 +250,9 @@ private FindOptions buildOptions(int maxResults) { if (projections != null) { options.projection(this.projections); } + if (this.collation != null) { + options.collation(collation); + } return options.limit(maxResults); } } diff --git a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/runtime/PanacheQueryImpl.java b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/runtime/PanacheQueryImpl.java index 614c2b5d71820..b2c19376a615d 100644 --- a/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/runtime/PanacheQueryImpl.java +++ b/extensions/panache/mongodb-panache/runtime/src/main/java/io/quarkus/mongodb/panache/runtime/PanacheQueryImpl.java @@ -12,6 +12,7 @@ import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; +import com.mongodb.client.model.Collation; import io.quarkus.mongodb.panache.PanacheQuery; import io.quarkus.panache.common.Page; @@ -29,6 +30,8 @@ public class PanacheQueryImpl implements PanacheQuery { private Range range; + private Collation collation; + PanacheQueryImpl(MongoCollection collection, Bson mongoQuery, Bson sort) { this.collection = collection; this.mongoQuery = mongoQuery; @@ -42,6 +45,8 @@ private PanacheQueryImpl(PanacheQueryImpl previousQuery, Bson projections) { this.projections = projections; this.page = previousQuery.page; this.count = previousQuery.count; + this.range = previousQuery.range; + this.collation = previousQuery.collation; } // Builder @@ -144,6 +149,12 @@ public PanacheQuery range(int startIndex, int lastIndex) { return (PanacheQuery) this; } + @Override + public PanacheQuery withCollation(Collation collation) { + this.collation = collation; + return (PanacheQuery) this; + } + // Results @Override @@ -167,6 +178,9 @@ private List list(Integer limit) { if (this.projections != null) { find.projection(projections); } + if (this.collation != null) { + find.collation(collation); + } manageOffsets(find, limit); MongoCursor cursor = find.sort(sort).iterator(); diff --git a/integration-tests/mongodb-panache/src/main/java/io/quarkus/it/mongodb/panache/test/TestResource.java b/integration-tests/mongodb-panache/src/main/java/io/quarkus/it/mongodb/panache/test/TestResource.java index 2a7579f0d77dc..935dd34a7e9f5 100644 --- a/integration-tests/mongodb-panache/src/main/java/io/quarkus/it/mongodb/panache/test/TestResource.java +++ b/integration-tests/mongodb-panache/src/main/java/io/quarkus/it/mongodb/panache/test/TestResource.java @@ -11,6 +11,9 @@ import org.bson.Document; import org.junit.jupiter.api.Assertions; +import com.mongodb.client.model.Collation; +import com.mongodb.client.model.CollationStrength; + import io.quarkus.mongodb.panache.PanacheQuery; import io.quarkus.mongodb.panache.reactive.ReactivePanacheQuery; import io.quarkus.panache.common.Page; @@ -86,6 +89,27 @@ public Response testImperativeEntity() { entityA.delete(); entityZ.delete(); + // collation + TestImperativeEntity entityALower = new TestImperativeEntity("aaa", "aaa", "aaa"); + entityALower.persist(); + TestImperativeEntity entityAUpper = new TestImperativeEntity("AAA", "AAA", "AAA"); + entityAUpper.persist(); + TestImperativeEntity entityB = new TestImperativeEntity("BBB", "BBB", "BBB"); + entityB.persistOrUpdate(); + List results = TestImperativeEntity. listAll(Sort.ascending("title")); + Assertions.assertEquals("AAA", results.get(0).title); + Assertions.assertEquals("BBB", results.get(1).title); + Assertions.assertEquals("aaa", results.get(2).title); + Collation collation = Collation.builder().caseLevel(true).collationStrength(CollationStrength.PRIMARY).locale("fr") + .build(); + results = TestImperativeEntity. findAll(Sort.ascending("title")).withCollation(collation).list(); + Assertions.assertEquals("aaa", results.get(0).title); + Assertions.assertEquals("AAA", results.get(1).title); + Assertions.assertEquals("BBB", results.get(2).title); + entityAUpper.delete(); + entityALower.delete(); + entityB.delete(); + // count Assertions.assertEquals(5, TestImperativeEntity.count("category", "category0")); Assertions.assertEquals(5, TestImperativeEntity.count("category = ?1", "category0")); @@ -199,6 +223,28 @@ public Response testImperativeRepository() { testImperativeRepository.delete(entityA); testImperativeRepository.delete(entityZ); + // collation + TestImperativeEntity entityALower = new TestImperativeEntity("aaa", "aaa", "aaa"); + testImperativeRepository.persist(entityALower); + TestImperativeEntity entityAUpper = new TestImperativeEntity("AAA", "AAA", "AAA"); + testImperativeRepository.persist(entityAUpper); + TestImperativeEntity entityB = new TestImperativeEntity("BBB", "BBB", "BBB"); + testImperativeRepository.persistOrUpdate(entityB); + List results = testImperativeRepository. listAll(Sort.ascending("title")); + Assertions.assertEquals("AAA", results.get(0).title); + Assertions.assertEquals("BBB", results.get(1).title); + Assertions.assertEquals("aaa", results.get(2).title); + Collation collation = Collation.builder().caseLevel(true).collationStrength(CollationStrength.PRIMARY).locale("fr") + .build(); + results = testImperativeRepository. findAll(Sort.ascending("title")).withCollation(collation) + .list(); + Assertions.assertEquals("aaa", results.get(0).title); + Assertions.assertEquals("AAA", results.get(1).title); + Assertions.assertEquals("BBB", results.get(2).title); + testImperativeRepository.delete(entityALower); + testImperativeRepository.delete(entityAUpper); + testImperativeRepository.delete(entityB); + // count Assertions.assertEquals(5, testImperativeRepository.count("category", "category0")); Assertions.assertEquals(5, testImperativeRepository.count("category = ?1", "category0")); @@ -387,6 +433,29 @@ public Response testReactiveEntity() { entityA.delete().await().indefinitely(); entityZ.delete().await().indefinitely(); + // collation + TestReactiveEntity entityALower = new TestReactiveEntity("aaa", "aaa", "aaa"); + entityALower.persist().await().indefinitely(); + TestReactiveEntity entityAUpper = new TestReactiveEntity("AAA", "AAA", "AAA"); + entityAUpper.persist().await().indefinitely(); + TestReactiveEntity entityB = new TestReactiveEntity("BBB", "BBB", "BBB"); + entityB.persistOrUpdate().await().indefinitely(); + List results = TestReactiveEntity. listAll(Sort.ascending("title")).await() + .indefinitely(); + Assertions.assertEquals("AAA", results.get(0).title); + Assertions.assertEquals("BBB", results.get(1).title); + Assertions.assertEquals("aaa", results.get(2).title); + Collation collation = Collation.builder().caseLevel(true).collationStrength(CollationStrength.PRIMARY).locale("fr") + .build(); + results = TestReactiveEntity. findAll(Sort.ascending("title")).withCollation(collation).list() + .await().indefinitely(); + Assertions.assertEquals("aaa", results.get(0).title); + Assertions.assertEquals("AAA", results.get(1).title); + Assertions.assertEquals("BBB", results.get(2).title); + entityAUpper.delete().await().indefinitely(); + entityALower.delete().await().indefinitely(); + entityB.delete().await().indefinitely(); + // count Assertions.assertEquals(5, TestReactiveEntity.count("category", "category0").await().indefinitely()); Assertions.assertEquals(5, TestReactiveEntity.count("category = ?1", "category0").await().indefinitely()); @@ -507,6 +576,28 @@ public Response testReactiveRepository() { testReactiveRepository.delete(entityA).await().indefinitely(); testReactiveRepository.delete(entityZ).await().indefinitely(); + // collation + TestReactiveEntity entityALower = new TestReactiveEntity("aaa", "aaa", "aaa"); + testReactiveRepository.persist(entityALower).await().indefinitely(); + TestReactiveEntity entityAUpper = new TestReactiveEntity("AAA", "AAA", "AAA"); + testReactiveRepository.persist(entityAUpper).await().indefinitely(); + TestReactiveEntity entityB = new TestReactiveEntity("BBB", "BBB", "BBB"); + testReactiveRepository.persistOrUpdate(entityB).await().indefinitely(); + List results = testReactiveRepository.listAll(Sort.ascending("title")).await().indefinitely(); + Assertions.assertEquals("AAA", results.get(0).title); + Assertions.assertEquals("BBB", results.get(1).title); + Assertions.assertEquals("aaa", results.get(2).title); + Collation collation = Collation.builder().caseLevel(true).collationStrength(CollationStrength.PRIMARY).locale("fr") + .build(); + results = testReactiveRepository.findAll(Sort.ascending("title")).withCollation(collation).list().await() + .indefinitely(); + Assertions.assertEquals("aaa", results.get(0).title); + Assertions.assertEquals("AAA", results.get(1).title); + Assertions.assertEquals("BBB", results.get(2).title); + testReactiveRepository.delete(entityALower).await().indefinitely(); + testReactiveRepository.delete(entityAUpper).await().indefinitely(); + testReactiveRepository.delete(entityB).await().indefinitely(); + // count Assertions.assertEquals(5, testReactiveRepository.count("category", "category0").await().indefinitely());