package net.sourceforge.mayfly.evaluation;
import net.sourceforge.mayfly.MayflyException;
import net.sourceforge.mayfly.evaluation.condition.Condition;
import net.sourceforge.mayfly.evaluation.select.Evaluator;
import net.sourceforge.mayfly.evaluation.what.Selected;
import net.sourceforge.mayfly.util.ImmutableList;
public class GroupBy implements Aggregator {
private final GroupByKeys keys;
private final Condition having;
public GroupBy(ImmutableList<GroupItem> items, Condition having) {
this(new GroupByKeys(items), having);
}
public GroupBy(GroupItem... item) {
this(ImmutableList.fromArray(item), Condition.TRUE);
}
public GroupBy(GroupByKeys keys, Condition having) {
this.keys = keys;
this.having = having;
}
public GroupedRows makeGroupedRows(ResultRows resultRows, Evaluator evaluator) {
GroupedRows grouped = new GroupedRows();
for (ResultRow row : resultRows) {
grouped.add(keys, row, evaluator);
}
return grouped;
}
public ResultRows group(ResultRows rows, Evaluator evaluator, Selected selected) {
ResultRows resultOfGrouping = makeGroupedRows(rows, evaluator).ungroup(selected);
return resultOfGrouping.select(having, evaluator);
}
public Aggregator resolve(ResultRow afterJoins, Evaluator evaluator) {
Condition newHaving = having.resolve(afterJoins, evaluator);
GroupByKeys newKeys = keys.resolve(afterJoins, evaluator);
if (newHaving != having || newKeys != keys) {
return new GroupBy(newKeys, newHaving);
}
else {
return this;
}
}
public ResultRow check(ResultRow afterJoins, Evaluator evaluator, Selected selected) {
GroupedRows grouped = makeGroupedRows(new ResultRows(afterJoins), evaluator);
ResultRows resultOfGrouping = grouped.ungroup(selected);
ResultRow afterGroupBy = resultOfGrouping.singleRow();
checkHaving(afterJoins, afterGroupBy, evaluator);
return afterGroupBy;
}
private void checkHaving(ResultRow afterJoins, ResultRow afterGroupBy,
Evaluator evaluator) {
try {
having.evaluate(afterGroupBy, evaluator);
}
catch (NoColumn doesNotSurviveGroupBy) {
having.evaluate(afterJoins, evaluator);
throw new MayflyException(doesNotSurviveGroupBy.displayName() +
" is not aggregate or mentioned in GROUP BY",
having.location());
}
}
}