Skip to content
Query.Farm
Talk with Us

Table functions

On this page

Set-returning producers, with the optimizer hooks that make them fast.

source
export function defineTableFunction<
TArgs = Record<string, any>,
TState = null,
>(config: TableFunctionConfig<TArgs, TState>): VgiFunction
source
export interface TableBindParams<TArgs = Record<string, any>>

Fields

argsTArgs
bindCallBindRequest
settingsRecord<string, any>
secretsRecord<string, Record<string, any>>
resolvedSecretsProvidedboolean
source
export interface TableFunctionConfig<
TArgs = Record<string, any>,
TState = null,
>

Fields

namestring
onBind(params: TableBindParams<TArgs>) => | { outputSchema: VgiSchema; opaqueData?: Uint8Array; lookupSecretTypes?: string[]; lookupScopes?: string[]; lookupNames?: string[]; } | Promise<{ outputSchema: VgiSchema; opaqueData?: Uint8Array; lookupSecretTypes?: string[]; lookupScopes?: string[]; lookupNames?: string[]; }>

Bind: return output schema. May be async — handlers await the result.

process( params: TableProcessParams<TArgs>, state: TState, out: OutputCollector ) => void | Promise<void>

Process: emit batches via out, call out.finish() when done

descriptionstringoptional
argsRecord<string, VgiDataType>optional

Argument schema (positional args)

argDocsRecord<string, string>optional

Argument docs

argDefaultsRecord<string, any>optional

Argument defaults

argConstraintsRecord<string, ArgumentConstraints>optional

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

varargsstring[]optional

Names of args that accept variable number of arguments

onInit(params: { args: TArgs; initCall: InitRequest; outputSchema: VgiSchema; executionId: Uint8Array; storage: BoundStorage; }) => GlobalInitResponse | Promise<GlobalInitResponse>optional

Init (optional). May be async — common when storage is HTTP-backed.

initialState(params: TableProcessParams<TArgs>) => TStateoptional

State factory

cardinality(params: TableBindParams<TArgs>) => TableCardinality | Promise<TableCardinality>optional

Cardinality hints

statistics(params: TableBindParams<TArgs>) => ColumnStatistics[] | nulloptional

Per-column statistics for the function’s output. Returned to DuckDB via the table_function_statistics RPC; the optimizer uses min/max to eliminate impossible filters at plan time (folding scans to EMPTY_RESULT). Return null or an empty array when bounds are unknown.

dynamicToString( params: TableBindParams<TArgs>, executionId: Uint8Array, storage: BoundStorage, ) => Record<string, string> | Promise<Record<string, string>>optional

Per-execution diagnostics surfaced under EXPLAIN ANALYZE. DuckDB calls this once per parallel scan thread at pipeline FinishSource via the table_function_dynamic_to_string RPC. Return ordered key→value strings; the C++ extension merges these with the intrinsic keys (Function, Rows Read, Threads). The framework provides a BoundStorage keyed by the global execution_id so process() can persist counters that this callback then reads back — see profiling_demo for the canonical pattern.

projectionPushdownbooleanoptional
filterPushdownbooleanoptional
samplingPushdownbooleanoptional
lateMaterializationbooleanoptional

Opt in to DuckDB’s late-materialization SEMI-join rewrite; requires a UNIQUE, snapshot-stable rowid column. FunctionInfo.late_materialization.

supportedExpressionFiltersstring[]optional
autoApplyFiltersbooleanoptional
stabilityFunctionStabilityoptional
examplesFunctionExample[]optional
categoriesstring[]optional
tagsRecord<string, string>optional
maxWorkersnumberoptional
requiredSettingsstring[]optional
requiredSecretsstring[]optional
preservesOrderOrderPreservationoptional

Row-order preservation behavior; flows to DuckDB’s TableFunction::order_preservation_type.

nullHandlingNullHandlingoptional
orderDependentOrderDependenceoptional
distinctDependentDistinctDependenceoptional
supportsBatchIndexbooleanoptional

Emit per-batch vgi_batch_index; FunctionInfo.supports_batch_index.

partitionKind“NOT_PARTITIONED” | “SINGLE_VALUE_PARTITIONS” | “OVERLAPPING_PARTITIONS” | “DISJOINT_PARTITIONS”optional

Hive-style partition-columns mode; FunctionInfo.partition_kind.

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

Fields

argsTArgs
initCallInitRequest
initResponseGlobalInitResponse
outputSchemaVgiSchema
settingsRecord<string, any>
secretsRecord<string, Record<string, any>>
pushdownFiltersPushdownFiltersoptional
storageBoundStorageoptional
atUnitstringoptional

AT (TIMESTAMP|VERSION) clause for this scan, or undefined when the scan has no AT clause. Carried on the per-scan bind embedded in the init request (initCall.bind_call.at_unit / .at_value), so function-backed tables can read time travel at init alongside their pushdown filters. Mirrors vgi-python’s ProcessParams.at_unit / .at_value. See BindRequest.at_unit.

atValuestringoptional
ifNoneMatchstringoptional

Conditional-revalidation validator (the client’s stored ETag). Set when the client holds a stale-but-revalidatable cached result and asks the worker to confirm freshness cheaply; a worker that advertised revalidatable compares it and, if unchanged, emits a 0-row batch tagged cacheControlMetadata({ notModified: true }) instead of re-streaming. Undefined on a normal call.

ifModifiedSincestringoptional

Conditional-revalidation validator (the client’s stored Last-Modified). Companion to {@link ifNoneMatch}. Undefined on a normal call.