mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge pull request #1944 from ebean-orm/feature/1943
#1943 - Use limit & offset via setFirstRow() and setMaxRows() on filterMany()
This commit is contained in:
@@ -506,7 +506,7 @@ public interface ExpressionList<T> {
|
||||
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
|
||||
* @param params Bind parameters used in the expressions
|
||||
*/
|
||||
Query<T> filterMany(String manyProperty, String expressions, Object... params);
|
||||
ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
|
||||
|
||||
/**
|
||||
* Specify specific properties to fetch on the main/root bean (aka partial
|
||||
@@ -557,14 +557,14 @@ public interface ExpressionList<T> {
|
||||
*
|
||||
* @see Query#setFirstRow(int)
|
||||
*/
|
||||
Query<T> setFirstRow(int firstRow);
|
||||
ExpressionList<T> setFirstRow(int firstRow);
|
||||
|
||||
/**
|
||||
* Set the maximum number of rows to fetch.
|
||||
*
|
||||
* @see Query#setMaxRows(int)
|
||||
*/
|
||||
Query<T> setMaxRows(int maxRows);
|
||||
ExpressionList<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the name of the property which values become the key of a map.
|
||||
|
||||
@@ -36,4 +36,11 @@ public interface SpiExpressionList<T> extends ExpressionList<T>, 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,9 +480,8 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> filterMany(String manyProperty, String expressions, Object... params) {
|
||||
query.filterMany(manyProperty).where(expressions, params);
|
||||
return query;
|
||||
public ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params) {
|
||||
return query.filterMany(manyProperty).where(expressions, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -521,13 +520,15 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setFirstRow(int firstRow) {
|
||||
return query.setFirstRow(firstRow);
|
||||
public ExpressionList<T> setFirstRow(int firstRow) {
|
||||
query.setFirstRow(firstRow);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setMaxRows(int maxRows) {
|
||||
return query.setMaxRows(maxRows);
|
||||
public ExpressionList<T> setMaxRows(int maxRows) {
|
||||
query.setMaxRows(maxRows);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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<T> extends DefaultExpressionList<T> {
|
||||
|
||||
private final FilterExprPath pathPrefix;
|
||||
|
||||
private int firstRow;
|
||||
private int maxRows;
|
||||
|
||||
public FilterExpressionList(FilterExprPath pathPrefix, FilterExpressionList<T> original) {
|
||||
super(null, original.expr, null, original.getUnderlyingList());
|
||||
this.pathPrefix = pathPrefix;
|
||||
@@ -144,19 +148,21 @@ public class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
throw new PersistenceException(notAllowedMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setFirstRow(int firstRow) {
|
||||
return rootQuery.setFirstRow(firstRow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setMapKey(String mapKey) {
|
||||
return rootQuery.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setMaxRows(int maxRows) {
|
||||
return rootQuery.setMaxRows(maxRows);
|
||||
public ExpressionList<T> setMaxRows(int maxRows) {
|
||||
this.maxRows = maxRows;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> setFirstRow(int firstRow) {
|
||||
this.firstRow = firstRow;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -169,5 +175,14 @@ public class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
return rootQuery.where();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyRowLimits(SpiQuery<?> query) {
|
||||
if (firstRow > 0) {
|
||||
query.setFirstRow(firstRow);
|
||||
}
|
||||
if (maxRows > 0) {
|
||||
query.setMaxRows(maxRows);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> filterMany(String manyProperty, String expressions, Object... params) {
|
||||
public ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params) {
|
||||
throw new IllegalStateException("filterMany not allowed on Junction expression list");
|
||||
}
|
||||
|
||||
@@ -864,7 +864,7 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setFirstRow(int firstRow) {
|
||||
public ExpressionList<T> setFirstRow(int firstRow) {
|
||||
return exprList.setFirstRow(firstRow);
|
||||
}
|
||||
|
||||
@@ -874,7 +874,7 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setMaxRows(int maxRows) {
|
||||
public ExpressionList<T> setMaxRows(int maxRows) {
|
||||
return exprList.setMaxRows(maxRows);
|
||||
}
|
||||
|
||||
|
||||
@@ -245,9 +245,9 @@ public class OrmQueryProperties implements Serializable {
|
||||
}
|
||||
|
||||
if (filterMany != null) {
|
||||
filterMany.applyRowLimits(query);
|
||||
SpiExpressionList<?> trimPath = filterMany.trimPath(path.length() + 1);
|
||||
List<SpiExpression> underlyingList = trimPath.getUnderlyingList();
|
||||
for (SpiExpression spiExpression : underlyingList) {
|
||||
for (SpiExpression spiExpression : trimPath.getUnderlyingList()) {
|
||||
query.where().add(spiExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class TestLimitQuery extends BaseTestCase {
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(3)
|
||||
.setFirstRow(0);
|
||||
.setFirstRow(0).query();
|
||||
|
||||
query.findList();
|
||||
|
||||
@@ -96,7 +96,7 @@ public class TestLimitQuery extends BaseTestCase {
|
||||
.setAutoTune(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(10);
|
||||
.setMaxRows(10).query();
|
||||
//.findList();
|
||||
|
||||
List<Order> list = query.findList();
|
||||
|
||||
@@ -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,94 @@ public class TestQueryFilterMany extends BaseTestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterMany_firstMaxRows_fluidStyle() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
final Query<Customer> query = DB.find(Customer.class)
|
||||
.where().ieq("name", "Rob")
|
||||
// fluid style adding maxRows/firstRow to filterMany
|
||||
.filterMany("orders").eq("status", Order.Status.NEW).setMaxRows(100).setFirstRow(3)
|
||||
.order().asc("id").setMaxRows(5);
|
||||
|
||||
final List<Customer> customers = query.findList();
|
||||
assertThat(customers).isNotEmpty();
|
||||
List<String> 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_firstMaxRows() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
final Query<Customer> query = DB.find(Customer.class)
|
||||
.where().ieq("name", "Rob")
|
||||
.order().asc("id").setMaxRows(5);
|
||||
|
||||
// non-fluid style adding maxRows/firstRow
|
||||
final ExpressionList<Customer> filterMany = query.filterMany("orders").eq("status", Order.Status.NEW);
|
||||
filterMany.setMaxRows(100);
|
||||
filterMany.setFirstRow(3);
|
||||
|
||||
final List<Customer> customers = query.findList();
|
||||
assertThat(customers).isNotEmpty();
|
||||
List<String> 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 filterMany_firstMaxRows_expressionFluidStyle() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
final Query<Customer> query = DB.find(Customer.class)
|
||||
.where().ieq("name", "Rob")
|
||||
// use expression + fluid style adding maxRows/firstRow to filterMany
|
||||
.filterMany("orders", "status = ?", Order.Status.NEW).setMaxRows(100).setFirstRow(3)
|
||||
.order().asc("id").setMaxRows(5);
|
||||
|
||||
final List<Customer> customers = query.findList();
|
||||
assertThat(customers).isNotEmpty();
|
||||
List<String> 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() {
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
Query<Customer> query = server.find(Customer.class)
|
||||
.setAutoTune(false)
|
||||
.where().gt("id", "JUNK_NOT_A_LONG")
|
||||
.setMaxRows(2);
|
||||
.setMaxRows(2).query();
|
||||
|
||||
// this throws an exception immediately
|
||||
query.findEach(bean -> {
|
||||
@@ -221,7 +221,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
Query<Customer> query = server.find(Customer.class)
|
||||
.setAutoTune(false)
|
||||
.where().gt("id", 0)
|
||||
.setMaxRows(2);
|
||||
.setMaxRows(2).query();
|
||||
|
||||
query.findEach(customer -> {
|
||||
if (customer != null) {
|
||||
|
||||
Reference in New Issue
Block a user