Skip to content

yggdrasil.execution.expr.builder

builder

Fluent factory functions for the expression AST.

Users build trees with :func:col plus operator overloads (the :class:Expression base carries them) and the named methods on :class:Expression for the rare cases where the operator is spelled with a Python keyword (is_in, between, …).

Example

::

from yggdrasil.execution.expr import col, lit

p = (col("price") >= 100) & col("side").is_in(["buy", "sell"])
p.to_sql()       # SQL string
p.to_python()    # Callable[[Mapping], bool]
p.to_pyarrow()   # pa.compute.Expression

The factory accepts an optional :class:Field so backends that need typed literals (Spark casts, Arrow scalars) have everything they need without an extra dtype argument at call sites.

Projections (rename + cast-on-select) live on :class:yggdrasil.data.data_field.Field directly — there's no separate selector node. Build a Field with the desired output :attr:name, optional :attr:alias for the source-side label, and target :attr:dtype, then pass it to Tabular.select or the SQL executor's statement.select list.

col

col(
    name: "str | Field",
    *,
    field: "Field | None" = None,
    alias: "str | None" = None,
    qualifier: "str | None" = None,
    dtype: "Any | None" = None
) -> Column

Build a :class:Column reference.

name is the column identifier; pass a pre-built :class:Field here to reuse the typed metadata (the bound dtype, nullability, children, …). dtype is the convenience knob for the common "I know the column type" case — when omitted the (synthesised) field's dtype defaults to :class:ObjectType so backends fall back to engine-side inference.

alias adds a column-level rename so emitters render foo AS bar. qualifier adds the table-level T.col addressing used by aliased SQL / MERGE rewrites. Both live on the :class:Column itself — :class:Field stays as origin metadata only.

field= is the explicit entry: when the caller already has a :class:Field instance, hand it in directly and the builder skips the construction. field and dtype are mutually exclusive — the field's dtype wins if both are supplied.

neg

neg(expr: Expression) -> Not

Return NOT expr. Same as ~expr but explicit.

all_of

all_of(*operands: Any) -> Logical

Conjunction over an arbitrary number of operands.

Equivalent to chaining a & b & c but produces a flat :class:Logical instead of a left-leaning tree — useful when callers know the conjunction is commutative and want the cheaper round-trip.

any_of

any_of(*operands: Any) -> Logical

Disjunction over an arbitrary number of operands.