Skip to main content
Requires feature = "udf". See the UDF overview for shared semantics.
#[duckdb_aggregate] is applied to an inline mod { … } (not mod name;) defining four free functions. It generates a VAggregate impl plus a register(&mut Connection).
Register with int_sum::register(&mut conn)?, then SELECT int_sum(x) FROM t.

The four functions

The fresh per-group accumulator. State is inferred from this return type.
Fold one row into state. The value parameter types are inferred from the arguments after the leading &mut state (so DuckDB’s argument types come from here). May return Result<(), E> to fail the query.
Merge partial states — DuckDB uses this for parallel/partial aggregation.
Produce the result; the return type T (or Result<T, E>) is the function’s result type.
All four must be present. init and finalize must return a value; update must take &mut state as its first argument. A missing function, or mod name; instead of an inline module, is a compile error.

Options

The VAggregate trait

The macro implements better_duck_core::udf::VAggregate:
Register with conn.register_aggregate_function::<A>(name) or register_aggregate_function_with_state::<A>(name, shared). To group several overloads of different Rust types under one SQL name (DuckDB dispatches on argument types), use conn.register_aggregate_function_set(name, |b| { b.add::<A>()?; b.add::<B>()?; Ok(()) }) — the closure receives an AggregateSetBuilder with add::<A>() / add_with_state::<A>(shared).

See also