mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-20 00:17:04 +00:00
#3666 Fix for NPE with filterMany() containing or()
For FilterMany with QueryBeans, it creates a queryBean to build the filterMany predicates with. This query bean needed 2 changes for this fix: 1. Needs to set it's internal "root" such that it supports chaining (required for or() etc) 2. The ExpressionFactory needs to be explicitly passed to the expression list (rather than get it from the query which is actually null in this case).
This commit is contained in:
+6
-6
@@ -726,7 +726,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public <T> Junction<T> conjunction(Query<T> query) {
|
||||
return new JunctionExpression<>(Junction.Type.AND, query, query.where());
|
||||
return new JunctionExpression<>(Junction.Type.AND, query, this, query.where());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -734,7 +734,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public <T> Junction<T> disjunction(Query<T> query) {
|
||||
return new JunctionExpression<>(Junction.Type.OR, query, query.where());
|
||||
return new JunctionExpression<>(Junction.Type.OR, query, this, query.where());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -742,7 +742,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public <T> Junction<T> conjunction(Query<T> query, ExpressionList<T> parent) {
|
||||
return new JunctionExpression<>(Junction.Type.AND, query, parent);
|
||||
return new JunctionExpression<>(Junction.Type.AND, query, this, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -750,14 +750,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public <T> Junction<T> disjunction(Query<T> query, ExpressionList<T> parent) {
|
||||
return new JunctionExpression<>(Junction.Type.OR, query, parent);
|
||||
return new JunctionExpression<>(Junction.Type.OR, query, this, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of expressions that are wrapped by NOT.
|
||||
*/
|
||||
public <T> Junction<T> junction(Junction.Type type, Query<T> query) {
|
||||
return new JunctionExpression<>(type, query, query.where());
|
||||
return new JunctionExpression<>(type, query, this, query.where());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -765,6 +765,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public <T> Junction<T> junction(Junction.Type type, Query<T> query, ExpressionList<T> parent) {
|
||||
return new JunctionExpression<>(type, query, parent);
|
||||
return new JunctionExpression<>(type, query, this, parent);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-6
@@ -40,12 +40,8 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
/**
|
||||
* Construct for Text root expression list - this handles implicit Bool Should, Must etc.
|
||||
*/
|
||||
public DefaultExpressionList(Query<T> query) {
|
||||
this(query, query.getExpressionFactory(), null, new ArrayList<>(), true);
|
||||
}
|
||||
|
||||
public DefaultExpressionList(Query<T> query, ExpressionList<T> parentExprList) {
|
||||
this(query, query.getExpressionFactory(), parentExprList, new ArrayList<>());
|
||||
public DefaultExpressionList(Query<T> query, boolean textRoot) {
|
||||
this(query, query.getExpressionFactory(), null, new ArrayList<>(), textRoot);
|
||||
}
|
||||
|
||||
DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList, List<SpiExpression> list) {
|
||||
|
||||
@@ -24,9 +24,9 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
DefaultExpressionList<T> exprList;
|
||||
Junction.Type type;
|
||||
|
||||
JunctionExpression(Junction.Type type, Query<T> query, ExpressionList<T> parent) {
|
||||
JunctionExpression(Junction.Type type, Query<T> query, ExpressionFactory expr, ExpressionList<T> parent) {
|
||||
this.type = type;
|
||||
this.exprList = new DefaultExpressionList<>(query, parent);
|
||||
this.exprList = new DefaultExpressionList<>(query, expr, parent, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1895,7 +1895,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
public final ExpressionList<T> text() {
|
||||
if (textExpressions == null) {
|
||||
useDocStore = true;
|
||||
textExpressions = new DefaultExpressionList<>(this);
|
||||
textExpressions = new DefaultExpressionList<>(this, true);
|
||||
}
|
||||
return textExpressions;
|
||||
}
|
||||
@@ -1903,7 +1903,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
@Override
|
||||
public final ExpressionList<T> where() {
|
||||
if (whereExpressions == null) {
|
||||
whereExpressions = new DefaultExpressionList<>(this, null);
|
||||
whereExpressions = new DefaultExpressionList<>(this, false);
|
||||
}
|
||||
return whereExpressions;
|
||||
}
|
||||
@@ -1924,7 +1924,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
@Override
|
||||
public final ExpressionList<T> having() {
|
||||
if (havingExpressions == null) {
|
||||
havingExpressions = new DefaultExpressionList<>(this, null);
|
||||
havingExpressions = new DefaultExpressionList<>(this, false);
|
||||
}
|
||||
return havingExpressions;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public abstract class QueryBean<T, R extends QueryBean<T, R>> implements IQueryB
|
||||
/** Construct for FilterMany */
|
||||
protected QueryBean(ExpressionList<T> filter) {
|
||||
this.query = null;
|
||||
this.root = null;
|
||||
this.root = (R) this;
|
||||
this.whereStack = new ArrayStack<>();
|
||||
whereStack.push(filter);
|
||||
}
|
||||
|
||||
@@ -377,6 +377,20 @@ public class QCustomerTest {
|
||||
assertThat(q.getGeneratedSql()).contains(" from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where (t1.id is null or (t1.first_name like ? and t1.first_name like ? escape'|')) order by t0.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterManyOr() {
|
||||
var q = new QCustomer()
|
||||
.contacts.filterMany(c ->
|
||||
c.or()
|
||||
.firstName.startsWith("R")
|
||||
.lastName.startsWith("R")
|
||||
.endOr())
|
||||
.query();
|
||||
|
||||
q.findList();
|
||||
assertThat(q.getGeneratedSql()).contains(" from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where (t1.id is null or ((t1.first_name like ? escape'|' or t1.last_name like ? escape'|'))) order by t0.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdIn() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user