From ec0c00eb725d61fb0f9f986cca32f6e604f0aadd Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Tue, 15 Aug 2023 21:56:50 +1200 Subject: [PATCH] Add Query alsoIf() to conditionally apply changes to a query --- ebean-api/src/main/java/io/ebean/Query.java | 11 ++++++ .../server/query/DefaultFetchGroupQuery.java | 6 +++ .../server/querydefn/DefaultOrmQuery.java | 9 +++++ .../java/io/ebean/typequery/TQRootBean.java | 16 ++++++++ .../java/org/querytest/QueryAlsoIfTest.java | 37 +++++++++++++++++++ .../java/org/tests/query/TestQueryAlsoIf.java | 36 ++++++++++++++++++ 6 files changed, 115 insertions(+) create mode 100644 ebean-querybean/src/test/java/org/querytest/QueryAlsoIfTest.java create mode 100644 ebean-test/src/test/java/org/tests/query/TestQueryAlsoIf.java diff --git a/ebean-api/src/main/java/io/ebean/Query.java b/ebean-api/src/main/java/io/ebean/Query.java index f3e39056c..c595b2749 100644 --- a/ebean-api/src/main/java/io/ebean/Query.java +++ b/ebean-api/src/main/java/io/ebean/Query.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; @@ -671,6 +672,16 @@ public interface Query extends CancelableQuery { */ Query apply(FetchPath fetchPath); + /** + * Apply changes to the query conditional on the supplied predicate. + *

+ * Typically, the changes are extra predicates etc. + * + * @param predicate The predicate which when true the changes are applied + * @param apply The changes to apply to the query + */ + Query alsoIf(BooleanSupplier predicate, Consumer> apply); + /** * Execute the query using the given transaction. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java index a168d03d7..ce8f71a53 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; @@ -219,6 +220,11 @@ final class DefaultFetchGroupQuery implements SpiFetchGroupQuery, SpiQuery throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup"); } + @Override + public Query alsoIf(BooleanSupplier predicate, Consumer> apply) { + throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup"); + } + @Override public Query usingTransaction(Transaction transaction) { throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup"); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 9e8a41225..a3bf1024a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -26,6 +26,7 @@ import javax.persistence.PersistenceException; import java.sql.Connection; import java.sql.Timestamp; import java.util.*; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; @@ -282,6 +283,14 @@ public class DefaultOrmQuery extends AbstractQuery implements SpiQuery { return this; } + @Override + public Query alsoIf(BooleanSupplier predicate, Consumer> consumer) { + if (predicate.getAsBoolean()) { + consumer.accept(this); + } + return this; + } + @Override public final void addSoftDeletePredicate(String softDeletePredicate) { if (softDeletePredicates == null) { diff --git a/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java b/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java index 2a43aa441..78224d9c5 100644 --- a/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java +++ b/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java @@ -16,6 +16,7 @@ import javax.sql.DataSource; import java.sql.Connection; import java.sql.Timestamp; import java.util.*; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; @@ -486,6 +487,21 @@ public abstract class TQRootBean { return root; } + /** + * Apply changes to the query conditional on the supplied predicate. + *

+ * Typically, the changes are extra predicates etc. + * + * @param predicate The predicate which when true the changes are applied + * @param apply The changes to apply to the query + */ + public R alsoIf(BooleanSupplier predicate, Consumer apply) { + if (predicate.getAsBoolean()) { + apply.accept(root); + } + return root; + } + /** * Perform an 'As of' query using history tables to return the object graph * as of a time in the past. diff --git a/ebean-querybean/src/test/java/org/querytest/QueryAlsoIfTest.java b/ebean-querybean/src/test/java/org/querytest/QueryAlsoIfTest.java new file mode 100644 index 000000000..3ccc58879 --- /dev/null +++ b/ebean-querybean/src/test/java/org/querytest/QueryAlsoIfTest.java @@ -0,0 +1,37 @@ +package org.querytest; + +import org.example.domain.Customer; +import org.example.domain.query.QCustomer; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.example.domain.query.QCustomer.Alias.name; + +class QueryAlsoIfTest { + + int dummy = 1; + + @Test + void apply() { + var q = new QCustomer() + .select(name) + .name.isNotNull() + .alsoIf(() -> dummy == 1, query -> query.status.equalTo(Customer.Status.GOOD)) + .query(); + + q.findList(); + assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name from be_customer t0 where t0.name is not null and t0.status = ?"); + } + + @Test + void notApply() { + var q = new QCustomer() + .select(name) + .name.isNotNull() + .alsoIf(() -> dummy > 1, query -> query.status.equalTo(Customer.Status.GOOD)) + .query(); + + q.findList(); + assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name from be_customer t0 where t0.name is not null"); + } +} diff --git a/ebean-test/src/test/java/org/tests/query/TestQueryAlsoIf.java b/ebean-test/src/test/java/org/tests/query/TestQueryAlsoIf.java new file mode 100644 index 000000000..3ed66c800 --- /dev/null +++ b/ebean-test/src/test/java/org/tests/query/TestQueryAlsoIf.java @@ -0,0 +1,36 @@ +package org.tests.query; + +import io.ebean.DB; +import io.ebean.Query; +import org.junit.jupiter.api.Test; +import org.tests.model.basic.Customer; +import org.tests.model.basic.ResetBasicData; + +import static org.assertj.core.api.Assertions.assertThat; + +class TestQueryAlsoIf { + + int dummy = 1; + + @Test + void apply() { + ResetBasicData.reset(); + Query query = DB.find(Customer.class) + .select("name") + .alsoIf(() -> dummy == 1, qy -> qy.where().isNotNull("name")); + + query.findList(); + assertThat(query.getGeneratedSql()).isEqualTo("select t0.id, t0.name from o_customer t0 where t0.name is not null"); + } + + @Test + void notApply() { + ResetBasicData.reset(); + Query query = DB.find(Customer.class) + .select("name") + .alsoIf(() -> dummy > 1, qy -> qy.where().isNotNull("name")); + + query.findList(); + assertThat(query.getGeneratedSql()).isEqualTo("select t0.id, t0.name from o_customer t0"); + } +}