@Override protected String visitFunctionCall(FunctionCall node, Boolean unmangleNames) { StringBuilder builder = new StringBuilder(); String arguments = joinExpressions(node.getArguments(), unmangleNames); if (node.getArguments().isEmpty() && "count".equalsIgnoreCase(node.getName().getSuffix())) { arguments = "*"; } if (node.isDistinct()) { arguments = "DISTINCT " + arguments; } if (unmangleNames && node.getName().toString().startsWith(QueryUtil.FIELD_REFERENCE_PREFIX)) { checkState( node.getArguments().size() == 1, "Expected only one argument to field reference"); QualifiedName name = QualifiedName.of(QueryUtil.unmangleFieldReference(node.getName().toString())); builder.append(arguments).append(".").append(name); } else { builder .append(formatQualifiedName(node.getName())) .append('(') .append(arguments) .append(')'); } if (node.getWindow().isPresent()) { builder.append(" OVER ").append(visitWindow(node.getWindow().get(), unmangleNames)); } return builder.toString(); }
@Override protected Type visitFunctionCall(FunctionCall node, AnalysisContext context) { if (node.getWindow().isPresent()) { for (Expression expression : node.getWindow().get().getPartitionBy()) { process(expression, context); Type type = expressionTypes.get(expression); if (!type.isComparable()) { throw new SemanticException( TYPE_MISMATCH, node, "%s is not comparable, and therefore cannot be used in window function PARTITION BY", type); } } for (SortItem sortItem : node.getWindow().get().getOrderBy()) { process(sortItem.getSortKey(), context); Type type = expressionTypes.get(sortItem.getSortKey()); if (!type.isOrderable()) { throw new SemanticException( TYPE_MISMATCH, node, "%s is not orderable, and therefore cannot be used in window function ORDER BY", type); } } if (node.getWindow().get().getFrame().isPresent()) { WindowFrame frame = node.getWindow().get().getFrame().get(); if (frame.getStart().getValue().isPresent()) { Type type = process(frame.getStart().getValue().get(), context); if (!type.equals(BIGINT)) { throw new SemanticException( TYPE_MISMATCH, node, "Window frame start value type must be BIGINT (actual %s)", type); } } if (frame.getEnd().isPresent() && frame.getEnd().get().getValue().isPresent()) { Type type = process(frame.getEnd().get().getValue().get(), context); if (!type.equals(BIGINT)) { throw new SemanticException( TYPE_MISMATCH, node, "Window frame end value type must be BIGINT (actual %s)", type); } } } } ImmutableList.Builder<TypeSignature> argumentTypes = ImmutableList.builder(); for (Expression expression : node.getArguments()) { argumentTypes.add(process(expression, context).getTypeSignature()); } Signature function = functionRegistry.resolveFunction( node.getName(), argumentTypes.build(), context.isApproximate()); for (int i = 0; i < node.getArguments().size(); i++) { Expression expression = node.getArguments().get(i); Type type = typeManager.getType(function.getArgumentTypes().get(i)); requireNonNull(type, format("Type %s not found", function.getArgumentTypes().get(i))); if (node.isDistinct() && !type.isComparable()) { throw new SemanticException( TYPE_MISMATCH, node, "DISTINCT can only be applied to comparable types (actual: %s)", type); } coerceType( context, expression, type, String.format("Function %s argument %d", function, i)); } resolvedFunctions.put(node, function); Type type = typeManager.getType(function.getReturnType()); expressionTypes.put(node, type); return type; }