Requires
feature = "udf". See the UDF overview for shared semantics.#[duckdb_table_function] turns a Rust function into a DuckDB table function — used in a FROM
clause. It returns impl Iterator<Item = T> + Send: T for one column, or a tuple (A, B, …) for
several. DuckDB pulls rows in chunks, so the iterator is driven lazily and may be scanned across
several calls.
Options
schema = "…" is intentionally rejected — DuckDB’s C API cannot register a function into a
schema. Register it, then move it with SQL.Named parameters
A parameter listed innamed_params is bound as name := … in SQL. A non-Option named parameter
is required; an Option<T> one is optional:
Projection pushdown and extra info — body macros
Inside the body:duck_projection!() -> Vec<usize>— the 0-based column indices the current query needs (empty if no pushdown was requested; only meaningful underprojection_pushdown).duck_extra_info!(Type) -> Type— aCloneof the registered extra-info value.
The VTab trait
The macro implements better_duck_core::udf::VTab. Implement it by hand for stateful scans:
VTab (and VTabLocalInit) by hand
VTab (and VTabLocalInit) by hand
bind defines the output schema via BindInfo::add_result_column and may set_cardinality;
init produces per-query state and may set_max_threads and read column_indices (projection);
func writes up to output.capacity() rows then calls output.set_len(k), signalling
completion with set_len(0). Register with conn.register_table_function::<T>(name),
register_table_function_ext::<T>(name) (adds a per-worker VTabLocalInit::local_init), or
register_table_function_with_extra_info::<T, E>(name, extra).See also
- UDF overview — shared semantics and the panic caveat.
- Scalar functions · Aggregate functions.
- Data chunks / vectors — writing output in a hand-written
func.