@Override public PhysicalOperator visitCollapsingAggregate(CollapsingAggregate agg, Object value) throws OptimizerException { if (!(agg.getInput() instanceof Segment)) { throw new OptimizerException( String.format( "Currently, Drill only supports CollapsingAggregate immediately preceded by a Segment. The input of this operator is %s.", agg.getInput())); } Segment segment = (Segment) agg.getInput(); if (!agg.getWithin().equals(segment.getName())) { throw new OptimizerException( String.format( "Currently, Drill only supports CollapsingAggregate immediately preceded by a Segment where the CollapsingAggregate works on the defined segments. In this case, the segment has been defined based on the name %s but the collapsing aggregate is working within the field %s.", segment.getName(), agg.getWithin())); } // a collapsing aggregate is a currently implemented as a sort followed by a streaming // aggregate. List<OrderDef> orderDefs = Lists.newArrayList(); List<NamedExpression> keys = Lists.newArrayList(); for (LogicalExpression e : segment.getExprs()) { if (!(e instanceof SchemaPath)) throw new OptimizerException( "The basic optimizer doesn't currently support collapsing aggregate where the segment value is something other than a SchemaPath."); keys.add(new NamedExpression(e, new FieldReference((SchemaPath) e))); orderDefs.add(new OrderDef(Direction.ASC, e)); } Sort sort = new Sort(segment.getInput().accept(this, value), orderDefs, false); StreamingAggregate sa = new StreamingAggregate( sort, keys.toArray(new NamedExpression[keys.size()]), agg.getAggregations(), 1.0f); return sa; }