mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-11-10 00:44:15 +00:00
#1737 - PersistenceException while using aggregate query on related entity
This part includes support for joins off an aggregation formula
on a ManyToOne.
e.g. We use min(customer) ... to 'query join' to customer
in the query below.
List<Contact> contacts = Ebean.find(Contact.class)
.select("lastName, min(customer)")
.fetchQuery("customer", "name, status")
.findList();
This commit is contained in:
1 parent
24b08663af
commit
a932d61a94
7 files changed
+122
-72
No files matched your search
@@ -39,6 +39,13 @@ public interface STreeProperty extends ScalarDataReader<Object> {
|
||||
*/
|
||||
boolean isAggregation();
|
||||
|
||||
/**
|
||||
* Return true if the property is an aggregation on a ManyToOne.
|
||||
*/
|
||||
default boolean isAggregationManyToOne() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is a formula.
|
||||
*/
|
||||
|
||||
@@ -273,10 +273,7 @@ public final class SqlTreeBuilder {
|
||||
OrmQueryProperties queryProps = queryDetail.getChunk(prefix, false);
|
||||
SqlTreeProperties props = getBaseSelect(desc, queryProps);
|
||||
|
||||
if (prefix != null) {
|
||||
// check for aggregation on a fetch
|
||||
props.checkAggregation();
|
||||
} else if (!rawSql) {
|
||||
if (prefix == null && !rawSql) {
|
||||
if (props.requireSqlDistinct(manyWhereJoins)) {
|
||||
sqlDistinct = true;
|
||||
}
|
||||
@@ -479,12 +476,24 @@ public final class SqlTreeBuilder {
|
||||
// Also note that this can include transient properties.
|
||||
// This makes sense for transient properties used to
|
||||
// hold sum() count() type values (with SqlSelect)
|
||||
for (String propName : queryProps.getSelectProperties()) {
|
||||
final Set<String> selectInclude = queryProps.getSelectInclude();
|
||||
for (String propName : selectInclude) {
|
||||
if (!propName.isEmpty()) {
|
||||
addProperty(selectProps, desc, queryProps, propName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectProps.isAggregationManyToOne()) {
|
||||
final Set<String> selectQueryJoin = queryProps.getSelectQueryJoin();
|
||||
if (selectQueryJoin != null) {
|
||||
for (String joinProperty : selectQueryJoin) {
|
||||
if (!selectInclude.contains(joinProperty)) {
|
||||
addProperty(selectProps, desc, queryProps, joinProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selectProps;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ public class SqlTreeProperties {
|
||||
|
||||
private boolean allProperties;
|
||||
|
||||
private boolean aggregationManyToOne;
|
||||
|
||||
private boolean aggregation;
|
||||
|
||||
private String aggregationPath;
|
||||
@@ -47,6 +49,15 @@ public class SqlTreeProperties {
|
||||
public void add(STreeProperty prop) {
|
||||
propsList.add(prop);
|
||||
propNames.add(prop.getName());
|
||||
if (prop.isAggregation()) {
|
||||
if (!aggregation) {
|
||||
aggregation = true;
|
||||
aggregationPath = prop.getElPrefix();
|
||||
}
|
||||
if (prop.isAggregationManyToOne()) {
|
||||
aggregationManyToOne = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public STreeProperty[] getProps() {
|
||||
@@ -85,6 +96,13 @@ public class SqlTreeProperties {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is an aggregation formula on a ManyToOne.
|
||||
*/
|
||||
boolean isAggregationManyToOne() {
|
||||
return aggregationManyToOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this contains an aggregation property.
|
||||
*/
|
||||
@@ -92,33 +110,17 @@ public class SqlTreeProperties {
|
||||
return aggregation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for aggregation (need for groug by clause).
|
||||
*/
|
||||
public void checkAggregation() {
|
||||
aggregationJoin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property to join for aggregation.
|
||||
*/
|
||||
private String aggregationJoin() {
|
||||
if (!allProperties) {
|
||||
for (STreeProperty beanProperty : propsList) {
|
||||
if (beanProperty.isAggregation()) {
|
||||
aggregation = true;
|
||||
aggregationPath = beanProperty.getElPrefix();
|
||||
return aggregationPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return aggregationPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a top level aggregation which means the Id property must be excluded.
|
||||
*/
|
||||
public boolean isAggregationRoot() {
|
||||
boolean isAggregationRoot() {
|
||||
return aggregation && (aggregationPath == null);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user