public Boolean visitGroupingOperation(GroupingOperation node, Void context) { // ensure that no output fields are referenced from ORDER BY clause if (orderByScope.isPresent()) { node.getGroupingColumns().forEach(groupingColumn -> verifyNoOrderByReferencesToOutputColumns( groupingColumn, REFERENCE_TO_OUTPUT_ATTRIBUTE_WITHIN_ORDER_BY_GROUPING, "Invalid reference to output of SELECT clause from grouping() expression in ORDER BY")); } Optional<Expression> argumentNotInGroupBy = node.getGroupingColumns().stream() .filter(argument -> !columnReferences.containsKey(NodeRef.of(argument)) || !isGroupingKey(argument)) .findAny(); if (argumentNotInGroupBy.isPresent()) { throw new SemanticException( INVALID_PROCEDURE_ARGUMENTS, node, "The arguments to GROUPING() must be expressions referenced by the GROUP BY at the associated query level. Mismatch due to %s.", argumentNotInGroupBy.get()); } return true; }
@Override public Boolean visitWindow(Window node, Void context) { for (Expression expression : node.getPartitionBy()) { if (!process(expression, context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, expression, "PARTITION BY expression '%s' must be an aggregate expression or appear in GROUP BY clause", expression); } } for (SortItem sortItem : node.getOrderBy()) { Expression expression = sortItem.getSortKey(); if (!process(expression, context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, expression, "ORDER BY expression '%s' must be an aggregate expression or appear in GROUP BY clause", expression); } } if (node.getFrame().isPresent()) { process(node.getFrame().get(), context); } return true; }
@Override public Boolean visitWindowFrame(WindowFrame node, Void context) { Optional<Expression> start = node.getStart().getValue(); if (start.isPresent()) { if (!process(start.get(), context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, start.get(), "Window frame start must be an aggregate expression or appear in GROUP BY clause"); } } if (node.getEnd().isPresent() && node.getEnd().get().getValue().isPresent()) { Expression endValue = node.getEnd().get().getValue().get(); if (!process(endValue, context)) { throw new SemanticException(MUST_BE_AGGREGATE_OR_GROUP_BY, endValue, "Window frame end must be an aggregate expression or appear in GROUP BY clause"); } } return true; }
@Override protected Boolean visitSimpleCaseExpression(SimpleCaseExpression node, Void context) { if (!process(node.getOperand(), context)) { return false; } for (WhenClause whenClause : node.getWhenClauses()) { if (!process(whenClause.getOperand(), context) || !process(whenClause.getResult(), context)) { return false; } } if (node.getDefaultValue().isPresent() && !process(node.getDefaultValue().get(), context)) { return false; } return true; }
@Override protected Boolean visitIfExpression(IfExpression node, Void context) { ImmutableList.Builder<Expression> expressions = ImmutableList.<Expression>builder() .add(node.getCondition()) .add(node.getTrueValue()); if (node.getFalseValue().isPresent()) { expressions.add(node.getFalseValue().get()); } return expressions.build().stream().allMatch(expression -> process(expression, context)); }
@Override protected Boolean visitArithmeticUnary(ArithmeticUnaryExpression node, Void context) { return process(node.getValue(), context); }
@Override protected Boolean visitExtract(Extract node, Void context) { return process(node.getExpression(), context); }
@Override protected Boolean visitCoalesceExpression(CoalesceExpression node, Void context) { return node.getOperands().stream().allMatch(expression -> process(expression, context)); }
@Override protected Boolean visitCast(Cast node, Void context) { return process(node.getExpression(), context); }
@Override protected Boolean visitTryExpression(TryExpression node, Void context) { return process(node.getInnerExpression(), context); }
@Override protected Boolean visitNotExpression(NotExpression node, Void context) { return process(node.getValue(), context); }
@Override protected Boolean visitArrayConstructor(ArrayConstructor node, Void context) { return node.getValues().stream().allMatch(expression -> process(expression, context)); }
@Override protected Boolean visitIsNotNullPredicate(IsNotNullPredicate node, Void context) { return process(node.getValue(), context); }