if (aggOps.isEmpty()) {
final ProjectOperator project = new ProjectOperator(groupByVEs);
affectedComponent.addOperator(project);
} else if (aggOps.size() == 1) {
// all the others are group by
final AggregateOperator firstAgg = aggOps.get(0);
if (ParserUtil.isAllColumnRefs(groupByVEs)) {
// plain fields in select
final List<Integer> groupByColumns = ParserUtil.extractColumnIndexes(groupByVEs);
firstAgg.setGroupByColumns(groupByColumns);
// Setting new level of components is necessary for correctness
// only for distinct in aggregates
// but it's certainly pleasant to have the final result grouped
// on nodes by group by columns.
final boolean newLevel = !(_it.isHashedBy(affectedComponent, groupByColumns));
if (newLevel) {
affectedComponent.setHashIndexes(groupByColumns);
new OperatorComponent(affectedComponent,
ParserUtil.generateUniqueName("OPERATOR"), _cg.getQueryPlan())
.addOperator(firstAgg);
} else
affectedComponent.addOperator(firstAgg);
} else {
// Sometimes groupByVEs contains other functions, so we have to
// use projections instead of simple groupBy
// always new level
if (affectedComponent.getHashExpressions() != null
&& !affectedComponent.getHashExpressions().isEmpty())
throw new RuntimeException(
"Too complex: cannot have hashExpression both for joinCondition and groupBy!");
// WARNING: groupByVEs cannot be used on two places: that's why
// we do deep copy
final ProjectOperator groupByProj = new ProjectOperator(
(List<ValueExpression>) DeepCopy.copy(groupByVEs));
if (!(groupByProj.getExpressions() == null || groupByProj.getExpressions()
.isEmpty()))
firstAgg.setGroupByProjection(groupByProj);
// current component
affectedComponent.setHashExpressions((List<ValueExpression>) DeepCopy
.copy(groupByVEs));