public LogicalNode visitProjection(PlanContext context, Stack<OpType> stack, Projection projection)
throws PlanningException {
//1: init Phase
LogicalPlan plan = context.plan;
QueryBlock block = context.block;
if (!projection.isAllProjected()) {
block.targetListManager = new TargetListManager(plan, projection);
}
if (!projection.hasChild()) {
EvalExprNode evalOnly =
new EvalExprNode(context.plan.newPID(), annotateTargets(plan, block, projection.getTargets()));
evalOnly.setOutSchema(getProjectedSchema(plan, evalOnly.getExprs()));
block.setProjectionNode(evalOnly);
for (int i = 0; i < evalOnly.getTargets().length; i++) {
block.targetListManager.fill(i, evalOnly.getTargets()[i]);
}
return evalOnly;
}
// 2: Build Child Plans
stack.push(OpType.Projection);
LogicalNode child = visitChild(context, stack, projection.getChild());
child = insertGroupbyNodeIfUnresolved(plan, block, child, stack);
stack.pop();
// All targets must be evaluable before the projection.
Preconditions.checkState(block.getTargetListManager().isAllResolved(),
"Some targets cannot be evaluated in the query block \"%s\"", block.getName());
ProjectionNode projectionNode;
if (projection.isAllProjected()) {
projectionNode = new ProjectionNode(context.plan.newPID(), PlannerUtil.schemaToTargets(child.getOutSchema()));
} else {
projectionNode = new ProjectionNode(context.plan.newPID(), block.getCurrentTargets());
}
block.setProjectionNode(projectionNode);
projectionNode.setOutSchema(getProjectedSchema(plan, projectionNode.getTargets()));
projectionNode.setInSchema(child.getOutSchema());
projectionNode.setChild(child);
if (projection.isDistinct() && block.hasGrouping()) {
throw new VerifyException("Cannot support grouping and distinct at the same time");
} else {
if (projection.isDistinct()) {
Schema outSchema = projectionNode.getOutSchema();
GroupbyNode dupRemoval = new GroupbyNode(plan.newPID(), outSchema.toArray());
dupRemoval.setTargets(block.getTargetListManager().getTargets());
dupRemoval.setInSchema(child.getOutSchema());
dupRemoval.setOutSchema(outSchema);
dupRemoval.setChild(child);
projectionNode.setChild(dupRemoval);
}