Source:
protected Scope visitCreateFunction(CreateFunction node, Optional<Scope> scope) { analysis.setUpdateType("CREATE FUNCTION"); checkFunctionName(node, node.getFunctionName()); List<String> duplicateParameters = node.getParameters().stream() .map(SqlParameterDeclaration::getName) .map(Identifier::getValue) .collect(groupingBy(Function.identity(), counting())) .entrySet() .stream() .filter(entry -> entry.getValue() > 1) .map(Entry::getKey) .collect(toImmutableList()); if (!duplicateParameters.isEmpty()) { throw new SemanticException(DUPLICATE_PARAMETER_NAME, node, "Duplicate function parameter name: %s", Joiner.on(", ").join(duplicateParameters)); } Type returnType = metadata.getType(parseTypeSignature(node.getReturnType())); List<Field> fields = node.getParameters().stream() .map(parameter -> Field.newUnqualified(parameter.getName().getValue(), metadata.getType(parseTypeSignature(parameter.getType())))) .collect(toImmutableList()); Scope functionScope = Scope.builder() .withRelationType(RelationId.anonymous(), new RelationType(fields)) .build(); if (node.getBody().getReturnExpression().isPresent()) { Expression returnExpression = node.getBody().getReturnExpression().get(); Type bodyType = analyzeExpression(returnExpression, functionScope).getExpressionTypes().get(NodeRef.of(returnExpression)); if (!bodyType.equals(returnType)) { throw new SemanticException(TYPE_MISMATCH, node, "Function implementation type '%s' does not match declared return type '%s'", bodyType, returnType); } Analyzer.verifyNoAggregateWindowOrGroupingFunctions(analysis.getFunctionHandles(), metadata.getFunctionManager(), returnExpression, "CREATE FUNCTION body"); } return createAndAssignScope(node, scope); }

Target:
protected Scope visitCreateFunction(CreateFunction node, Optional<Scope> scope) { analysis.setUpdateType("CREATE FUNCTION"); checkFunctionName(node, node.getFunctionName()); List<String> duplicateParameters = node.getParameters().stream() .map(SqlParameterDeclaration::getName) .map(Identifier::getValue) .collect(groupingBy(Function.identity(), counting())) .entrySet() .stream() .filter(entry -> entry.getValue() > 1) .map(Entry::getKey) .collect(toImmutableList()); if (!duplicateParameters.isEmpty()) { throw new SemanticException(DUPLICATE_PARAMETER_NAME, node, "Duplicate function parameter name: %s", Joiner.on(", ").join(duplicateParameters)); } Type returnType = metadata.getType(parseTypeSignature(node.getReturnType())); List<Field> fields = node.getParameters().stream() .map(parameter -> Field.newUnqualified(parameter.getName().getValue(), metadata.getType(parseTypeSignature(parameter.getType())))) .collect(toImmutableList()); Scope functionScope = Scope.builder() .withRelationType(RelationId.anonymous(), new RelationType(fields)) .build(); if (node.getBody() instanceof Return) { Expression returnExpression = ((Return) node.getBody()).getExpression(); Type bodyType = analyzeExpression(returnExpression, functionScope).getExpressionTypes().get(NodeRef.of(returnExpression)); if (!bodyType.equals(returnType)) { throw new SemanticException(TYPE_MISMATCH, node, "Function implementation type '%s' does not match declared return type '%s'", bodyType, returnType); } Analyzer.verifyNoAggregateWindowOrGroupingFunctions(analysis.getFunctionHandles(), metadata.getFunctionManager(), returnExpression, "CREATE FUNCTION body"); } return createAndAssignScope(node, scope); }