Protocol & metadata
On this page
Function metadata and the on-the-wire request/response types.
struct ArgSpec
Section titled âstruct ArgSpecâtype ArgSpec struct {// Name is the argument name (empty for positional-only).Name string// Position is the positional index (0-based). -1 for named-only.Position int// ArrowType is the Arrow type string (e.g., "int64", "varchar", "any").ArrowType string// Doc is a documentation string.Doc string// IsConst is true for constant (scalar) parameters.IsConst bool// IsVarargs is true for variadic parameters.IsVarargs bool// HasDefault is true if the parameter has a default value.HasDefault bool// DefaultValue is the string representation of the default.DefaultValue string// ArrowDataType is an optional concrete Arrow DataType for the argument.// When set, it takes precedence over ArrowType for schema building.// Use this for complex types like structs where the string representation// is insufficient (e.g., arrow.StructOf(...) for typed struct params).ArrowDataType arrow.DataType// TypeBound is an optional slice of type predicates for "any"-typed arguments.// At bind time, the input schema field type must satisfy at least one predicate// (OR logic). Nil means no type constraint (any type is accepted).TypeBound []TypeBoundPredicate
// Choices is an optional closed set of allowed values for this argument.// Surfaced as the vgi_choices field-metadata key (JSON array). Element// values should match the argument's value type. Nil/empty = unrestricted.Choices []any// Ge is an optional inclusive lower bound (value >= Ge). nil = absent.Ge *float64// Le is an optional inclusive upper bound (value <= Le). nil = absent.Le *float64// Gt is an optional exclusive lower bound (value > Gt). nil = absent.Gt *float64// Lt is an optional exclusive upper bound (value < Lt). nil = absent.Lt *float64// Pattern is an optional regex the value must match. Surfaced as the// vgi_pattern field-metadata key (raw). Empty = no pattern constraint.Pattern string}Description
ArgSpec describes a single argument in a functionâs signature.
Methods
function DeriveArgSpecs
Section titled âfunction DeriveArgSpecsâfunc DeriveArgSpecs(args any) []ArgSpecDeriveArgSpecs returns []ArgSpec derived from the structâs vgi:"..." tags.
args may be a struct value or pointer to one. Panics on malformed tags;
these are developer errors that should fail at startup.
function getArgSpecsFromFn
Section titled âfunction getArgSpecsFromFnâfunc getArgSpecsFromFn(fn interface{}) []ArgSpecgetArgSpecsFromFn extracts ArgumentSpecs from any function type.
function parseArgTag
Section titled âfunction parseArgTagâfunc parseArgTag(f reflect.StructField, tag string) (ArgSpec, error)parseArgTag parses one vgi:"..." tag, applying Go-type-based inference for
unspecified fields (name, ArrowType, ArrowDataType).
function writableArgumentSpecs
Section titled âfunction writableArgumentSpecsâfunc writableArgumentSpecs() []ArgSpectype DistinctDependence
Section titled âtype DistinctDependenceâtype DistinctDependence stringDescription
DistinctDependence declares whether a DISTINCT modifier changes an aggregateâs result. Wire-protocol dictionary constants â must not be changed.
struct FinalizeProducerState
Section titled âstruct FinalizeProducerStateâtype FinalizeProducerState struct {Recipe InitRecipe // exported, serializedBatchIPC [][]byte // exported, serialized finalize batch IPC bytesBatchIdx int // exported, current emission positionbatches []arrow.RecordBatch // transient (deserialized from BatchIPC)// CacheMeta, when non-nil, is attached to every emitted finalize batch.// Set from FunctionMetadata.CacheControl so a table-buffering function can// advertise vgi.cache.* on its finalize output for the exchange-mode// result cache (the C++ side latches the first batch's keys). Exported so// it survives the HTTP state-token round-trip.CacheMeta map[string]string}Description
FinalizeProducerState implements ProducerState for table-in-out FINALIZE phase.
Methods
method Produce
Section titled âmethod Produceâfunc (s *FinalizeProducerState) Produce(ctx context.Context, out *vgirpc.OutputCollector, callCtx *vgirpc.CallContext) errorProduce emits the next buffered finalize batch to the output collector, finishing the stream once all batches have been emitted.
struct FunctionMetadata
Section titled âstruct FunctionMetadataâtype FunctionMetadata struct {// Description is a human-readable description.Description string// Stability controls caching/optimization hints.Stability FunctionStability// NullHandling controls whether NULLs are passed to the function.NullHandling NullHandling// ProjectionPushdown indicates support for projection pushdown.ProjectionPushdown bool// FilterPushdown indicates support for filter pushdown.FilterPushdown bool// SamplingPushdown indicates support for TABLESAMPLE SYSTEM pushdown.SamplingPushdown bool// LateMaterialization advertises that the function participates in DuckDB's// late-materialization rewrite. DuckDB only honours this when the function// also exposes a rowid virtual column and supports projection + filter// pushdown; the rowid must be unique, deterministic, and snapshot-stable.LateMaterialization bool// SupportedExpressionFilters lists DuckDB expression names that the// function can absorb into its scan (e.g. "&&", "list_contains",// "starts_with"). Without this, DuckDB inserts a separate FILTER node.SupportedExpressionFilters []string// SupportsWindow indicates an aggregate also implements the windowed// callbacks (window_init, window, window_destructor). Ignored for// non-aggregate functions.SupportsWindow bool// StreamingPartitioned indicates an aggregate also implements the// streaming-partitioned protocol (aggregate_streaming_open/_chunk/_close).// DuckDB's optimizer can replace a LogicalWindow with the streaming// operator when the frame is cumulative. The function MUST also keep its// standard update/combine/finalize path for the fallback case.StreamingPartitioned bool// HasFinalize signals a TableInOut function whose Finalize method emits// meaningful batches. Defaults to false; set to true only for functions// that accumulate during Process and flush at end-of-stream. DuckDB// skips the FINALIZE phase RPC entirely when this is false â required// for LATERAL compatibility (avoids "FinalExecute not supported for// project_input").HasFinalize bool// OrderPreservation declares how a table function's output rows relate// to its inputs. Empty leaves the field null and uses the C++ extension// default. Maps to DuckDB's OrderPreservationType.OrderPreservation OrderPreservation// OrderDependent declares whether the aggregate result depends on the// row order. Empty defaults to NOT_ORDER_DEPENDENT.OrderDependent OrderDependence// DistinctDependent declares whether DISTINCT changes the result.// Empty defaults to NOT_DISTINCT_DEPENDENT.DistinctDependent DistinctDependence// AutoApplyFilters indicates the framework should auto-apply pushdown filters.AutoApplyFilters bool// Categories is a list of classification tags for the function.Categories []string// Tags are arbitrary key/value annotations surfaced through the catalog as// duckdb_functions().tags. Distinct from Categories (a flat list); Tags is// a map for structured metadata (e.g. {"category": "debug"}).Tags map[string]string// Examples lists usage examples surfaced in the catalog's FunctionInfo.// Each example carries SQL, a description, and an optional expected output.Examples []CatalogExample// ReturnType is the static return type for scalar functions.// When set, the catalog registers this concrete type instead of ANY.// Leave nil for functions with dynamic return types (resolved at bind time).ReturnType arrow.DataType// RequiredSecrets lists secret types the function needs at bind time.RequiredSecrets []SecretRequirement// SupportsBatchIndex opts a table function into per-batch vgi_batch_index// tagging (see EmitBatchIndex). The C++ extension enforces monotonicity.SupportsBatchIndex bool// PartitionKind declares the partition shape of a table function's output// (see PartitionField / EmitPartitioned). Empty = NOT_PARTITIONED.PartitionKind PartitionKind// SourceOrderDependent / SinkOrderDependent / RequiresInputBatchIndex are// table-buffering ordering hints (mirror the FunctionInfo fields).SourceOrderDependent boolSinkOrderDependent boolRequiresInputBatchIndex bool// InputFromArgs marks a blended ("UNNEST-style") table-in-out function: the// function's positional args ARE its per-row input columns (real typed// args, no synthetic TABLE placeholder), so ONE registration serves// f(52, 13) (literal -> 1 input row), FROM t, f(t.x, t.y) (columns ->// streaming), and LATERAL f(t.x, t.y). A blended function is map-shaped and// per-row: it must NOT set HasFinalize (DuckDB forbids FinalExecute under// correlated LATERAL, one of the call shapes blended must serve), must not// declare a "table"-typed arg, and must not take a positional const arg.// The worker reads the positional args from the input batch (by declared// name for fixed args, positionally for varargs); named args stay bind-time// scalars on ProcessParams.Args. Mirrors vgi-python's RowTransformFunction.InputFromArgs bool// CacheControl opts the function into the extension's result cache: when// set, its vgi.cache.* metadata is attached by the framework to every// output batch of a SCALAR function and to every finalize batch of a// TABLE-BUFFERING function (the exchange-mode buffered result cache).// Per-VALUE memoization of a scalar is a SEPARATE opt-in on top of this â// set CacheControl.PerValue, and only when one call is more expensive than// a cache probe plus a decode (see that field). A pure, deterministic function// only â advertising this on a non-pure function serves stale rows.// Streaming table(-in-out) functions attach cache control per-emit instead// (vgi.WithCacheControl). Mirrors vgi-python's ScalarFunction.CACHE_CONTROL// and the buffered finalize cache-control support.CacheControl *CacheControl}Description
FunctionMetadata holds descriptive metadata about a function.
Methods
function DefaultMetadata
Section titled âfunction DefaultMetadataâfunc DefaultMetadata() FunctionMetadataDefaultMetadata returns metadata with default values.
function writableMetadata
Section titled âfunction writableMetadataâfunc writableMetadata(desc string) FunctionMetadatatype FunctionStability
Section titled âtype FunctionStabilityâtype FunctionStability stringDescription
FunctionStability describes when function results may change.
type FunctionType
Section titled âtype FunctionTypeâtype FunctionType stringDescription
FunctionType identifies the kind of VGI function.
Methods
function normalizeFunctionType
Section titled âfunction normalizeFunctionTypeâfunc normalizeFunctionType(ft FunctionType) FunctionTypenormalizeFunctionType converts DuckDB function type strings to our canonical values.
type NullHandling
Section titled âtype NullHandlingâtype NullHandling stringDescription
NullHandling describes how the function handles NULL inputs. These values are DuckDB wire-protocol constants and must not be changed.
type OrderByDirection
Section titled âtype OrderByDirectionâtype OrderByDirection stringDescription
OrderByDirection is the sort direction carried by an ORDER BY pushdown hint. Wire-protocol dictionary constants â must not be changed.
type OrderByNullOrder
Section titled âtype OrderByNullOrderâtype OrderByNullOrder stringDescription
OrderByNullOrder is the NULL placement carried by an ORDER BY pushdown hint. Wire-protocol dictionary constants â must not be changed.
type OrderDependence
Section titled âtype OrderDependenceâtype OrderDependence stringDescription
OrderDependence declares whether an aggregateâs result depends on row order. Wire-protocol dictionary constants â must not be changed.
type OrderPreservation
Section titled âtype OrderPreservationâtype OrderPreservation stringDescription
OrderPreservation declares how a table functionâs output rows relate to its inputs. These values are DuckDB wire-protocol dictionary constants and must not be changed. The empty value leaves the field null (C++ extension default).
type PartitionKind
Section titled âtype PartitionKindâtype PartitionKind stringDescription
PartitionKind describes the partition shape a table function declares over its vgi.partition_column-annotated bind-schema fields. These values are DuckDB wire-protocol dictionary constants and must not be changed.
type Phase
Section titled âtype Phaseâtype Phase stringDescription
Phase identifies the table-in-out init phase. Wire-protocol dictionary constants â must not be changed.
struct ScalarExchangeState
Section titled âstruct ScalarExchangeStateâtype ScalarExchangeState struct {Recipe InitRecipe // exported, serializedfn ScalarFunction // transientparams *ProcessParams // transient
// cacheMetaResolved memoizes the result-cache annotation for this stream.// Metadata()/CacheControl.Metadata() are invariant across batches, so we// resolve them once on the first Exchange and reuse the map (nil for a// non-cacheable scalar). Transient: recomputed after rehydration.cacheMetaResolved bool // transientcacheMeta map[string]string // transient}Description
ScalarExchangeState implements ExchangeState for scalar functions.
Methods
method Exchange
Section titled âmethod Exchangeâfunc (s *ScalarExchangeState) Exchange(ctx context.Context, input arrow.RecordBatch, out *vgirpc.OutputCollector, callCtx *vgirpc.CallContext) errorExchange processes one input batch through the scalar function and emits the resulting batch to the output collector.
struct SecretLookup
Section titled âstruct SecretLookupâtype SecretLookup struct {SecretType stringSecretName stringScope string}Description
SecretLookup describes a scoped secret lookup request for two-phase bind.
struct SecretRequirement
Section titled âstruct SecretRequirementâtype SecretRequirement struct {SecretType stringSecretName string // empty = not specifiedScope string // empty = not specified}Description
SecretRequirement describes a secret type that a function needs.
type Secrets
Section titled âtype Secretsâtype Secrets map[string]map[string]interface{}Description
Secrets holds the resolved secrets passed to a worker, keyed by each secretâs unique DuckDB secret name (not by type), so several secrets of the same type (e.g. one per S3 bucket) coexist. Each secret is a map of its fields, including the connector-serialized âtypeâ (the DuckDB secret type) and âscopeâ (newline-joined scope prefixes), plus type-specific fields like âkey_idâ.
Secrets is a plain map, so direct access (s[name][field]) still works; the methods below add type- and scope-aware selection.
Methods
method Field
Section titled âmethod Fieldâfunc (s Secrets) Field(field string) (string, bool)Field returns the first secret (of any name) carrying field, rendered to a string; ok is false when no secret carries it.
method FieldForScope
Section titled âmethod FieldForScopeâfunc (s Secrets) FieldForScope(path, field string) (string, bool)FieldForScope returns a field of the best scope-matching secret for path.
method ForScope
Section titled âmethod ForScopeâfunc (s Secrets) ForScope(path string) (map[string]interface{}, bool)ForScope returns the fields of the resolved secret whose âscopeâ is the longest prefix of path. Use this when the worker requested secrets for several scopes (e.g. one per cloud path / bucket) and must pick the right one per path. The connector serializes each secretâs scope as a newline-joined list of prefixes; a secret with no (or empty) scope matches as a last-resort fallback. ok is false only when there are no candidate secrets.
method ForScopeOfType
Section titled âmethod ForScopeOfTypeâfunc (s Secrets) ForScopeOfType(path, secretType string) (map[string]interface{}, bool)ForScopeOfType is like ForScope but only over secrets of secretType â the precise selector for cloud paths (e.g. the s3 secret matching a given s3://⌠URL when several buckets are in play).
method NamedField
Section titled âmethod NamedFieldâfunc (s Secrets) NamedField(name, field string) (string, bool)NamedField returns a field of the named secret, rendered to a string.
method OfType
Section titled âmethod OfTypeâfunc (s Secrets) OfType(secretType string) []map[string]interface{}OfType returns every resolved secret whose serialized âtypeâ field matches secretType (since secrets are keyed by name, not type).
method SecretType
Section titled âmethod SecretTypeâfunc (s Secrets) SecretType(name string) (string, bool)SecretType returns the DuckDB secret type of the named secret (its serialized âtypeâ field).
method selectForScope
Section titled âmethod selectForScopeâfunc (s Secrets) selectForScope(path, secretType string) (map[string]interface{}, bool)struct TableInOutExchangeState
Section titled âstruct TableInOutExchangeStateâtype TableInOutExchangeState struct {Recipe InitRecipe // exported, serializedUserStateBytes []byte // exported, gob-serialized user statefn TableInOutFunction // transientparams *ProcessParams // transientstate interface{} // transientautoApply *PushdownFilters // transient}Description
TableInOutExchangeState implements ExchangeState for table-in-out INPUT phase.
Methods
method Exchange
Section titled âmethod Exchangeâfunc (s *TableInOutExchangeState) Exchange(ctx context.Context, input arrow.RecordBatch, out *vgirpc.OutputCollector, callCtx *vgirpc.CallContext) errorExchange transforms one input batch through the table-in-out function and emits the resulting batches to the output collector.
method GobDecode
Section titled âmethod GobDecodeâfunc (s *TableInOutExchangeState) GobDecode(data []byte) errorGobDecode restores the exported wire fields; transient fields are rebuilt by rehydrateTableInOut.
method GobEncode
Section titled âmethod GobEncodeâfunc (s *TableInOutExchangeState) GobEncode() ([]byte, error)GobEncode snapshots the live user state into UserStateBytes, then encodes the wire form. Each table-in-out exchange tick re-serializes the token, so the INPUT-phase state must reflect the latest Process mutation.
struct TableProducerState
Section titled âstruct TableProducerStateâtype TableProducerState struct {Recipe InitRecipe // exported, serializedUserStateBytes []byte // exported, gob-serialized user stateAutoProjectIDs []int32 // exportedfn TableFunction // transientparams *ProcessParams // transientstate interface{} // transient (reconstructed from UserStateBytes)autoApply *PushdownFilters // transient}Description
TableProducerState implements ProducerState for table functions.
Methods
method GobDecode
Section titled âmethod GobDecodeâfunc (s *TableProducerState) GobDecode(data []byte) errorGobDecode restores the exported wire fields; transient fields are rebuilt by rehydrateTableProducer.
method GobEncode
Section titled âmethod GobEncodeâfunc (s *TableProducerState) GobEncode() ([]byte, error)GobEncode snapshots the live user state into UserStateBytes, then encodes the wire form. See the file-level comment for why this is required.
method Produce
Section titled âmethod Produceâfunc (s *TableProducerState) Produce(ctx context.Context, out *vgirpc.OutputCollector, callCtx *vgirpc.CallContext) errorProduce advances the table function by one tick, applying any dynamic filter update carried on the tickâs metadata and emitting produced batches to the output collector.
func type TypeBoundPredicate
Section titled âfunc type TypeBoundPredicateâtype TypeBoundPredicate func(arrow.DataType) boolDescription
TypeBoundPredicate is a function that validates whether an Arrow DataType is acceptable for a given argument. Used with ArgSpec.TypeBound to constrain âanyâ-typed arguments to specific type families (e.g., numeric types only).
Methods
function LookupTypeBound
Section titled âfunction LookupTypeBoundâfunc LookupTypeBound(name string) TypeBoundPredicateLookupTypeBound returns the predicate registered under name, or nil.
function resolveBounds
Section titled âfunction resolveBoundsâfunc resolveBounds(spec string) ([]TypeBoundPredicate, error)type WriteOp
Section titled âtype WriteOpâtype WriteOp stringDescription
WriteOp identifies which DML operation a writable-table function lookup is for. Wire-protocol dictionary constants â must not be changed.
function RenderSecretValue
Section titled âfunction RenderSecretValueâfunc RenderSecretValue(v interface{}) stringRenderSecretValue renders a secret field value to a string.
function applyTickFilters
Section titled âfunction applyTickFiltersâfunc applyTickFilters(params *ProcessParams, meta arrow.Metadata)applyTickFilters checks the tick-level custom metadata for a dynamic filter update and, if present, replaces params.CurrentPushdownFilters with the freshly decoded filter state. Silent on decode errors â the previous filter state is retained (DuckDB falls back to client-side filtering).
function applyTickValidators
Section titled âfunction applyTickValidatorsâfunc applyTickValidators(params *ProcessParams, meta arrow.Metadata)applyTickValidators lifts the conditional-revalidation validators off a tickâs custom metadata onto ProcessParams. The client sends them when it holds a stale-but-revalidatable cached result and wants the worker to confirm freshness without recomputing. They arrive once â on the first tick (subprocess) or on the init request (HTTP) â and stay set for the stream.
function attachAAD
Section titled âfunction attachAADâfunc attachAAD(auth *vgirpc.AuthContext) []byteattachAAD is the AAD for an attach_opaque_data envelope.
function identityTail
Section titled âfunction identityTailâfunc identityTail(auth *vgirpc.AuthContext) []byteidentityTail builds the identity portion of an opaque-data AAD. Mirrors the (domain, principal) convention: unauthenticated requests get a fixed anonymous tail, so an anonymous caller cannot open an envelope sealed for a real principal.
function normalizeCryptoKey
Section titled âfunction normalizeCryptoKeyâfunc normalizeCryptoKey(key []byte) []bytenormalizeCryptoKey stretches/compresses an arbitrary-length key to the 32 bytes XChaCha20-Poly1305 requires. Matches vgi-pythonâs normalize_key.
function openBytes
Section titled âfunction openBytesâfunc openBytes(token, key, aad []byte, version byte) ([]byte, error)openBytes opens and verifies an envelope produced by sealBytes. Every failure mode â malformed, wrong version, tampered, wrong key, wrong AAD (cross-principal/cross-attach replay) â returns errOpaqueDataRejected.
function projectBatch
Section titled âfunction projectBatchâfunc projectBatch(batch arrow.RecordBatch, ids []int32) arrow.RecordBatchprojectBatch selects only the columns at the given indices from a RecordBatch.
function sealBytes
Section titled âfunction sealBytesâfunc sealBytes(payload, key, aad []byte, version byte) ([]byte, error)sealBytes seals payload into an AEAD envelope: version || nonce || ct+tag.
function selectColumnsByName
Section titled âfunction selectColumnsByNameâfunc selectColumnsByName(src arrow.RecordBatch, schema *arrow.Schema) (arrow.RecordBatch, error)selectColumnsByName builds a batch containing only the columns named in schema, in schema order, taken from src by field name.
function transactionAAD
Section titled âfunction transactionAADâfunc transactionAAD(auth *vgirpc.AuthContext, attachEnvelope []byte) []bytetransactionAAD is the AAD for a transaction_opaque_data envelope. It binds both the caller identity and the parent attach envelope, so a transaction value minted under one attach cannot be replayed against a different attach even by the same principal.
function unaryCatalog
Section titled âfunction unaryCatalogâfunc unaryCatalog[P any, R any](w *Worker, s *vgirpc.Server, name string,handler func(context.Context, *vgirpc.CallContext, P) (R, error))unaryCatalog registers a catalog unary handler whose request opaque-data fields are unwrapped before the handler body runs.
function unaryVoidCatalog
Section titled âfunction unaryVoidCatalogâfunc unaryVoidCatalog[P any](w *Worker, s *vgirpc.Server, name string,handler func(context.Context, *vgirpc.CallContext, P) error)unaryVoidCatalog is unaryCatalog for void-returning catalog handlers.