public LogicalNode visitProjection(PlanContext context, Stack<Expr> stack, Projection projection)
throws PlanningException {
LogicalPlan plan = context.plan;
QueryBlock block = context.queryBlock;
// If a non-from statement is given
if (!projection.hasChild()) {
return buildPlanForNoneFromStatement(context, stack, projection);
}
String [] referenceNames;
// in prephase, insert all target list into NamedExprManagers.
// Then it gets reference names, each of which points an expression in target list.
referenceNames = doProjectionPrephase(context, projection);
////////////////////////////////////////////////////////
// Visit and Build Child Plan
////////////////////////////////////////////////////////
stack.push(projection);
LogicalNode child = visit(context, stack, projection.getChild());
// check if it is implicit aggregation. If so, it inserts group-by node to its child.
if (block.isAggregationRequired()) {
child = insertGroupbyNode(context, child, stack);
}
stack.pop();
////////////////////////////////////////////////////////
ProjectionNode projectionNode;
Target [] targets;
targets = buildTargets(plan, block, referenceNames);
// Set ProjectionNode
projectionNode = context.queryBlock.getNodeFromExpr(projection);
projectionNode.setInSchema(child.getOutSchema());
projectionNode.setTargets(targets);
projectionNode.setChild(child);
if (projection.isDistinct() && block.hasNode(NodeType.GROUP_BY)) {
throw new VerifyException("Cannot support grouping and distinct at the same time yet");
} else {
if (projection.isDistinct()) {
insertDistinctOperator(context, projectionNode, child, stack);
}