private static boolean noFilters(AggregationNode aggregation) { return aggregation.getAggregations() .values().stream() .map(Aggregation::getCall) .noneMatch(call -> call.getFilter().isPresent()); }
private static boolean hasFilters(AggregationNode aggregation) { return aggregation.getAggregations() .values().stream() .anyMatch(e -> e.getCall().getFilter().isPresent() && !e.getMask().isPresent()); // can't handle filtered aggregations with DISTINCT (conservatively, if they have a mask) }
@Override public void validate(PlanNode plan, Session session, Metadata metadata, SqlParser sqlParser, TypeProvider types, WarningCollector warningCollector) { searchFrom(plan) .where(AggregationNode.class::isInstance) .<AggregationNode>findAll() .stream() .flatMap(node -> node.getAggregations().values().stream()) .filter(aggregation -> aggregation.getCall().getFilter().isPresent()) .forEach(ignored -> { throw new IllegalStateException("Generated plan contains unimplemented filtered aggregations"); }); } }
private static boolean hasNoDistinctWithFilterOrMask(AggregationNode aggregation) { return aggregation.getAggregations() .values().stream() .noneMatch(e -> e.getCall().isDistinct() && (e.getCall().getFilter().isPresent() || e.getMask().isPresent())); }
private static Predicate<FunctionCall> isAggregationPredicate(FunctionRegistry functionRegistry) { return ((functionCall) -> (functionRegistry.isAggregationFunction(functionCall.getName()) || functionCall.getFilter().isPresent()) && !functionCall.getWindow().isPresent() || functionCall.getOrderBy().isPresent()); }
@Override protected R visitFunctionCall(FunctionCall node, C context) { for (Expression argument : node.getArguments()) { process(argument, context); } if (node.getOrderBy().isPresent()) { process(node.getOrderBy().get(), context); } if (node.getWindow().isPresent()) { process(node.getWindow().get(), context); } if (node.getFilter().isPresent()) { process(node.getFilter().get(), context); } return null; }
@Override protected String visitFunctionCall(FunctionCall node, Void context) { StringBuilder builder = new StringBuilder(); String arguments = joinExpressions(node.getArguments()); if (node.getArguments().isEmpty() && "count".equalsIgnoreCase(node.getName().getSuffix())) { arguments = "*"; } if (node.isDistinct()) { arguments = "DISTINCT " + arguments; } builder.append(formatQualifiedName(node.getName())) .append('(').append(arguments); if (node.getOrderBy().isPresent()) { builder.append(' ').append(formatOrderBy(node.getOrderBy().get(), parameters)); } builder.append(')'); if (node.getFilter().isPresent()) { builder.append(" FILTER ").append(visitFilter(node.getFilter().get(), context)); } if (node.getWindow().isPresent()) { builder.append(" OVER ").append(visitWindow(node.getWindow().get(), context)); } return builder.toString(); }
if (node.getFilter().isPresent()) { throw new SemanticException(MUST_BE_AGGREGATION_FUNCTION, node,
if (windowFunction.getFilter().isPresent()) { throw new SemanticException(NOT_SUPPORTED, node, "FILTER is not yet supported for window functions");
private static AggregationNode.Aggregation removeDistinct(AggregationNode.Aggregation aggregation) { checkArgument(aggregation.getCall().isDistinct(), "Expected aggregation to have DISTINCT input"); FunctionCall call = aggregation.getCall(); return new AggregationNode.Aggregation( new FunctionCall( call.getName(), call.getWindow(), call.getFilter(), call.getOrderBy(), false, call.getArguments()), aggregation.getSignature(), aggregation.getMask()); } }
aggregation.getCall().isDistinct(), aggregation.getCall().getArguments(), aggregation.getCall().getFilter());
@Override protected Boolean visitFunctionCall(FunctionCall actual, Node expected) { if (!(expected instanceof FunctionCall)) { return false; } FunctionCall expectedFunction = (FunctionCall) expected; if (actual.isDistinct() != expectedFunction.isDistinct()) { return false; } if (!actual.getName().equals(expectedFunction.getName())) { return false; } if (!process(actual.getArguments(), expectedFunction.getArguments())) { return false; } if (!process(actual.getFilter(), expectedFunction.getFilter())) { return false; } if (!process(actual.getWindow(), expectedFunction.getWindow())) { return false; } return true; }
@Override protected String visitFunctionCall(FunctionCall node, Void context) { StringBuilder builder = new StringBuilder(); String arguments = joinExpressions(node.getArguments()); if (node.getArguments().isEmpty() && "count".equalsIgnoreCase(node.getName().getSuffix())) { arguments = "*"; } if (node.isDistinct()) { arguments = "DISTINCT " + arguments; } String name; if (node.getName().getParts().size() > 1) { name = formatQualifiedName(node.getName(), escape); } else { // for Mysql - > SELECT `count`(1) doesn't work name = node.getName().getSuffix(); } builder.append(name).append('(').append(arguments).append(')'); if (node.getFilter().isPresent()) { builder.append(" FILTER ").append(visitFilter(node.getFilter().get(), context)); } if (node.getWindow().isPresent()) { builder.append(" OVER ").append(visitWindow(node.getWindow().get(), context)); } return builder.toString(); }
@Override protected R visitFunctionCall(FunctionCall node, C context) { for (Expression argument : node.getArguments()) { process(argument, context); } if (node.getOrderBy().isPresent()) { process(node.getOrderBy().get(), context); } if (node.getWindow().isPresent()) { process(node.getWindow().get(), context); } if (node.getFilter().isPresent()) { process(node.getFilter().get(), context); } return null; }
@Override protected String visitFunctionCall(FunctionCall node, Void context) { StringBuilder builder = new StringBuilder(); String arguments = joinExpressions(node.getArguments()); if (node.getArguments().isEmpty() && "count".equalsIgnoreCase(node.getName().getSuffix())) { arguments = "*"; } if (node.isDistinct()) { arguments = "DISTINCT " + arguments; } builder.append(formatQualifiedName(node.getName())) .append('(').append(arguments); if (node.getOrderBy().isPresent()) { builder.append(' ').append(formatOrderBy(node.getOrderBy().get(), parameters)); } builder.append(')'); if (node.getFilter().isPresent()) { builder.append(" FILTER ").append(visitFilter(node.getFilter().get(), context)); } if (node.getWindow().isPresent()) { builder.append(" OVER ").append(visitWindow(node.getWindow().get(), context)); } return builder.toString(); }