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(); }
@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()));
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()); }