/** * Return plan tree that augments 'root' with plan nodes that implement single-node evaluation of * the AnalyticExprs in analyticInfo. This plan takes into account a possible hash partition of * its input on 'groupingExprs'; if this is non-null, it returns in 'inputPartitionExprs' a subset * of the grouping exprs which should be used for the aggregate hash partitioning during the * parallelization of 'root'. TODO: when generating sort orders for the sort groups, optimize the * ordering of the partition exprs (so that subsequent sort operations see the input sorted on a * prefix of their required sort exprs) TODO: when merging sort groups, recognize equivalent exprs * (using the equivalence classes) rather than looking for expr equality */ public PlanNode createSingleNodePlan( PlanNode root, List<Expr> groupingExprs, List<Expr> inputPartitionExprs) throws ImpalaException { List<WindowGroup> windowGroups = collectWindowGroups(); for (int i = 0; i < windowGroups.size(); ++i) { windowGroups.get(i).init(analyzer_, "wg-" + i); } List<SortGroup> sortGroups = collectSortGroups(windowGroups); mergeSortGroups(sortGroups); for (SortGroup g : sortGroups) { g.init(); } List<PartitionGroup> partitionGroups = collectPartitionGroups(sortGroups); mergePartitionGroups(partitionGroups, root.getNumNodes()); orderGroups(partitionGroups); if (groupingExprs != null) { Preconditions.checkNotNull(inputPartitionExprs); computeInputPartitionExprs( partitionGroups, groupingExprs, root.getNumNodes(), inputPartitionExprs); } for (PartitionGroup partitionGroup : partitionGroups) { for (int i = 0; i < partitionGroup.sortGroups.size(); ++i) { root = createSortGroupPlan( root, partitionGroup.sortGroups.get(i), i == 0 ? partitionGroup.partitionByExprs : null); } } // create equiv classes for newly added slots analyzer_.createIdentityEquivClasses(); return root; }