Table functions natively support named parameters via SimpleNamedParameterFunction base class.
// Bind function receives named params in input.named_parameters
static unique_ptr<FunctionData> MyTableBind(ClientContext &context, TableFunctionBindInput &input,
vector<LogicalType> &return_types, vector<string> &names) {
auto result = make_uniq<MyBindData>();
result->url = input.inputs[0].GetValue<string>(); // positional arg
// Named parameters
auto headers_entry = input.named_parameters.find("headers");
if (headers_entry != input.named_parameters.end()) {
result->headers = headers_entry->second;
}
return result;
}
// Registration
TableFunction my_func("my_func", {LogicalType::VARCHAR}, MyTableFunction, MyTableBind, MyTableInit);
my_func.named_parameters["headers"] = LogicalType::ANY;
my_func.named_parameters["params"] = LogicalType::ANY;
loader.RegisterFunction(my_func);SQL usage:
SELECT * FROM my_func('https://example.com', headers := {'Accept': 'application/json'});Scalar functions don't natively support named parameters - arguments are passed positionally. However, you can detect := syntax via Expression::alias in a bind function.
// Bind function reorders arguments based on aliases
static unique_ptr<FunctionData> MyScalarBind(ClientContext &context, ScalarFunction &bound_function,
vector<unique_ptr<Expression>> &arguments) {
if (arguments.size() == 3) {
idx_t headers_idx = 1; // expected position
idx_t params_idx = 2; // expected position
// Detect aliases from := syntax
for (idx_t i = 1; i < arguments.size(); i++) {
if (StringUtil::CIEquals(arguments[i]->alias, "headers")) {
headers_idx = i;
} else if (StringUtil::CIEquals(arguments[i]->alias, "params")) {
params_idx = i;
}
}
// Swap if out of order
if (headers_idx == 2 && params_idx == 1) {
std::swap(arguments[1], arguments[2]);
}
}
return nullptr;
}
// Registration - pass bind function as 4th argument
ScalarFunction my_scalar({LogicalType::VARCHAR, LogicalType::ANY, LogicalType::ANY},
return_type, MyScalarFunc, MyScalarBind);
loader.RegisterFunction(my_scalar);SQL usage:
-- Both work identically:
SELECT my_func('url', headers := {...}, params := {...});
SELECT my_func('url', params := {...}, headers := {...});| Feature | TableFunction | ScalarFunction |
|---|---|---|
| Native named params | Yes (named_parameters map) |
No |
| Access method | input.named_parameters |
arguments[i]->alias in bind |
| Reordering needed | No | Yes (manual swap) |