}
private AbstractPlanNode getNextSelectPlan() {
assert (subAssembler != null);
AbstractPlanNode subSelectRoot = subAssembler.nextPlan();
if (subSelectRoot == null)
return null;
AbstractPlanNode root = subSelectRoot;
/*
* Establish the output columns for the sub select plan.
* The order, aggregation and expression operations placed
* "on top" of this work should calculate correct output
* column state as nodes are added. (That is,
* the recursive updateOutputColumns() ideally wouldn't
* have other callers.)
*/
root.updateOutputColumns(m_catalogDb);
// PAVLO: Ok so now before this just assumed that we were going to stick a AggregatePlanNode on top
// of the root that we sent it (which should be a AbstractScanPlanNode or a ReceievePlanNode).
// But now because we are trying to impress John Hugg (and who isn't really?), we may actually perform
// part of the aggregation at the remote partitions, so we need a buttom up approach for cleaning
// up the PlanColumns...
root = handleAggregationOperators(root);
// if (PlanNodeUtil.getPlanNodes(root, ReceivePlanNode.class).isEmpty() == false) {
// LOG.debug("PAVLO OPTIMIZATION:\n" + PlanNodeUtil.debug(root));
// }
root.updateOutputColumns(m_catalogDb);
if ((subSelectRoot.getPlanNodeType() != PlanNodeType.INDEXSCAN ||
((IndexScanPlanNode) subSelectRoot).getSortDirection() == SortDirectionType.INVALID) &&
m_parsedSelect.orderColumns.size() > 0) {
root = addOrderBy(root);
}
if ((root.getPlanNodeType() != PlanNodeType.AGGREGATE) &&
(root.getPlanNodeType() != PlanNodeType.HASHAGGREGATE) &&
(root.getPlanNodeType() != PlanNodeType.DISTINCT) &&
(root.getPlanNodeType() != PlanNodeType.PROJECTION)) {
root = addProjection(root);
}
if ((m_parsedSelect.limit != -1) || (m_parsedSelect.limitParameterId != -1) ||
(m_parsedSelect.offset > 0) || (m_parsedSelect.offsetParameterId != -1))
{
LimitPlanNode limit = new LimitPlanNode(m_context, getNextPlanNodeId());
limit.setLimit((int) m_parsedSelect.limit);
limit.setOffset((int) m_parsedSelect.offset);
if (m_parsedSelect.offsetParameterId != -1) {
ParameterInfo parameterInfo =
m_parsedSelect.paramsById.get(m_parsedSelect.offsetParameterId);
limit.setOffsetParameterIndex(parameterInfo.index);
}
if (m_parsedSelect.limitParameterId != -1) {
ParameterInfo parameterInfo =
m_parsedSelect.paramsById.get(m_parsedSelect.limitParameterId);
limit.setLimitParameterIndex(parameterInfo.index);
}
limit.addAndLinkChild(root);
limit.setOutputColumns(root.getOutputColumnGUIDs());
root = limit;
}
// System.out.println(PlanNodeUtil.debug(root));
// System.out.println();
// System.out.println();
// System.err.println(m_parsedSelect.sql);
PlanOptimizer po = new PlanOptimizer(m_context, m_catalogDb);
AbstractPlanNode new_root = po.optimize(m_parsedSelect.sql, root);
// if (root.getPlanNodeType().equals(PlanNodeType.PROJECTION) && PlanNodeUtil.getDepth(root) == 0) {
// System.out.println("Root node type: " + root.getPlanNodeType());
// System.out.println("Depth: " + PlanNodeUtil.getDepth(root));
// System.out.println(PlanNodeUtil.debug(root));
// System.out.println();
// System.out.println();
// }
SendPlanNode sendNode = new SendPlanNode(m_context, getNextPlanNodeId());
// check if there is a new root + connect the nodes to build the graph
if (new_root != null) {
sendNode.addAndLinkChild(new_root);
sendNode.setOutputColumns(new_root.getOutputColumnGUIDs());
} else {
sendNode.addAndLinkChild(root);
sendNode.setOutputColumns(root.getOutputColumnGUIDs());
}