Table-in-out functions
On this page
Streaming a relation through, batch by batch.
class PassthroughTIOFunction
Section titled âclass PassthroughTIOFunctionâpublic abstract class PassthroughTIOFunction implements TableInOutFunctionDescription
Base for table-in-out functions whose output schema equals their input
schema (echo, filter, repeat, exception-finalize, etc.). Mirrors the
vgi-python TableInOutGenerator default-bind shape.
Subclasses inherit a default #onBind that returns the input
schema (with an empty-schema fallback for catalog enumeration). They still
provide name(), metadata(), argumentSpecs(), and
createExchange() as usual.
Members
BindResponse onBind(TableInOutBindParams params)Returns the input schema as the output schema, falling back to an empty schema when no input is present (catalog enumeration).
interface RowTransformFunction
Section titled âinterface RowTransformFunctionâpublic interface RowTransformFunction extends TableInOutFunctionDescription
Blended (âUNNEST-styleâ) table-in-out: positional args ARE per-row input columns.
A RowTransformFunction collapses the classic either/or between a
standard table function (literal args only) and a table-in-out function (an
explicit TABLE subquery arg). Its positional
farm.query.vgi.function.ArgSpecs declare its per-row input columns â
real typed args, NO synthetic TABLE placeholder â so ONE registration
serves every call shape:
f(52, 13) -- literal -> one input row FROM t, f(t.x, t.y) -- columns -> streaming input SELECT ... FROM t, LATERAL f(t.x, t.y)Contract.
-
Positional args are the input columns; they arrive on the exchangeâs input batch (by declared name for fixed args,
col0..colN-1for varargs â read them positionally). They are NOT on the wire arguments. -
Named args stay bind-time scalars on
params.arguments().named(). -
Map-shaped, per-row: 1->1, 1->N, 1->0 all work. There is no finalize â
#hasFinalize()is final-false here (DuckDB forbidsFinalExecuteunder correlated LATERAL, one of the call shapes blended must serve). Accumulating functions use a classicTABLE-input table-in-out or afarm.query.vgi.buffering.TableBufferingFunction. -
A positional const arg must not be declared (in the column form DuckDB sweeps a constant into the input subquery; in the literal form it is indistinguishable from an input column). Use a named arg for optional config.
Implementing this interface (not a metadata flag) IS the blended signal â
a per-arg or metadata flag could be forgotten on one of N same-named
overloads; the type cannot. The wire FunctionInfo.input_from_args is
derived from it, and the C++ extension reads that to enter the in-out
registration branch with real-typed args and drive the literal single-row
scan-mode. Mirrors vgi-pythonâs RowTransformFunction.
record TableInOutBindParams
Section titled ârecord TableInOutBindParamsâpublic record TableInOutBindParams( String functionName, Arguments arguments, Schema inputSchema, Map<String, Object> settings, byte[] secrets, boolean resolvedSecretsProvided, byte[] attachOpaqueData, farm.query.vgi.storage.BoundStorage attachStorage, farm.query.vgi.protocol.CopyToContext copyTo)Description
Bind-time inputs for a TableInOutFunction: the resolved arguments and
the schema of the incoming stream, from which the function derives its output
schema.
Members
TableInOutBindParams(String functionName, Arguments arguments, Schema inputSchema, Map<String, Object> settings)Convenience constructor with no attach context (catalog enumeration).
TableInOutBindParams(String functionName, Arguments arguments, Schema inputSchema, Map<String, Object> settings, byte[] secrets, boolean resolvedSecretsProvided, byte[] attachOpaqueData, farm.query.vgi.storage.BoundStorage attachStorage)Convenience constructor without the copyTo context (non-COPY binds).
class TableInOutExchangeState
Section titled âclass TableInOutExchangeStateâpublic abstract class TableInOutExchangeState extends ExchangeStateDescription
Base for table-in-out exchange states: each input batch produces zero or
one output batch via #process. Subclasses override
#onInputBatch which receives the AnnotatedBatch input root
and the OutputCollector to emit on.
Members
void exchange(AnnotatedBatch input, OutputCollector out, CallContext ctx)Final dispatch hook from the RPC layer; forwards each input batch to
#onInputBatch.
void onInputBatch(AnnotatedBatch input, OutputCollector out, CallContext ctx)Processes a single input batch, emitting zero or one output batch.
interface TableInOutFunction
Section titled âinterface TableInOutFunctionâpublic interface TableInOutFunction extends FunctionDescriptorDescription
A VGI table-in-out function: receives input batches and emits output batches, one output batch per input batch (echo, filter, transform). State may accumulate across exchange ticks and round-trips with the stream, so it works on both the launcher and HTTP transports.
A streaming table-in-out may additionally declare a per-substream
finalize (#hasFinalize() + #finish): under per-substream
worker fan-out, DuckDB runs one substream per PipelineExecutor and issues a
FINALIZE-phase init (same execution_id as the substreamâs
INPUT phase) after input EOS. The finalize sees only this
substreamâs accumulated state â coordinate it through
params.storage() (execution-scoped), never a global cross-substream
merge.
Functions that need a global Sink+Combine+Source shape â buffer
the whole input across every substream, then emit a summary at the end
(sums, distributed aggregation, full buffering) â use
farm.query.vgi.buffering.TableBufferingFunction instead, whose
worker-side storage (keyed by execution_id) survives the stateless
HTTP processâcombineâfinalize round-trip.
Mirrors vgi.TableInOutFunction in vgi-go.
record TableInOutInitParams
Section titled ârecord TableInOutInitParamsâpublic record TableInOutInitParams( String functionName, Arguments arguments, Schema inputSchema, Schema outputSchema, Map<String, Object> settings, BufferAllocator allocator, farm.query.vgi.storage.BoundStorage storage, byte[] secrets, byte[] substreamId)Description
Per-execution inputs handed to TableInOutFunction#createExchange when
a stream begins: the bound arguments, the negotiated input and (possibly
projection-narrowed) output schemas, and the allocator the exchange must use.
Members
TableInOutInitParams( String functionName, Arguments arguments, Schema inputSchema, Schema outputSchema, Map<String, Object> settings, BufferAllocator allocator, farm.query.vgi.storage.BoundStorage storage, byte[] secrets)Compatibility constructor without a substream id (serial path).