Skip to content
Query.Farm
Talk with Us

Attributes & Arrow types

On this page

Compute parameter annotations and Arrow type helpers.

source
[AttributeUsage(AttributeTargets.Parameter)] public sealed class ConstParamAttribute : Attribute

Description

Marks a Compute parameter as a bind-time constant argument — named after vgi-python's ConstParam marker. DuckDB requires the SQL call site to pass a foldable (constant) expression for this positional argument; its value is extracted once at bind and delivered to every batch of the call (never as a per-row column). ScalarFn resolves const parameters by a SEPARATE positional counter from ParamAttribute ones — the wire's positional_<i> struct fields inside BindRequest.Arguments are indexed 0.. over CONST parameters only, in Compute declaration order.

Public members

public double Ge { get; set; }

Inclusive lower bound (>=), surfaced as part of vgi_function_arguments() 's arg_range interval notation (e.g. "[0, 10]" ) and — for a table-function positional/named argument built via the matching range on Table.TableArgFields — enforced at bind time. double.NaN (the default) means unset; at most one of Ge/Gt may be set.

public double Gt { get; set; }

Exclusive lower bound (>). See Ge.

public double Le { get; set; }

Inclusive upper bound (<=). See Ge; at most one of Le/Lt may be set.

public double Lt { get; set; }

Exclusive upper bound (<). See Le.

public string Doc { get; set; }
public string Name { get; set; }
source
[AttributeUsage(AttributeTargets.Parameter)] public sealed class OutputLengthAttribute : Attribute

Description

Marker attribute (no fields) — injects the current batch's row count (an int) into a Compute parameter, for functions with no per-row column input at all (e.g. a const-seeded generator that must still emit one value per row). Named after vgi-python's OutputLength marker.

source
[AttributeUsage(AttributeTargets.Parameter)] public sealed class ParamAttribute : Attribute

Description

Marks a Compute parameter as a per-row (columnar) argument — named after vgi-python's Param marker ( Annotated[pa.Int64Array, Param(doc=…)] ), adapted for C#'s attribute-on-parameter syntax. ScalarFn's reflection dispatch resolves the parameter's own CLR array type (e.g. StringArray ) into the corresponding fixed Arrow type UNLESS Any is set, in which case the parameter's declared CLR type must be the wide IArrowArray and the column's actual on-wire type is accepted as-is (optionally constrained by TypeBound).

Public members

public TypeBoundKind TypeBound { get; set; }
public bool Any { get; set; }

Set to accept any Arrow-typed column (the parameter's CLR type must then be IArrowArray ); TypeBound optionally narrows which actual types are accepted, enforced once at bind time.

public bool Varargs { get; set; }

Consumes every remaining positional column from this point on — the parameter's CLR type must be IReadOnlyList<IArrowArray> (or a same-shaped array type for a fixed-element-type vararg). Must be the last ParamAttribute/ConstParamAttribute-less vector parameter declared.

public string Doc { get; set; }
public string Name { get; set; }

Wire field name; defaults to the parameter's own (snake_cased) CLR name when left empty. Field names are cosmetic for scalar arguments — the C++ side keys by position, not name — but still surfaced for introspection/documentation.

source
[AttributeUsage(AttributeTargets.Parameter)] public sealed class SecretAttribute : Attribute

Description

Marks a Compute parameter as bound to a resolved DuckDB secret — named after vgi-python's Secret marker. Invisible in the function's SQL signature (not counted in IScalarFunction.ArgumentsSchema/ duckdb_functions() ); the C++ extension pre-resolves the secret (by SecretType, optionally narrowed by Name/ Scope) BEFORE the very first bind call and ships it in BindRequest.Secrets — the function must additionally declare this requirement in FunctionInfo.RequiredSecrets for the extension to bother resolving it at all (see Scalar.ScalarFn's ComputePlan , which derives that list automatically from every SecretAttribute it finds). The bound parameter type is IReadOnlyDictionary<string, Apache.Arrow.IArrowArray>? — the resolved secret's field name → single-element value column map (null when no matching secret was resolved). Since scalar functions only support STATIC secret declarations (no dynamic-scope two-phase retry — see Internal.SecretsAccessor's doc comment for why that's a table/table-in-out-only mechanism), the resolved value is available on the very first bind/compute call whenever a matching secret exists at all.

Public members

public required string SecretType { get; init; }

The DuckDB secret TYPE this parameter needs resolved (e.g. "vgi_example" ) — required, C++ enforces type matching.

public string? Name { get; init; }

Optional exact secret name for name-based resolution — null (the default) resolves by type (optionally narrowed by Scope) instead.

public string? Scope { get; init; }

Optional static scope (resolved once, the same way for every call — NOT a per-call dynamic value) for scope-based pre-resolution.

source
[AttributeUsage(AttributeTargets.Parameter)] public sealed class SettingAttribute : Attribute

Description

Marks a Compute parameter as bound to a DuckDB session/connection setting ( SET <key> = … ) rather than a SQL call argument — named after vgi-python's Setting marker. Invisible in the function's SQL signature (not counted in IScalarFunction.ArgumentsSchema/ duckdb_functions() ); the C++ extension resolves the named setting's current value at bind time and ships it in BindRequest.Settings , keyed by Key — the function must additionally declare Key in FunctionInfo.RequiredSettings for the extension to bother looking it up at all (see Scalar.ScalarFn's ComputePlan , which derives that list automatically from every SettingAttribute it finds).

Public members

public string Key { get; set; }

The DuckDB setting name; defaults to the parameter's own (snake_cased) CLR name when left empty.

source
public enum TypeBoundKind

Description

Bind-time constraints that can be attached to an "any"-typed ParamAttribute (a parameter with no fixed Arrow type) — mirrors vgi-python's TypeBoundPredicate / vgi-java's TypeBoundPredicate enum. Currently only one predicate exists upstream.

source
public static class TypeRules

Description

Numeric-promotion rules ported from vgi-java's farm.query.vgi.types.TypeRules (itself mirroring vgi-python's _promote_for_addition /common-type helpers) — used by any scalar fixture whose output type is derived dynamically from its ("any"-typed) input type(s) rather than declared statically ( double , add_values , sum_values ). The core idea in every rule below: promote for OVERFLOW HEADROOM, not just "the wider of the inputs" — doubling/adding two N-bit integers can overflow N bits, so the result gets the next tier up (capped at 64-bit); float always lands on float64; decimal gains exactly one more digit of precision (capped at Arrow's decimal128 38-digit ceiling).

Public members

public static IArrowType CommonTypeForAddition(IArrowType a, IArrowType b) ;

Common type of two operands for addition ( add_values(a, b) ): float wins outright; both-integer widens the WIDER operand one tier (capped at 64); decimal (or a mixed int/decimal pair) merges precision/scale via the DuckDB decimal-add rule, then adds two digits of headroom, capped at 38.

public static IArrowType CommonTypeForAddition(IReadOnlyList<IArrowType> types) ;

Widest-of-N-operand promotion for varargs addition ( sum_values(…) ): scans left to right, floating wins immediately, otherwise keeps the widest integer seen, then applies PromoteForAddition to the final widest type.

public static IArrowType PromoteForAddition(IArrowType type) ;

Promotes a single input type one tier up — the rule double(value) uses.

public static bool IsAddable(IArrowType type) ;
public static bool IsFloating(IArrowType type) ;
public static bool IsInteger(IArrowType type) ;
public static bool IsNumeric(IArrowType type) ;