pub struct AggregateFunctionBuilder { /* private fields */ }Expand description
Builder for registering a single-signature DuckDB aggregate function.
§Pitfall L6
Unlike duckdb_register_aggregate_function, this builder also handles
the case where you later want to convert to a function set — it sets the
function name correctly.
§Example
use quack_rs::aggregate::AggregateFunctionBuilder;
use quack_rs::types::TypeId;
use libduckdb_sys::{duckdb_connection, duckdb_function_info, duckdb_aggregate_state,
duckdb_data_chunk, duckdb_vector, idx_t};
unsafe extern "C" fn state_size(_: duckdb_function_info) -> idx_t { 8 }
unsafe extern "C" fn state_init(_: duckdb_function_info, _: duckdb_aggregate_state) {}
unsafe extern "C" fn update(_: duckdb_function_info, _: duckdb_data_chunk, _: duckdb_aggregate_state) {}
unsafe extern "C" fn combine(_: duckdb_function_info, _: duckdb_aggregate_state, _: duckdb_aggregate_state, _: idx_t) {}
unsafe extern "C" fn finalize(_: duckdb_function_info, _: duckdb_aggregate_state, _: duckdb_vector, _: idx_t, _: idx_t) {}
// fn register(con: duckdb_connection) -> Result<(), quack_rs::error::ExtensionError> {
// AggregateFunctionBuilder::new("word_count")
// .param(TypeId::Varchar)
// .returns(TypeId::BigInt)
// .state_size(state_size)
// .init(state_init)
// .update(update)
// .combine(combine)
// .finalize(finalize)
// .register(con)
// }Implementations§
Source§impl AggregateFunctionBuilder
impl AggregateFunctionBuilder
Sourcepub fn new(name: &str) -> Self
pub fn new(name: &str) -> Self
Creates a new builder for an aggregate function with the given name.
§Panics
Panics if name contains an interior null byte.
Sourcepub fn try_new(name: &str) -> Result<Self, ExtensionError>
pub fn try_new(name: &str) -> Result<Self, ExtensionError>
Creates a new builder with function name validation.
Unlike new, this method validates the function name against
DuckDB naming conventions and returns an error instead of panicking.
§Errors
Returns ExtensionError if the name is empty, too long, contains invalid
characters, or does not start with a lowercase letter or underscore.
Sourcepub fn name(&self) -> &str
pub fn name(&self) -> &str
Returns the function name.
Useful for introspection and for MockRegistrar.
Sourcepub fn param(self, type_id: TypeId) -> Self
pub fn param(self, type_id: TypeId) -> Self
Adds a positional parameter with the given type.
Call this once per parameter in order. For complex types like
LIST(BIGINT) or MAP(VARCHAR, INTEGER), use param_logical.
Sourcepub fn param_logical(self, logical_type: LogicalType) -> Self
pub fn param_logical(self, logical_type: LogicalType) -> Self
Adds a positional parameter with a complex LogicalType.
Use this for parameterized types that TypeId cannot express, such as
LIST(BIGINT), MAP(VARCHAR, INTEGER), or STRUCT(...).
The parameter position is determined by the total number of param and
param_logical calls made so far.
§Example
use quack_rs::aggregate::AggregateFunctionBuilder;
use quack_rs::types::{LogicalType, TypeId};
// fn register(con: libduckdb_sys::duckdb_connection) -> Result<(), quack_rs::error::ExtensionError> {
// AggregateFunctionBuilder::new("my_func")
// .param(TypeId::Varchar)
// .param_logical(LogicalType::list(TypeId::BigInt))
// .returns(TypeId::BigInt)
// // ... callbacks ...
// ;
// Ok(())
// }Sourcepub const fn returns(self, type_id: TypeId) -> Self
pub const fn returns(self, type_id: TypeId) -> Self
Sets the return type for this function.
For complex return types like LIST(BIGINT), use
returns_logical instead.
Sourcepub fn returns_logical(self, logical_type: LogicalType) -> Self
pub fn returns_logical(self, logical_type: LogicalType) -> Self
Sets the return type to a complex LogicalType.
Use this for parameterized return types that TypeId cannot express,
such as LIST(BOOLEAN), LIST(TIMESTAMP), MAP(VARCHAR, INTEGER), etc.
If both returns and returns_logical are called, the logical type takes
precedence.
§Example
use quack_rs::aggregate::AggregateFunctionBuilder;
use quack_rs::types::{LogicalType, TypeId};
// fn register(con: libduckdb_sys::duckdb_connection) -> Result<(), quack_rs::error::ExtensionError> {
// AggregateFunctionBuilder::new("retention")
// .param(TypeId::Boolean)
// .param(TypeId::Boolean)
// .returns_logical(LogicalType::list(TypeId::Boolean))
// // ... callbacks ...
// ;
// Ok(())
// }Sourcepub fn state_size(self, f: StateSizeFn) -> Self
pub fn state_size(self, f: StateSizeFn) -> Self
Sets the state_size callback.
Sourcepub fn init(self, f: StateInitFn) -> Self
pub fn init(self, f: StateInitFn) -> Self
Sets the state_init callback.
Sourcepub fn finalize(self, f: FinalizeFn) -> Self
pub fn finalize(self, f: FinalizeFn) -> Self
Sets the finalize callback.
Sourcepub fn destructor(self, f: DestroyFn) -> Self
pub fn destructor(self, f: DestroyFn) -> Self
Sets the optional destructor callback.
Required if your state allocates heap memory (e.g., when using
FfiState<T>).
Sourcepub const fn null_handling(self, handling: NullHandling) -> Self
pub const fn null_handling(self, handling: NullHandling) -> Self
Sets the NULL handling behaviour for this aggregate function.
By default, DuckDB skips NULL rows in aggregate functions
(DefaultNullHandling).
Set to SpecialNullHandling to receive
NULL values in your update callback.
Sourcepub unsafe fn extra_info(
self,
data: *mut c_void,
destroy: duckdb_delete_callback_t,
) -> Self
pub unsafe fn extra_info( self, data: *mut c_void, destroy: duckdb_delete_callback_t, ) -> Self
Attaches arbitrary data to this aggregate function.
The data pointer is available inside callbacks via
duckdb_aggregate_function_get_extra_info. The destroy callback is
called by DuckDB when the function is dropped to free the data.
§Safety
data must point to valid memory that outlives the function registration,
or will be freed by destroy. The typical pattern
is to box your data: Box::into_raw(Box::new(my_data)).cast().