Skip to content
Query.Farm
Talk with Us

Aggregate functions

On this page

Per-group accumulation: update, combine, finalize.

source
export interface AggregateBindParams<TArgs = Record<string, any>>

Fields

argsTArgs
argumentsArguments
inputSchemaVgiSchema | null
settingsRecord<string, any>
secretsRecord<string, Record<string, any>>
source
export interface AggregateFinalizeParams<TArgs = Record<string, any>, TState = any>

Fields

groupIdsbigint[]
statesMap<bigint, TState | null>
outputSchemaVgiSchema
argsTArgs
source
export interface AggregateFunctionConfig<TArgs = Record<string, any>, TState = any>

Fields

namestring
outputTypeVgiDataType

Arrow type of the aggregate’s output (one value per group). DuckDB uses this to build the result column type at bind time. May be overridden at bind time by onBind (returning a different Arrow type) for aggregates whose return type depends on the input column type (e.g. vgi_generic_sum: BIGINT input → BIGINT output, DOUBLE → DOUBLE).

initialState(params: AggregateBindParams<TArgs>) => TState
update(params: AggregateUpdateParams<TArgs, TState>) => void

Fold a batch of input rows into the provided per-group state map. Implementations mutate states in place. groupIds[i] identifies which group row i belongs to; columns[k][i] is the value for the kth declared column argument at row i.

combine(source: TState, target: TState, params: AggregateBindParams<TArgs>) => TState
finalize(params: AggregateFinalizeParams<TArgs, TState>) => VgiBatch

Must return a single-column RecordBatch with groupIds.length rows.

descriptionstringoptional
argsRecord<string, VgiDataType>optional

Map of positional argument name → Arrow type. Passed through to DuckDB function registration. Use null (untyped) for varargs placeholders.

varargsstring[]optional

Names of args that accept a variable number of column arguments. DuckDB treats these as varargs of the declared Arrow type; at call time the function may receive 1..N columns of that type. update() sees all of them as consecutive entries in columns.

constParamsstring[]optional

Names of args whose value is constant (known at bind time) and must be folded away by DuckDB before reaching update(). The value arrives in bindParams.args[name]; it is NOT passed as an input column in the update batch. Use for aggregates parameterized by a literal (e.g. percentile=0.5 in vgi_percentile).

onBind(params: AggregateBindParams<TArgs>) => VgiDataType | Promise<VgiDataType>optional

Optional bind-time hook for dynamic output types. Receives the bind parameters (including input_schema) and returns the Arrow type to advertise for this invocation. Defaults to returning config.outputType.

argDefaultsRecord<string, any>optional

Optional per-arg default values (positional only here).

argConstraintsRecord<string, ArgumentConstraints>optional

Per-argument discovery constraints (choices / ge / le / gt / lt / pattern), keyed by argument name. Surfaced via vgi_function_arguments() and enforced at aggregate_bind for const params: a value violating a declared constraint fails the bind with an ArgumentValidationError.

examplesFunctionExample[]optional
categoriesstring[]optional
tagsRecord<string, string>optional

Arbitrary function-level tags surfaced into duckdb_functions().tags.

nullHandling“DEFAULT” | “SPECIAL”optional
requiredSecretsstring[]optional

DuckDB secret types this aggregate needs. Advertised on the catalog’s required_secrets so the C++ extension pre-resolves matching secrets and delivers their VALUES on the aggregate_bind request (keyed by secret name). The secret is read at bind time only — update/combine/finalize receive an empty ResolvedSecrets. Mirrors vgi-python’s Secret() annotation on an aggregate on_bind.

source
export interface AggregateUpdateParams<TArgs = Record<string, any>, TState = any>

Fields

statesMap<bigint, TState>
groupIdsbigint[]
columnsany[]
argsTArgs
ensureState(gid: bigint) => TState

Get-or-initialize accessor for per-group state. Call this inside the loop only when the row actually contributes to the aggregate — skipping it (e.g. on NULL input under NullHandling.DEFAULT) leaves states without an entry for the group, so finalize() can return SQL NULL for that group (matches vgi-python’s “state absent = NULL” semantics for SUM/AVG/MIN/MAX over zero non-null rows).

source
export function defineAggregate<TArgs = Record<string, any>, TState = any>(
config: AggregateFunctionConfig<TArgs, TState>,
): VgiFunction & { aggregateConfig: AggregateFunctionConfig<TArgs, TState> }

Description

Declare an aggregate function. The returned VgiFunction has kind: "aggregate" plus a config handle the dispatch layer uses to drive the aggregate_* RPCs; the scalar/table-function code paths ignore it.

source
const GROUP_COLUMN_NAME = “__vgi_group_id”