diff --git a/src/main/java/io/ebeaninternal/api/SpiExpressionList.java b/src/main/java/io/ebeaninternal/api/SpiExpressionList.java index cc07d2787..3cf5c2e64 100644 --- a/src/main/java/io/ebeaninternal/api/SpiExpressionList.java +++ b/src/main/java/io/ebeaninternal/api/SpiExpressionList.java @@ -36,4 +36,11 @@ public interface SpiExpressionList extends ExpressionList, SpiExpression { * Write the top level where expressions taking into account possible extra idEquals expression. */ void writeDocQuery(DocQueryContext context, SpiExpression idEquals) throws IOException; + + /** + * Apply firstRow maxRows limits on the filterMany query. + */ + default void applyRowLimits(SpiQuery query) { + // do nothing by default + } } diff --git a/src/main/java/io/ebeaninternal/server/expression/FilterExpressionList.java b/src/main/java/io/ebeaninternal/server/expression/FilterExpressionList.java index ffaa52702..a79354cd2 100644 --- a/src/main/java/io/ebeaninternal/server/expression/FilterExpressionList.java +++ b/src/main/java/io/ebeaninternal/server/expression/FilterExpressionList.java @@ -9,6 +9,7 @@ import io.ebean.Junction; import io.ebean.OrderBy; import io.ebean.Query; import io.ebeaninternal.api.SpiExpressionList; +import io.ebeaninternal.api.SpiQuery; import javax.persistence.PersistenceException; import java.util.Collection; @@ -25,6 +26,9 @@ public class FilterExpressionList extends DefaultExpressionList { private final FilterExprPath pathPrefix; + private int firstRow; + private int maxRows; + public FilterExpressionList(FilterExprPath pathPrefix, FilterExpressionList original) { super(null, original.expr, null, original.getUnderlyingList()); this.pathPrefix = pathPrefix; @@ -144,11 +148,6 @@ public class FilterExpressionList extends DefaultExpressionList { throw new PersistenceException(notAllowedMessage); } - @Override - public Query setFirstRow(int firstRow) { - return rootQuery.setFirstRow(firstRow); - } - @Override public Query setMapKey(String mapKey) { return rootQuery.setMapKey(mapKey); @@ -156,7 +155,14 @@ public class FilterExpressionList extends DefaultExpressionList { @Override public Query setMaxRows(int maxRows) { - return rootQuery.setMaxRows(maxRows); + this.maxRows = maxRows; + return rootQuery; + } + + @Override + public Query setFirstRow(int firstRow) { + this.firstRow = firstRow; + return rootQuery; } @Override @@ -169,5 +175,14 @@ public class FilterExpressionList extends DefaultExpressionList { return rootQuery.where(); } + @Override + public void applyRowLimits(SpiQuery query) { + if (firstRow > 0) { + query.setFirstRow(firstRow); + } + if (maxRows > 0) { + query.setMaxRows(maxRows); + } + } } diff --git a/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryProperties.java b/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryProperties.java index cf03b0188..805c3bf68 100644 --- a/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryProperties.java +++ b/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryProperties.java @@ -245,9 +245,9 @@ public class OrmQueryProperties implements Serializable { } if (filterMany != null) { + filterMany.applyRowLimits(query); SpiExpressionList trimPath = filterMany.trimPath(path.length() + 1); - List underlyingList = trimPath.getUnderlyingList(); - for (SpiExpression spiExpression : underlyingList) { + for (SpiExpression spiExpression : trimPath.getUnderlyingList()) { query.where().add(spiExpression); } } diff --git a/src/test/java/org/tests/query/TestQueryFilterMany.java b/src/test/java/org/tests/query/TestQueryFilterMany.java index fcc734a98..b8dc4ed45 100644 --- a/src/test/java/org/tests/query/TestQueryFilterMany.java +++ b/src/test/java/org/tests/query/TestQueryFilterMany.java @@ -1,7 +1,9 @@ package org.tests.query; import io.ebean.BaseTestCase; +import io.ebean.DB; import io.ebean.Ebean; +import io.ebean.ExpressionList; import io.ebean.FetchConfig; import io.ebean.Query; import org.ebeantest.LoggedSqlCollector; @@ -44,6 +46,37 @@ public class TestQueryFilterMany extends BaseTestCase { } + @Test + public void test_firstMaxRows() { + + ResetBasicData.reset(); + + LoggedSqlCollector.start(); + + final Query query = DB.find(Customer.class) + .where().ieq("name", "Rob") + .order().asc("id").setMaxRows(5); + + final ExpressionList filterMany = query.filterMany("orders").eq("status", Order.Status.NEW); + filterMany.setMaxRows(100); + filterMany.setFirstRow(3); + + final List customers = query.findList(); + assertThat(customers).isNotEmpty(); + List sqlList = LoggedSqlCollector.stop(); + assertEquals(2, sqlList.size()); + + assertThat(sqlList.get(0)).contains("lower(t0.name) = ?"); + assertThat(sqlList.get(1)).contains("status = ?"); + + if (isH2() || isPostgres()) { + assertThat(sqlList.get(0)).doesNotContain("offset"); + assertThat(sqlList.get(0)).contains(" limit 5"); + assertThat(sqlList.get(1)).contains(" offset 3"); + assertThat(sqlList.get(1)).contains(" limit 100"); + } + } + @Test public void test_with_findOne() {