WindowNode.Frame frame = new WindowNode.Frame( frameType, frameStartType,
private static String formatFrame(WindowNode.Frame frame) { StringBuilder builder = new StringBuilder(frame.getType().toString()); frame.getOriginalStartValue().ifPresent(value -> builder.append(" ").append(value)); builder.append(" ").append(frame.getStartType()); frame.getOriginalEndValue().ifPresent(value -> builder.append(" ").append(value)); builder.append(" ").append(frame.getEndType()); return builder.toString(); }
if (frame.getStartValue().isPresent()) { expectedInputs.add(frame.getStartValue().get()); if (frame.getEndValue().isPresent()) { expectedInputs.add(frame.getEndValue().get());
WindowNode.Frame frame = new WindowNode.Frame(frameType, frameStartType, frameStartSymbol, frameEndType, frameEndSymbol);
@Test public void testWindow() throws Exception { PlanNode node = new WindowNode(newId(), filter(baseTableScan, and( equals(AE, BE), equals(BE, CE), lessThan(CE, number(10)))), ImmutableList.of(A), ImmutableList.of(A), ImmutableMap.of(A, SortOrder.ASC_NULLS_LAST), new WindowNode.Frame(WindowFrame.Type.RANGE, FrameBound.Type.UNBOUNDED_PRECEDING, Optional.empty(), FrameBound.Type.CURRENT_ROW, Optional.empty()), ImmutableMap.<Symbol, FunctionCall>of(), ImmutableMap.<Symbol, Signature>of(), Optional.empty(), ImmutableSet.of(), 0); Expression effectivePredicate = EffectivePredicateExtractor.extract(node, TYPES); // Pass through assertEquals(normalizeConjuncts(effectivePredicate), normalizeConjuncts( equals(AE, BE), equals(BE, CE), lessThan(CE, number(10)))); }
.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());
@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())); }
frame = new WindowNode.Frame(frame.getType(), frame.getStartType(), canonicalize(frame.getStartValue()), frame.getEndType(), canonicalize(frame.getEndValue()));
@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; }
new FunctionCall(QualifiedName.of("min"), ImmutableList.of(input1.toSymbolReference())), signature, new WindowNode.Frame( WindowFrame.Type.RANGE, UNBOUNDED_PRECEDING, new FunctionCall(QualifiedName.of("min"), ImmutableList.of(input2.toSymbolReference())), signature, new WindowNode.Frame( WindowFrame.Type.RANGE, UNBOUNDED_PRECEDING,
false); FunctionCall functionCall = new FunctionCall(QualifiedName.of("sum"), ImmutableList.of(columnC.toSymbolReference())); WindowNode.Frame frame = new WindowNode.Frame( WindowFrame.Type.RANGE, FrameBound.Type.UNBOUNDED_PRECEDING,
windowFunction.getFrame().getStartValue().ifPresent(referencedInputs::add); windowFunction.getFrame().getEndValue().ifPresent(referencedInputs::add);
FunctionCall functionCall = new FunctionCall(QualifiedName.of("sum"), ImmutableList.of(columnC.toSymbolReference())); WindowNode.Frame frame = new WindowNode.Frame( WindowFrame.Type.RANGE, FrameBound.Type.UNBOUNDED_PRECEDING,
FunctionCall functionCall = new FunctionCall(QualifiedName.of("sum"), ImmutableList.of(columnA.toSymbolReference())); // should be columnC WindowNode.Frame frame = new WindowNode.Frame( WindowFrame.Type.RANGE, FrameBound.Type.UNBOUNDED_PRECEDING,
FunctionCall functionCall = new FunctionCall(QualifiedName.of("sum"), ImmutableList.of(columnC.toSymbolReference())); WindowNode.Frame frame = new WindowNode.Frame( WindowFrame.Type.RANGE, FrameBound.Type.UNBOUNDED_PRECEDING,
@Override public Void visitWindow(WindowNode node, Set<Symbol> boundSymbols) { PlanNode source = node.getSource(); source.accept(this, boundSymbols); // visit child Set<Symbol> inputs = createInputs(source, boundSymbols); checkDependencies(inputs, node.getPartitionBy(), "Invalid node. Partition by symbols (%s) not in source plan output (%s)", node.getPartitionBy(), node.getSource().getOutputSymbols()); if (node.getOrderingScheme().isPresent()) { checkDependencies( inputs, node.getOrderingScheme().get().getOrderBy(), "Invalid node. Order by symbols (%s) not in source plan output (%s)", node.getOrderingScheme().get().getOrderBy(), node.getSource().getOutputSymbols()); } ImmutableList.Builder<Symbol> bounds = ImmutableList.builder(); for (WindowNode.Frame frame : node.getFrames()) { if (frame.getStartValue().isPresent()) { bounds.add(frame.getStartValue().get()); } if (frame.getEndValue().isPresent()) { bounds.add(frame.getEndValue().get()); } } checkDependencies(inputs, bounds.build(), "Invalid node. Frame bounds (%s) not in source plan output (%s)", bounds.build(), node.getSource().getOutputSymbols()); for (WindowNode.Function function : node.getWindowFunctions().values()) { Set<Symbol> dependencies = SymbolsExtractor.extractUnique(function.getFunctionCall()); checkDependencies(inputs, dependencies, "Invalid node. Window function dependencies (%s) not in source plan output (%s)", dependencies, node.getSource().getOutputSymbols()); } return null; }
public TestSwapAdjacentWindowsBySpecifications() { frame = new WindowNode.Frame( WindowFrame.Type.RANGE, UNBOUNDED_PRECEDING, Optional.empty(), CURRENT_ROW, Optional.empty(), Optional.empty(), Optional.empty()); signature = new Signature( "avg", FunctionKind.WINDOW, ImmutableList.of(), ImmutableList.of(), DOUBLE.getTypeSignature(), ImmutableList.of(BIGINT.getTypeSignature()), false); }
@Override public WindowNode.Frame getExpectedValue(SymbolAliases aliases) { // synthetize original start/end value to keep the constructor of the frame happy. These are irrelevant for the purpose // of testing the plan structure. Optional<Expression> originalStartValue = startValue.map(alias -> alias.toSymbol(aliases).toSymbolReference()); Optional<Expression> originalEndValue = endValue.map(alias -> alias.toSymbol(aliases).toSymbolReference()); return new WindowNode.Frame( type, startType, startValue.map(alias -> alias.toSymbol(aliases)), endType, endValue.map(alias -> alias.toSymbol(aliases)), originalStartValue, originalEndValue); }
private WindowNode.Frame canonicalize(WindowNode.Frame frame) { return new WindowNode.Frame( frame.getType(), frame.getStartType(), canonicalize(frame.getStartValue()), frame.getEndType(), canonicalize(frame.getEndValue()), frame.getOriginalStartValue(), frame.getOriginalEndValue()); }