io.ebeaninternal.api.ManyWhereJoins Maven / Gradle / Ivy
package io.ebeaninternal.api;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import io.ebeaninternal.server.el.ElPropertyDeploy;
import io.ebean.util.SplitName;
import io.ebeaninternal.server.query.SqlJoinType;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Holds the joins needs to support the many where predicates.
* These joins are independent of any 'fetch' joins on the many.
*/
public final class ManyWhereJoins implements Serializable {
private static final long serialVersionUID = -6490181101871795417L;
private final TreeMap joins = new TreeMap<>();
private Map> formulaJoinProperties;
private boolean aggregation;
/**
* 'Mode' indicating that joins added while this is true are required to be outer joins.
*/
private boolean requireOuterJoins;
/**
* Return the current 'mode' indicating if outer joins are currently required or not.
*/
public boolean isRequireOuterJoins() {
return requireOuterJoins;
}
/**
* Set the 'mode' to be that joins added are required to be outer joins.
* This is set during the evaluation of disjunction predicates.
*/
public void setRequireOuterJoins(boolean requireOuterJoins) {
this.requireOuterJoins = requireOuterJoins;
}
/**
* Add a many where join.
*/
public void add(ElPropertyDeploy elProp) {
String join = elProp.elPrefix();
BeanProperty p = elProp.beanProperty();
if (p instanceof BeanPropertyAssocMany>) {
join = addManyToJoin(join, p.name());
}
if (join != null) {
addJoin(join);
if (p != null) {
String secondaryTableJoinPrefix = p.secondaryTableJoinPrefix();
if (secondaryTableJoinPrefix != null) {
addJoin(join + "." + secondaryTableJoinPrefix);
}
}
addParentJoins(join);
}
}
/**
* For 'many' properties we also need to add the name of the
* many property to get the full logical name of the join.
*/
private String addManyToJoin(String join, String manyPropName) {
if (join == null) {
return manyPropName;
} else {
return join + "." + manyPropName;
}
}
private void addParentJoins(String join) {
String[] split = SplitName.split(join);
if (split[0] != null) {
addJoin(split[0]);
addParentJoins(split[0]);
}
}
private void addJoin(String property) {
SqlJoinType joinType = (requireOuterJoins) ? SqlJoinType.OUTER : SqlJoinType.INNER;
joins.put(property, new PropertyJoin(property, joinType));
}
/**
* Return true if this is an aggregation query or if there are no extra many where joins.
*/
public boolean requireSqlDistinct() {
return !aggregation && !joins.isEmpty();
}
/**
* Return the set of many where joins.
*/
public Collection propertyJoins() {
return joins.values();
}
/**
* Return the set of property names for the many where joins.
*/
public TreeSet propertyNames() {
TreeSet propertyNames = new TreeSet<>();
for (PropertyJoin join : joins.values()) {
propertyNames.add(join.property());
}
return propertyNames;
}
/**
* In findCount query found a formula property with a join clause so building a select clause
* specifically for the findCount query.
*/
public void addFormulaWithJoin(String prefix, String name) {
if (formulaJoinProperties == null) {
formulaJoinProperties = new HashMap<>();
}
formulaJoinProperties.computeIfAbsent(prefix, k -> new ArrayList<>()).add(name);
}
/**
* Return true if the query select includes a formula with join.
*/
public boolean isFormulaWithJoin(String prefix) {
return formulaJoinProperties != null && formulaJoinProperties.containsKey(prefix);
}
/**
* Return the formula properties to build the select clause for a findCount query.
*/
public List formulaJoinProperties(String prefix) {
return formulaJoinProperties.get(prefix);
}
/**
* Mark this as part of an aggregation query (so using group by clause).
*/
public void setAggregation() {
aggregation = true;
}
/**
* Ensure we have the join required to support the aggregation properties.
*/
public void addAggregationJoin(String property) {
this.aggregation = true;
joins.put(property, new PropertyJoin(property, SqlJoinType.INNER));
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy