com.avaje.ebeaninternal.server.expression.JunctionExpression Maven / Gradle / Ivy
package com.avaje.ebeaninternal.server.expression;
import com.avaje.ebean.Expression;
import com.avaje.ebean.ExpressionList;
import com.avaje.ebean.FetchPath;
import com.avaje.ebean.FutureIds;
import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.Junction;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryEachConsumer;
import com.avaje.ebean.QueryEachWhileConsumer;
import com.avaje.ebean.Version;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebean.search.Match;
import com.avaje.ebean.search.MultiMatch;
import com.avaje.ebean.search.TextCommonTerms;
import com.avaje.ebean.search.TextQueryString;
import com.avaje.ebean.search.TextSimple;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.api.ManyWhereJoins;
import com.avaje.ebeaninternal.api.SpiExpression;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
import com.avaje.ebeaninternal.api.SpiJunction;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Junction implementation.
*/
class JunctionExpression implements SpiJunction, SpiExpression, ExpressionList {
protected DefaultExpressionList exprList;
protected Junction.Type type;
JunctionExpression(Junction.Type type, Query query, ExpressionList parent) {
this.type = type;
this.exprList = new DefaultExpressionList(query, parent);
}
/**
* Construct for copyForPlanKey.
*/
JunctionExpression(Junction.Type type, DefaultExpressionList exprList) {
this.type = type;
this.exprList = exprList;
}
/**
* Simplify nested expressions where possible.
*
* This is expected to only used after expressions are built via query language parsing.
*
*/
public void simplify() {
exprList.simplifyEntries();
List list = exprList.list;
if (list.size() == 1 && list.get(0) instanceof JunctionExpression) {
JunctionExpression nested = (JunctionExpression)list.get(0);
if (type == Type.AND && !nested.type.isText()) {
// and (and (a, b, c)) -> and (a, b, c)
// and (not (a, b, c)) -> not (a, b, c)
// and (or (a, b, c)) -> or (a, b, c)
this.exprList = nested.exprList;
this.type = nested.type;
} else if (type == Type.NOT && nested.type == Type.AND) {
// not (and (a, b, c)) -> not (a, b, c)
this.exprList = nested.exprList;
}
}
}
public SpiExpression copyForPlanKey() {
return new JunctionExpression(type, exprList.copyForPlanKey());
}
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
context.startBool(type);
List list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).writeDocQuery(context);
}
context.endBool();
}
@Override
public void writeDocQueryJunction(DocQueryContext context) throws IOException {
context.startBoolGroupList(type);
List list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).writeDocQuery(context);
}
context.endBoolGroupList();
}
@Override
public Object getIdEqualTo(String idName) {
// always null for this expression
return null;
}
@Override
public void containsMany(BeanDescriptor> desc, ManyWhereJoins manyWhereJoin) {
List list = exprList.internalList();
// get the current state for 'require outer joins'
boolean parentOuterJoins = manyWhereJoin.isRequireOuterJoins();
if (type == Type.OR) {
// turn on outer joins required for disjunction expressions
manyWhereJoin.setRequireOuterJoins(true);
}
for (int i = 0; i < list.size(); i++) {
list.get(i).containsMany(desc, manyWhereJoin);
}
if (type == Type.OR && !parentOuterJoins) {
// restore state to not forcing outer joins
manyWhereJoin.setRequireOuterJoins(false);
}
}
@Override
public void validate(SpiExpressionValidation validation) {
exprList.validate(validation);
}
@Override
public Junction add(Expression item) {
exprList.add(item);
return this;
}
@Override
public Junction addAll(ExpressionList addList) {
exprList.addAll(addList);
return this;
}
@Override
public void addBindValues(SpiExpressionRequest request) {
List list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).addBindValues(request);
}
}
@Override
public void addSql(SpiExpressionRequest request) {
List list = exprList.internalList();
if (!list.isEmpty()) {
request.append(type.prefix());
request.append("(");
for (int i = 0; i < list.size(); i++) {
SpiExpression item = list.get(i);
if (i > 0) {
request.append(type.literal());
}
item.addSql(request);
}
request.append(") ");
}
}
@Override
public void prepareExpression(BeanQueryRequest> request) {
List list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).prepareExpression(request);
}
}
/**
* Based on Junction type and all the expression contained.
*/
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(JunctionExpression.class).add(type);
List list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).queryPlanHash(builder);
}
}
@Override
public int queryBindHash() {
int hc = JunctionExpression.class.getName().hashCode();
List list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
hc = hc * 31 + list.get(i).queryBindHash();
}
return hc;
}
@Override
public boolean isSameByPlan(SpiExpression other) {
if (!(other instanceof JunctionExpression)) {
return false;
}
JunctionExpression that = (JunctionExpression) other;
return type == that.type && exprList.isSameByPlan(that.exprList);
}
@Override
public boolean isSameByBind(SpiExpression other) {
JunctionExpression that = (JunctionExpression) other;
return type == that.type && exprList.isSameByBind(that.exprList);
}
@Override
public ExpressionList match(String propertyName, String search) {
return match(propertyName, search, null);
}
@Override
public ExpressionList match(String propertyName, String search, Match options) {
return exprList.match(propertyName, search, options);
}
@Override
public ExpressionList multiMatch(String query, String... properties) {
return exprList.multiMatch(query, properties);
}
@Override
public ExpressionList multiMatch(String query, MultiMatch options) {
return exprList.multiMatch(query, options);
}
@Override
public ExpressionList textSimple(String search, TextSimple options) {
return exprList.textSimple(search, options);
}
@Override
public ExpressionList textQueryString(String search, TextQueryString options) {
return exprList.textQueryString(search, options);
}
@Override
public ExpressionList textCommonTerms(String search, TextCommonTerms options) {
return exprList.textCommonTerms(search, options);
}
@Override
public ExpressionList allEq(Map propertyMap) {
return exprList.allEq(propertyMap);
}
@Override
public ExpressionList and(Expression expOne, Expression expTwo) {
return exprList.and(expOne, expTwo);
}
@Override
public ExpressionList between(String propertyName, Object value1, Object value2) {
return exprList.between(propertyName, value1, value2);
}
@Override
public ExpressionList betweenProperties(String lowProperty, String highProperty, Object value) {
return exprList.betweenProperties(lowProperty, highProperty, value);
}
@Override
public ExpressionList contains(String propertyName, String value) {
return exprList.contains(propertyName, value);
}
@Override
public ExpressionList endsWith(String propertyName, String value) {
return exprList.endsWith(propertyName, value);
}
@Override
public ExpressionList eq(String propertyName, Object value) {
return exprList.eq(propertyName, value);
}
@Override
public ExpressionList exampleLike(Object example) {
return exprList.exampleLike(example);
}
@Override
public ExpressionList filterMany(String prop) {
throw new RuntimeException("filterMany not allowed on Junction expression list");
}
@Override
public int delete() {
return exprList.delete();
}
@Override
public int update() {
return exprList.update();
}
@Override
public Query asOf(Timestamp asOf) {
return exprList.asOf(asOf);
}
@Override
public Query asDraft() {
return exprList.asDraft();
}
@Override
public Query includeSoftDeletes() {
return setIncludeSoftDeletes();
}
@Override
public Query setIncludeSoftDeletes() {
return exprList.setIncludeSoftDeletes();
}
@Override
public List> findVersions() {
return exprList.findVersions();
}
@Override
public List> findVersionsBetween(Timestamp start, Timestamp end) {
return exprList.findVersionsBetween(start, end);
}
@Override
public Query apply(FetchPath fetchPath) {
return exprList.apply(fetchPath);
}
@Override
public FutureIds findFutureIds() {
return exprList.findFutureIds();
}
@Override
public FutureList findFutureList() {
return exprList.findFutureList();
}
@Override
public FutureRowCount findFutureCount() {
return exprList.findFutureCount();
}
@Override
public FutureRowCount findFutureRowCount() {
return findFutureCount();
}
@Override
public List