.addAll(node.getOrderBy()); if (node.getFrame().getStartValue().isPresent()) { expectedInputs.add(node.getFrame().getStartValue().get()); if (node.getFrame().getEndValue().isPresent()) { expectedInputs.add(node.getFrame().getEndValue().get()); node.getOrderBy(), node.getOrderings(), node.getFrame(), functionCalls.build(), functions.build(),
@Override public Void visitWindow(WindowNode node, Void context) { PlanNode source = node.getSource(); source.accept(this, context); // visit child verifyUniqueId(node); Set<Symbol> inputs = ImmutableSet.copyOf(source.getOutputSymbols()); checkDependencies(inputs, node.getPartitionBy(), "Invalid node. Partition by symbols (%s) not in source plan output (%s)", node.getPartitionBy(), node.getSource().getOutputSymbols()); checkDependencies(inputs, node.getOrderBy(), "Invalid node. Order by symbols (%s) not in source plan output (%s)", node.getOrderBy(), node.getSource().getOutputSymbols()); ImmutableList.Builder<Symbol> bounds = ImmutableList.builder(); if (node.getFrame().getStartValue().isPresent()) { bounds.add(node.getFrame().getStartValue().get()); } if (node.getFrame().getEndValue().isPresent()) { bounds.add(node.getFrame().getEndValue().get()); } checkDependencies(inputs, bounds.build(), "Invalid node. Frame bounds (%s) not in source plan output (%s)", bounds.build(), node.getSource().getOutputSymbols()); for (FunctionCall call : node.getWindowFunctions().values()) { Set<Symbol> dependencies = DependencyExtractor.extractUnique(call); checkDependencies(inputs, dependencies, "Invalid node. Window function dependencies (%s) not in source plan output (%s)", dependencies, node.getSource().getOutputSymbols()); } return null; }
@Override public PlanNode visitWindow(WindowNode node, RewriteContext<Context> context) { if (!node.getWindowFunctions().values().stream() .map(FunctionCall::getName) .allMatch(metadata.getFunctionRegistry()::isAggregationFunction)) { return node; } // Don't need this restriction if we can prove that all order by symbols are deterministically produced if (!node.getOrderBy().isEmpty()) { return node; } // Only RANGE frame type currently supported for aggregation functions because it guarantees the // same value for each peer group. // ROWS frame type requires the ordering to be fully deterministic (e.g. deterministically sorted on all columns) if (node.getFrame().getType() != WindowFrame.Type.RANGE) { return node; } // Lookup symbols can only be passed through if they are part of the partitioning Set<Symbol> partitionByLookupSymbols = context.get().getLookupSymbols().stream() .filter(node.getPartitionBy()::contains) .collect(toImmutableSet()); if (partitionByLookupSymbols.isEmpty()) { return node; } return context.defaultRewrite(node, new Context(partitionByLookupSymbols, context.get().getSuccess())); }
WindowNode.Frame frame = node.getFrame(); frame = new WindowNode.Frame(frame.getType(), frame.getStartType(), canonicalize(frame.getStartValue()),
@Override public PlanNode visitWindow(WindowNode node, List<PlanNode> newChildren) { return new WindowNode( node.getId(), Iterables.getOnlyElement(newChildren), node.getPartitionBy(), node.getOrderBy(), node.getOrderings(), node.getFrame(), node.getWindowFunctions(), node.getSignatures(), node.getHashSymbol(), node.getPrePartitionedInputs(), node.getPreSortedOrderPrefix()); }
node.getOrderBy(), node.getOrderings(), node.getFrame(), node.getWindowFunctions(), node.getSignatures(),