All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ebeaninternal.api.ManyWhereJoins Maven / Gradle / Ivy

There is a newer version: 15.8.0
Show newest version
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