if ( accs == null )
{
for ( ExprAggregator agg : aggregators )
{
Accumulator x = agg.getAggregator().createAccumulator() ;
Var v = agg.getVar() ;
accumulators.put(key, Pair.create(v, x)) ;
}
accs = accumulators.get(key) ;
}
// Do the per-accumulator calculation.
for ( Pair<Var, Accumulator> pair : accs )
pair.getRight().accumulate(b, execCxt) ;
}
// Phase 2 : Empty input
// has as iter.hasNext false at start.
// If there are no binding from the input stage, two things can happen.
// If there are no aggregators, there are no groups.
// If there are aggregators, then they may have a default value.
if ( accumulators.isEmpty() )
{
if ( noAggregators )
{
// No rows to group, no aggregators.
// ==> No result rows.
return Iter.nullIterator() ;
}
BindingMap binding = BindingFactory.create() ;
for ( Iterator<ExprAggregator> aggIter = aggregators.iterator() ; aggIter.hasNext() ; )
{
ExprAggregator agg = aggIter.next();
Var v = agg.getVar() ;
Node value = agg.getAggregator().getValueEmpty() ;
if ( value != null )
binding.add(v, value) ;
}
if ( binding == null )
// This does not happen if there are any aggregators.
return Iter.nullIterator() ;
// cast to get the static type inference to work.
return Iter.singletonIter((Binding)binding) ;
}
// Phase 2 : There was input and so there are some groups.
// For each bucket, get binding, add aggregator values to the binding.
// We used AccNull so there are always accumulators.
if ( noAggregators )
// We used placeholder so there are always the key.
return accumulators.keys().iterator() ;
List<Binding> results = new ArrayList<Binding>() ;
for ( Binding k : accumulators.keys() )
{
Collection<Pair<Var, Accumulator>> accs = accumulators.get(k) ;
BindingMap b = BindingFactory.create(k) ;
for ( Pair<Var, Accumulator> pair : accs )
{
Var v = pair.getLeft() ;
NodeValue value = pair.getRight().getValue() ;
Node n = (value==null) ? null : value.asNode() ;
if ( v == null || n == null )
{}
else