Skip to main content

AggregateFunctionBuilder

Struct AggregateFunctionBuilder 

Source
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

Source

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.

Source

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.

Source

pub fn name(&self) -> &str

Returns the function name.

Useful for introspection and for MockRegistrar.

Source

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.

Source

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(())
// }
Source

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.

Source

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(())
// }
Source

pub fn state_size(self, f: StateSizeFn) -> Self

Sets the state_size callback.

Source

pub fn init(self, f: StateInitFn) -> Self

Sets the state_init callback.

Source

pub fn update(self, f: UpdateFn) -> Self

Sets the update callback.

Source

pub fn combine(self, f: CombineFn) -> Self

Sets the combine callback.

Source

pub fn finalize(self, f: FinalizeFn) -> Self

Sets the finalize callback.

Source

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>).

Source

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.

Source

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().

Source

pub unsafe fn register( self, con: duckdb_connection, ) -> Result<(), ExtensionError>

Registers the aggregate function on the given connection.

§Errors

Returns ExtensionError if:

  • The return type was not set.
  • Any required callback was not set.
  • DuckDB reports a registration failure.
§Safety

con must be a valid, open duckdb_connection.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.