diff --git a/pom.xml b/pom.xml index ded4d85d02..97ecdf60ad 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 4.5.0-SNAPSHOT + 4.5.0-GH-4889-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 58c63dfc97..e35e85033a 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -15,7 +15,7 @@ org.springframework.data spring-data-mongodb-parent - 4.5.0-SNAPSHOT + 4.5.0-GH-4889-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 37e68c6f78..470fb51ad2 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 4.5.0-SNAPSHOT + 4.5.0-GH-4889-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java index cebdf4e408..dd2b78de59 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java @@ -36,6 +36,7 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UpdateDefinition; +import org.springframework.data.mongodb.repository.util.SliceUtils; import org.springframework.data.support.PageableExecutionUtils; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; @@ -87,7 +88,7 @@ public Object execute(Query query) { int pageSize = pageable.getPageSize(); // Apply Pageable but tweak limit to peek into next page - Query modifiedQuery = query.with(pageable).limit(pageSize + 1); + Query modifiedQuery = SliceUtils.limitResult(query, pageable).with(pageable.getSort()); List result = find.matching(modifiedQuery).all(); boolean hasNext = result.size() > pageSize; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java index 0da7b76596..ec845510ce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java @@ -27,6 +27,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.ScrollPosition; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Window; import org.springframework.data.mongodb.core.MongoOperations; @@ -271,6 +272,14 @@ public Page page(Pageable pageable) { return createQuery().fetchPage(pageable); } + @Override + public Slice slice(Pageable pageable) { + + Assert.notNull(pageable, "Pageable must not be null"); + + return createQuery().fetchSlice(pageable); + } + @Override public Stream stream() { return createQuery().stream(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java index bb0284f915..9a1482823f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java @@ -24,11 +24,13 @@ import org.bson.Document; import org.reactivestreams.Publisher; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Window; import org.springframework.data.domain.ScrollPosition; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Window; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; @@ -239,6 +241,14 @@ public Mono> page(Pageable pageable) { return createQuery().fetchPage(pageable); } + @Override + public Mono> slice(Pageable pageable) { + + Assert.notNull(pageable, "Pageable must not be null"); + + return createQuery().fetchSlice(pageable); + } + @Override public Mono count() { return createQuery().fetchCount(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java index c23ca5a979..bd4b241837 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.repository.support; +import org.springframework.data.mongodb.repository.util.SliceUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -27,6 +28,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.ScrollPosition; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Window; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.ReactiveFindOperation; @@ -109,6 +111,20 @@ Mono> fetchPage(Pageable pageable) { return content.flatMap(it -> ReactivePageableExecutionUtils.getPage(it, pageable, fetchCount())); } + /** + * Fetch all matching query results as Slice. + * + * @return {@link Mono} emitting the requested Slice. + * @since 4.5 + */ + Mono> fetchSlice(Pageable pageable) { + + Mono> content = createQuery().map(it -> SliceUtils.limitResult(it, pageable).with(pageable.getSort())) + .flatMapMany(it -> find.matching(it).all()).collectList(); + + return content.map(it -> SliceUtils.sliceResult(it, pageable)); + } + /** * Fetch the one matching query result. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index ce6dcdd3a4..2f4c30ee7a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -33,6 +33,7 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.ScrollPosition; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Window; import org.springframework.data.mongodb.core.ExecutableFindOperation; @@ -42,6 +43,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; +import org.springframework.data.mongodb.repository.util.SliceUtils; import org.springframework.data.support.PageableExecutionUtils; import org.springframework.data.util.StreamUtils; import org.springframework.data.util.Streamable; @@ -136,8 +138,7 @@ public boolean existsById(ID id) { Query query = getIdQuery(id); getReadPreference().ifPresent(query::withReadPreference); - return mongoOperations.exists(query, entityInformation.getJavaType(), - entityInformation.getCollectionName()); + return mongoOperations.exists(query, entityInformation.getJavaType(), entityInformation.getCollectionName()); } @Override @@ -455,6 +456,16 @@ public Page page(Pageable pageable) { return PageableExecutionUtils.getPage(list, pageable, this::count); } + @Override + public Slice slice(Pageable pageable) { + + Assert.notNull(pageable, "Pageable must not be null"); + + List resultList = createQuery(q -> SliceUtils.limitResult(q, pageable).with(pageable.getSort())).all(); + + return SliceUtils.sliceResult(resultList, pageable); + } + @Override public Stream stream() { return createQuery().stream(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index e8ff60de46..1c1df2c9a1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -17,6 +17,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; +import org.springframework.data.mongodb.repository.util.SliceUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -37,6 +38,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.ScrollPosition; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Window; import org.springframework.data.mongodb.core.MongoTemplate; @@ -592,6 +594,13 @@ public Mono> page(Pageable pageable) { return items.flatMap(content -> ReactivePageableExecutionUtils.getPage(content, pageable, this.count())); } + @Override + public Mono> slice(Pageable pageable) { + + return createQuery(q -> SliceUtils.limitResult(q, pageable).with(pageable.getSort())).all().collectList() + .map(it -> SliceUtils.sliceResult(it, pageable)); + } + @Override public Mono count() { return createQuery().count(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java index c8cad08c09..0ef6c38744 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java @@ -22,16 +22,19 @@ import java.util.stream.Stream; import org.bson.Document; + import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.ScrollPosition; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Window; import org.springframework.data.mongodb.core.ExecutableFindOperation; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.mapping.FieldName; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.repository.util.SliceUtils; import org.springframework.data.support.PageableExecutionUtils; import org.springframework.lang.Nullable; @@ -182,6 +185,20 @@ public Page fetchPage(Pageable pageable) { } } + /** + * Fetch a {@link Slice}. + * + * @param pageable defines range and sort of requested slice + * @return new instance of {@link Slice} containing matching results within range. + * @since 4.5 + */ + public Slice fetchSlice(Pageable pageable) { + + List content = find.matching(SliceUtils.limitResult(createQuery(), pageable).with(pageable.getSort())).all(); + + return SliceUtils.sliceResult(content, pageable); + } + @Override public T fetchFirst() { try { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/util/SliceUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/util/SliceUtils.java new file mode 100644 index 0000000000..db22c3fea4 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/util/SliceUtils.java @@ -0,0 +1,72 @@ +/* + * Copyright 2025 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.repository.util; + +import java.util.List; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; +import org.springframework.data.mongodb.core.query.Query; + +/** + * Utility methods for {@link Slice} handling. + * + * @author Mark Paluch + * @since 4.5 + */ +public class SliceUtils { + + /** + * Creates a {@link Slice} given {@link Pageable} and {@link List} of results. + * + * @param + * @param resultList + * @param pageable + * @return + */ + public static Slice sliceResult(List resultList, Pageable pageable) { + + boolean hasNext = resultList.size() > pageable.getPageSize(); + + if (hasNext) { + resultList = resultList.subList(0, pageable.getPageSize()); + } + + return new SliceImpl<>(resultList, pageable, hasNext); + } + + /** + * Customize query for slice retrieval. + * + * @param query the source query + * @param pageable paging to apply. + * @return new instance of {@link Query} if either {@link Pageable#isPaged() paged} or {@link Pageable#getSort() + * sorted}, the source query otherwise. + */ + public static Query limitResult(Query query, Pageable pageable) { + + if (pageable.isUnpaged()) { + return query; + } + + Query target = Query.of(query); + target.skip(pageable.getOffset()); + target.limit(pageable.getPageSize() + 1); + + return target; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java index 8ab45e5964..44235c54ef 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java @@ -607,6 +607,33 @@ void findByShouldApplyPagination() { }).verifyComplete(); } + @Test // GH-4889 + void findByShouldApplySlice() { + + ReactivePerson probe = new ReactivePerson(); + probe.setLastname(oliver.getLastname()); + + repository + .findBy(Example.of(probe, matching().withIgnorePaths("age")), + it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname")))) // + .as(StepVerifier::create) // + .assertNext(it -> { + + assertThat(it.hasNext()).isTrue(); + assertThat(it.getContent()).contains(dave); + }).verifyComplete(); + + repository + .findBy(Example.of(probe, matching().withIgnorePaths("age")), + it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname")))) // + .as(StepVerifier::create) // + .assertNext(it -> { + + assertThat(it.hasNext()).isFalse(); + assertThat(it.getContent()).contains(oliver); + }).verifyComplete(); + } + @Test // GH-3757 void findByShouldCount() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java index 18d86d02dc..7d9024e2fb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java @@ -31,6 +31,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.MongoDatabaseFactory; @@ -314,6 +315,7 @@ public void findByShouldApplyPagination() { Page first = repository.findBy(person.lastname.eq(oliver.getLastname()), it -> it.page(PageRequest.of(0, 1, Sort.by("firstname")))); + assertThat(first.getTotalElements()).isEqualTo(2); assertThat(first.getContent()).contains(dave); @@ -324,6 +326,22 @@ public void findByShouldApplyPagination() { assertThat(next.getContent()).contains(oliver); } + @Test // GH-4889 + public void findByShouldApplySlice() { + + Slice first = repository.findBy(person.lastname.eq(oliver.getLastname()), + it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname")))); + + assertThat(first.hasNext()).isTrue(); + assertThat(first.getContent()).contains(dave); + + Slice next = repository.findBy(person.lastname.eq(oliver.getLastname()), + it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname")))); + + assertThat(next.hasNext()).isFalse(); + assertThat(next.getContent()).contains(oliver); + } + @Test // GH-3757 public void findByShouldCount() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java index 7e6f6e4995..807b7aec22 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java @@ -31,6 +31,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.IncorrectResultSizeDataAccessException; @@ -50,8 +51,8 @@ import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.repository.query.FluentQuery; import org.springframework.data.mongodb.test.util.ReactiveMongoClientClosingTestConfiguration; +import org.springframework.data.repository.query.FluentQuery; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -414,6 +415,28 @@ public void findByShouldApplyPagination() { }).verifyComplete(); } + @Test // GH-4889 + public void findByShouldApplySlice() { + + repository + .findBy(person.lastname.eq(oliver.getLastname()), it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname")))) // + .as(StepVerifier::create) // + .assertNext(it -> { + + assertThat(it.hasNext()).isTrue(); + assertThat(it.getContent()).containsOnly(dave); + }).verifyComplete(); + + repository + .findBy(person.lastname.eq(oliver.getLastname()), it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname")))) // + .as(StepVerifier::create) // + .assertNext(it -> { + + assertThat(it.hasNext()).isFalse(); + assertThat(it.getContent()).containsOnly(oliver); + }).verifyComplete(); + } + @Test // GH-3757 public void findByShouldCount() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 98cbab868b..60c02ee775 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -38,6 +38,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.MongoTransactionManager; @@ -579,6 +580,24 @@ void findByShouldApplyPagination() { assertThat(next.getContent()).contains(oliver); } + @Test // GH-4889 + void findByShouldApplySlice() { + + Person probe = new Person(); + probe.setLastname(oliver.getLastname()); + + Slice first = repository.findBy(Example.of(probe, getMatcher()), + it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname")))); + assertThat(first.hasNext()).isTrue(); + assertThat(first.getContent()).contains(dave); + + Slice next = repository.findBy(Example.of(probe, getMatcher()), + it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname")))); + + assertThat(next.hasNext()).isFalse(); + assertThat(next.getContent()).contains(oliver); + } + @Test // GH-3757 void findByShouldCount() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/util/SliceUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/util/SliceUtilsUnitTests.java new file mode 100644 index 0000000000..eb1353cde3 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/util/SliceUtilsUnitTests.java @@ -0,0 +1,77 @@ +/* + * Copyright 2025 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.repository.util; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verifyNoInteractions; + +import java.util.stream.Stream; + +import org.bson.Document; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Query; + +/** + * @author Christoph Strobl + */ +class SliceUtilsUnitTests { + + @ParameterizedTest + @MethodSource("paged") + void pagedPageableModifiesQuery(Pageable page) { + + Query source = new BasicQuery(Document.parse("{ 'spring' : 'data' }")); + + Query target = SliceUtils.limitResult(source, page); + assertThat(target.getQueryObject()).isEqualTo(source.getQueryObject()); + assertThat(target).isNotSameAs(source); + assertThat(target.isLimited()).isTrue(); + assertThat(target.getSkip()).isEqualTo(page.getOffset()); + assertThat(target.getLimit()).isEqualTo(page.toLimit().max() + 1); + assertThat(target.getSortObject()).isEqualTo(source.getSortObject()); + } + + @ParameterizedTest + @MethodSource("unpaged") + void unpagedPageableDoesNotModifyQuery(Pageable page) { + + Query source = spy(new BasicQuery(Document.parse("{ 'spring' : 'data' }"))); + + Query target = SliceUtils.limitResult(source, page); + + verifyNoInteractions(source); + + assertThat(target).isSameAs(source); + assertThat(target.isLimited()).isFalse(); + } + + public static Stream paged() { + return Stream.of(Arguments.of(Pageable.ofSize(1)), Arguments.of(PageRequest.of(0, 10)), + Arguments.of(PageRequest.of(0, 10, Direction.ASC, "name"))); + } + + public static Stream unpaged() { + return Stream.of(Arguments.of(Pageable.unpaged()), Arguments.of(Pageable.unpaged(Sort.by("name")))); + } +}