#99 - ENH (419) : Simplify aggregation queries - part 2

This commit is contained in:
Rob Bygrave
2016-11-03 23:06:54 +13:00
parent 3526f71f0a
commit d0230491e5
11 changed files with 104 additions and 26 deletions
@@ -155,4 +155,11 @@ public class ManyWhereJoins implements Serializable {
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));
}
}
@@ -236,11 +236,17 @@ public class SqlTreeBuilder {
}
}
OrmQueryProperties queryProps = queryDetail.getChunk(prefix, false);
SqlTreeProperties props = getBaseSelect(desc, queryProps);
if (prefix == null && !rawSql) {
if (props.requireSqlDistinct(manyWhereJoins)) {
query.setSqlDistinct(true);
}
addManyWhereJoins(myJoinList);
}
SqlTreeNode selectNode = buildNode(prefix, prop, desc, myJoinList);
SqlTreeNode selectNode = buildNode(prefix, prop, desc, myJoinList, props);
if (joinList != null) {
joinList.add(selectNode);
}
@@ -264,11 +270,7 @@ public class SqlTreeBuilder {
}
}
private SqlTreeNode buildNode(String prefix, BeanPropertyAssoc<?> prop, BeanDescriptor<?> desc, List<SqlTreeNode> myList) {
OrmQueryProperties queryProps = queryDetail.getChunk(prefix, false);
SqlTreeProperties props = getBaseSelect(desc, queryProps);
private SqlTreeNode buildNode(String prefix, BeanPropertyAssoc<?> prop, BeanDescriptor<?> desc, List<SqlTreeNode> myList, SqlTreeProperties props) {
if (prefix == null) {
buildExtraJoins(desc, myList);
@@ -10,7 +10,7 @@ import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
import java.sql.SQLException;
import java.util.List;
public interface SqlTreeNode {
interface SqlTreeNode {
String COMMA = ", ";
@@ -27,7 +27,7 @@ import java.util.Map;
/**
* Normal bean included in the query.
*/
public class SqlTreeNodeBean implements SqlTreeNode {
class SqlTreeNodeBean implements SqlTreeNode {
private static final SqlTreeNode[] NO_CHILDREN = new SqlTreeNode[0];
@@ -83,7 +83,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
*/
private boolean intersectionAsOfTableAlias;
private boolean aggregation;
private final boolean aggregation;
/**
* Construct for leaf node.
@@ -127,6 +127,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
this.partialObject = props.isPartialObject();
this.properties = props.getProps();
this.aggregation = props.isAggregation();
this.children = myChildren == null ? NO_CHILDREN : myChildren.toArray(new SqlTreeNode[myChildren.size()]);
pathMap = createPathMap(prefix, desc);
@@ -447,9 +448,6 @@ public class SqlTreeNodeBean implements SqlTreeNode {
for (int i = 0; i < props.length; i++) {
props[i].appendSelect(ctx, subQuery);
if (props[i].isAggregation()) {
aggregation = true;
}
}
}
@@ -22,7 +22,7 @@ import java.util.List;
* etc in this case we must add an extra join.
* </p>
*/
public class SqlTreeNodeExtraJoin implements SqlTreeNode {
class SqlTreeNodeExtraJoin implements SqlTreeNode {
private final BeanPropertyAssoc<?> assocBeanProperty;
@@ -34,7 +34,7 @@ public class SqlTreeNodeExtraJoin implements SqlTreeNode {
private List<SqlTreeNodeExtraJoin> children;
public SqlTreeNodeExtraJoin(String prefix, BeanPropertyAssoc<?> assocBeanProperty, boolean pathContainsMany) {
SqlTreeNodeExtraJoin(String prefix, BeanPropertyAssoc<?> assocBeanProperty, boolean pathContainsMany) {
this.prefix = prefix;
this.assocBeanProperty = assocBeanProperty;
this.pathContainsMany = pathContainsMany;
@@ -8,11 +8,11 @@ import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
import java.sql.SQLException;
import java.util.List;
public final class SqlTreeNodeManyRoot extends SqlTreeNodeBean {
final class SqlTreeNodeManyRoot extends SqlTreeNodeBean {
private final BeanPropertyAssocMany<?> manyProp;
public SqlTreeNodeManyRoot(String prefix, BeanPropertyAssocMany<?> prop, SqlTreeProperties props, List<SqlTreeNode> myList, boolean disableLazyLoad) {
SqlTreeNodeManyRoot(String prefix, BeanPropertyAssocMany<?> prop, SqlTreeProperties props, List<SqlTreeNode> myList, boolean disableLazyLoad) {
super(prefix, prop, props, myList, disableLazyLoad);
this.manyProp = prop;
}
@@ -17,7 +17,7 @@ import java.util.List;
/**
* Join to Many (or child of a many) to support where clause predicates on many properties.
*/
public class SqlTreeNodeManyWhereJoin implements SqlTreeNode {
class SqlTreeNodeManyWhereJoin implements SqlTreeNode {
private final String parentPrefix;
@@ -11,7 +11,7 @@ import java.util.List;
/**
* Represents the root node of the Sql Tree.
*/
public final class SqlTreeNodeRoot extends SqlTreeNodeBean {
final class SqlTreeNodeRoot extends SqlTreeNodeBean {
private final TableJoin includeJoin;
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import com.avaje.ebeaninternal.api.ManyWhereJoins;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
@@ -33,6 +34,8 @@ public class SqlTreeProperties {
private boolean allProperties;
private boolean aggregation;
public SqlTreeProperties() {
}
@@ -80,4 +83,41 @@ public class SqlTreeProperties {
this.allProperties = true;
}
/**
* Check for an aggregation property and set manyWhereJoin as needed.
* <p>
* Return true if a Sql distinct is required.
* </p>
*/
public boolean requireSqlDistinct(ManyWhereJoins manyWhereJoins) {
String joinProperty = aggregationJoin();
if (joinProperty != null) {
aggregation = true;
manyWhereJoins.addAggregationJoin(joinProperty);
return false;
} else{
return manyWhereJoins.requireSqlDistinct();
}
}
/**
* Return true if this contains an aggregation property.
*/
public boolean isAggregation() {
return aggregation;
}
/**
* Return the property to join for aggregation.
*/
private String aggregationJoin() {
if (!allProperties) {
for (BeanProperty beanProperty : propsList) {
if (beanProperty.isAggregation()) {
return beanProperty.getElPrefix();
}
}
}
return null;
}
}
@@ -373,9 +373,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
if (havingExpressions != null) {
havingExpressions.containsMany(beanDescriptor, manyWhereJoins);
}
if (manyWhereJoins.requireSqlDistinct()) {
setSqlDistinct(true);
}
}
/**