| 584 | } |
| 585 | |
| 586 | void FunctionBinder::ResolveTemplateTypes(BaseScalarFunction &bound_function, |
| 587 | const vector<unique_ptr<Expression>> &children) { |
| 588 | case_insensitive_map_t<vector<LogicalType>> bindings; |
| 589 | vector<reference<LogicalType>> to_substitute; |
| 590 | |
| 591 | // First, we need to infer the template types from the children. |
| 592 | for (idx_t i = 0; i < bound_function.arguments.size(); i++) { |
| 593 | auto ¶m = bound_function.arguments[i]; |
| 594 | |
| 595 | // If the parameter is not templated, we can skip it. |
| 596 | if (param.IsTemplated()) { |
| 597 | auto actual = ExpressionBinder::GetExpressionReturnType(*children[i]); |
| 598 | InferTemplateType(context, param, actual, bindings, *children[i], bound_function); |
| 599 | |
| 600 | to_substitute.emplace_back(param); |
| 601 | } |
| 602 | } |
| 603 | |
| 604 | // If the function has a templated varargs, we need to infer its type too |
| 605 | if (bound_function.varargs.IsTemplated()) { |
| 606 | // All remaining children are considered varargs. |
| 607 | for (idx_t i = bound_function.arguments.size(); i < children.size(); i++) { |
| 608 | auto actual = ExpressionBinder::GetExpressionReturnType(*children[i]); |
| 609 | InferTemplateType(context, bound_function.varargs, actual, bindings, *children[i], bound_function); |
| 610 | } |
| 611 | to_substitute.emplace_back(bound_function.varargs); |
| 612 | } |
| 613 | |
| 614 | // If the return type is templated, we need to subsitute it as well |
| 615 | if (bound_function.GetReturnType().IsTemplated()) { |
| 616 | to_substitute.emplace_back(bound_function.GetReturnType()); |
| 617 | } |
| 618 | |
| 619 | // Finally, substitute all template types in the bound function with their concrete types. |
| 620 | for (auto &templated_type : to_substitute) { |
| 621 | SubstituteTemplateType(templated_type, bindings, bound_function.name); |
| 622 | } |
| 623 | } |
| 624 | |
| 625 | static void VerifyTemplateType(const LogicalType &type, const string &function_name) { |
| 626 | TypeVisitor::Contains(type, [&](const LogicalType &type) { |
no test coverage detected