@Override public String visitWindow(Window node, Void context) { List<String> parts = new ArrayList<>(); if (!node.getPartitionBy().isEmpty()) { parts.add("PARTITION BY " + joinExpressions(node.getPartitionBy())); } if (!node.getOrderBy().isEmpty()) { parts.add("ORDER BY " + formatSortItems(node.getOrderBy())); } if (node.getFrame().isPresent()) { parts.add(process(node.getFrame().get(), null)); } return '(' + Joiner.on(' ').join(parts) + ')'; }
@Override public String visitWindow(Window node, Void context) { List<String> parts = new ArrayList<>(); if (!node.getPartitionBy().isEmpty()) { parts.add("PARTITION BY " + joinExpressions(node.getPartitionBy())); } if (!node.getOrderBy().isEmpty()) { parts.add("ORDER BY " + formatSortItems(node.getOrderBy())); } if (node.getFrame().isPresent()) { parts.add(process(node.getFrame().get(), null)); } else { if (!windowFunctionName.equalsIgnoreCase("rank")) { if (!node.getOrderBy().isEmpty()) { // Redshift needs to specify frame explicitly if there is order by and the function is not rank() FrameBound fb = new FrameBound(FrameBound.Type.UNBOUNDED_PRECEDING); WindowFrame wf = new WindowFrame(WindowFrame.Type.ROWS, fb, null); parts.add(process(wf, null)); } } } return '(' + Joiner.on(' ').join(parts) + ')'; }
@Override public String visitWindow(Window node, StackableAstVisitorContext<Integer> indent) { List<String> parts = new ArrayList<>(); if (!node.getPartitionBy().isEmpty()) { parts.add("PARTITION BY " + joinExpressions(node.getPartitionBy(), indent)); } if (node.getOrderBy().isPresent()) { parts.add("ORDER BY " + formatSortItems(node.getOrderBy().get().getSortItems(), parameters, indent.getContext())); } if (node.getFrame().isPresent()) { parts.add(process(node.getFrame().get(), indent)); } return '(' + Joiner.on(' ').join(parts) + ')'; }
@Override public String visitWindow(Window node, Boolean unmangleNames) { List<String> parts = new ArrayList<>(); if (!node.getPartitionBy().isEmpty()) { parts.add("PARTITION BY " + joinExpressions(node.getPartitionBy(), unmangleNames)); } if (!node.getOrderBy().isEmpty()) { parts.add("ORDER BY " + formatSortItems(node.getOrderBy(), unmangleNames)); } if (node.getFrame().isPresent()) { parts.add(process(node.getFrame().get(), unmangleNames)); } return '(' + Joiner.on(' ').join(parts) + ')'; }
@Override public Node visitOver(SqlBaseParser.OverContext context) { return new Window( getLocation(context), visit(context.partition, Expression.class), visit(context.sortItem(), SortItem.class), visitIfPresent(context.windowFrame(), WindowFrame.class)); }
private static Expression getHashFunctionCall(Expression previousHashValue, Symbol symbol) { FunctionCall functionCall = new FunctionCall(QualifiedName.of(HASH_CODE), Optional.<Window>empty(), false, ImmutableList.<Expression>of(new QualifiedNameReference(symbol.toQualifiedName()))); List<Expression> arguments = ImmutableList.of(previousHashValue, orNullHashCode(functionCall)); return new FunctionCall(QualifiedName.of("combine_hash"), arguments); }
private void analyzeWindowFunctions(QuerySpecification node, List<FieldOrExpression> outputExpressions, List<FieldOrExpression> orderByExpressions) { WindowFunctionExtractor extractor = new WindowFunctionExtractor(); for (FieldOrExpression fieldOrExpression : Iterables.concat(outputExpressions, orderByExpressions)) { if (fieldOrExpression.isExpression()) { extractor.process(fieldOrExpression.getExpression(), null); new WindowFunctionValidator().process(fieldOrExpression.getExpression(), analysis); } } List<FunctionCall> windowFunctions = extractor.getWindowFunctions(); for (FunctionCall windowFunction : windowFunctions) { Window window = windowFunction.getWindow().get(); WindowFunctionExtractor nestedExtractor = new WindowFunctionExtractor(); for (Expression argument : windowFunction.getArguments()) { nestedExtractor.process(argument, null); } for (Expression expression : window.getPartitionBy()) { nestedExtractor.process(expression, null); } for (SortItem sortItem : window.getOrderBy()) { nestedExtractor.process(sortItem.getSortKey(), null); } if (window.getFrame().isPresent()) { nestedExtractor.process(window.getFrame().get(), null); } if (!nestedExtractor.getWindowFunctions().isEmpty()) { throw new SemanticException(NESTED_WINDOW, node, "Cannot nest window functions inside window function '%s': %s", windowFunction, extractor.getWindowFunctions()); } if (windowFunction.isDistinct()) { throw new SemanticException(NOT_SUPPORTED, node, "DISTINCT in window function parameters not yet supported: %s", windowFunction); } if (window.getFrame().isPresent()) { analyzeWindowFrame(window.getFrame().get()); } List<TypeSignature> argumentTypes = Lists.transform(windowFunction.getArguments(), expression -> analysis.getType(expression).getTypeSignature()); FunctionKind kind = metadata.getFunctionRegistry().resolveFunction(windowFunction.getName(), argumentTypes, false).getKind(); if (kind != AGGREGATE && kind != APPROXIMATE_AGGREGATE && kind != WINDOW) { throw new SemanticException(MUST_BE_WINDOW_FUNCTION, node, "Not a window function: %s", windowFunction.getName()); } } analysis.setWindowFunctions(node, windowFunctions); }