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.List;
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.
/**
* Holds the joins needs to support the many where predicates.
* These joins are independent of any 'fetch' joins on the many.
*/
public class ManyWhereJoins implements Serializable {
private static final long serialVersionUID = -6490181101871795417L;
private final TreeMap<String, PropertyJoin> joins = new TreeMap<>();
private List<String> formulaJoinProperties;
private boolean aggregation;
'Mode' indicating that joins added while this is true are required to be outer joins.
/**
* '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.
/**
* 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.
/**
* 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.
/**
* Add a many where join.
*/
public void add(ElPropertyDeploy elProp) {
String join = elProp.getElPrefix();
BeanProperty p = elProp.getBeanProperty();
if (p instanceof BeanPropertyAssocMany<?>) {
join = addManyToJoin(join, p.getName());
}
if (join != null) {
addJoin(join);
if (p != null) {
String secondaryTableJoinPrefix = p.getSecondaryTableJoinPrefix();
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.
/**
* 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.
/**
* 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.
/**
* Return the set of many where joins.
*/
public Collection<PropertyJoin> getPropertyJoins() {
return joins.values();
}
Return the set of property names for the many where joins.
/**
* Return the set of property names for the many where joins.
*/
public TreeSet<String> getPropertyNames() {
TreeSet<String> propertyNames = new TreeSet<>();
for (PropertyJoin join : joins.values()) {
propertyNames.add(join.getProperty());
}
return propertyNames;
}
In findCount query found a formula property with a join clause so building a select clause
specifically for the findCount query.
/**
* 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 propertyName) {
if (formulaJoinProperties == null) {
formulaJoinProperties = new ArrayList<>();
}
formulaJoinProperties.add(propertyName);
}
Return true if the query select includes a formula with join.
/**
* Return true if the query select includes a formula with join.
*/
public boolean isFormulaWithJoin() {
return formulaJoinProperties != null;
}
Return the formula properties to build the select clause for a findCount query.
/**
* Return the formula properties to build the select clause for a findCount query.
*/
public List<String> getFormulaJoinProperties() {
return formulaJoinProperties;
}
Mark this as part of an aggregation query (so using group by clause).
/**
* 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.
/**
* 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));
}
}