Source:
protected Object visitFunctionCall(FunctionCall node, Object context) { List<Type> argumentTypes = new ArrayList<>(); List<Object> argumentValues = new ArrayList<>(); for (Expression expression : node.getArguments()) { Object value = process(expression, context); Type type = type(expression); argumentValues.add(value); argumentTypes.add(type); } FunctionHandle functionHandle = metadata.getFunctionManager().resolveFunction(session, node.getName(), fromTypes(argumentTypes)); FunctionMetadata functionMetadata = metadata.getFunctionManager().getFunctionMetadata(functionHandle); if (!functionMetadata.isCalledOnNullInput()) { for (int i = 0; i < argumentValues.size(); i++) { Object value = argumentValues.get(i); if (value == null) { return null; } } } if (optimize && (!functionMetadata.isDeterministic() || hasUnresolvedValue(argumentValues) || node.getName().equals(QualifiedName.of("fail")))) { return new FunctionCall(node.getName(), node.getWindow(), node.isDistinct(), toExpressions(argumentValues, argumentTypes)); } Object result = functionInvoker.invoke(functionHandle, connectorSession, argumentValues); if (optimize && !isSerializable(result, type(node))) { return new FunctionCall(node.getName(), node.getWindow(), node.isDistinct(), toExpressions(argumentValues, argumentTypes)); } return result; }

Target:
protected Object visitFunctionCall(FunctionCall node, Object context) { List<Type> argumentTypes = new ArrayList<>(); List<Object> argumentValues = new ArrayList<>(); for (Expression expression : node.getArguments()) { Object value = process(expression, context); Type type = type(expression); argumentValues.add(value); argumentTypes.add(type); } FunctionHandle functionHandle = metadata.getFunctionManager().resolveFunction(session.getTransactionId(), node.getName(), fromTypes(argumentTypes)); FunctionMetadata functionMetadata = metadata.getFunctionManager().getFunctionMetadata(functionHandle); if (!functionMetadata.isCalledOnNullInput()) { for (int i = 0; i < argumentValues.size(); i++) { Object value = argumentValues.get(i); if (value == null) { return null; } } } if (optimize && (!functionMetadata.isDeterministic() || hasUnresolvedValue(argumentValues) || node.getName().equals(QualifiedName.of("fail")))) { return new FunctionCall(node.getName(), node.getWindow(), node.isDistinct(), toExpressions(argumentValues, argumentTypes)); } Object result; switch (functionMetadata.getImplementationType()) { case BUILTIN: result = functionInvoker.invoke(functionHandle, connectorSession, argumentValues); break; case SQL: Expression function = getSqlFunctionExpression(functionMetadata, (SqlInvokedScalarFunctionImplementation) metadata.getFunctionManager().getScalarFunctionImplementation(functionHandle), session.getSqlFunctionProperties(), node.getArguments()); ExpressionInterpreter functionInterpreter = new ExpressionInterpreter( function, metadata, session, getExpressionTypes(session, metadata, new SqlParser(), TypeProvider.empty(), function, emptyList(), WarningCollector.NOOP), optimize); result = functionInterpreter.visitor.process(function, context); break; default: throw new IllegalArgumentException(format("Unsupported function implementation type: %s", functionMetadata.getImplementationType())); } if (optimize && !isSerializable(result, type(node))) { return new FunctionCall(node.getName(), node.getWindow(), node.isDistinct(), toExpressions(argumentValues, argumentTypes)); } return result; }