pub enum Expr {
Column(ColumnBinding),
Constant(ValueRef),
Cast {
input: ExprRef,
try_cast: bool,
},
Compare {
op: CompareOp,
left: ExprRef,
right: ExprRef,
},
Conjunction {
op: ConjunctionOp,
children: Slice,
},
Function {
name: StrRef,
args: Slice,
},
Aggregate {
name: StrRef,
args: Slice,
distinct: bool,
filter: Option<ExprRef>,
},
Window {
name: StrRef,
args: Slice,
distinct: bool,
filter: Option<ExprRef>,
ignore_nulls: bool,
order: Slice,
},
Case {
arms: Slice,
otherwise: Option<ExprRef>,
},
Lambda {
table: u32,
params: Slice,
body: ExprRef,
},
LambdaParam(ColumnBinding),
}Expand description
One bound expression.
The type of an expression is not in here. It lives in a parallel vector in Plan, indexed by
the same ExprRef, because a LogicalType owns a Vec for its nested cases and putting
one inside every variant would make the common variants three times larger for the benefit of
the rare ones.
Variants§
Column(ColumnBinding)
A reference to a column of some operator’s output.
Constant(ValueRef)
A literal, folded constant, or bound parameter value.
Cast
A cast to the expression’s own type.
The target is the type stored for this expression, not a second copy of it, so there is no way for a cast to disagree with its own result type.
Fields
Compare
A binary comparison.
Conjunction
An AND or OR over two or more operands.
Flat rather than binary, because filter pushdown splits a conjunction into its parts and a
right-leaning tree of two-argument ANDs makes that a recursion instead of a loop.
Fields
op: ConjunctionOpWhich connective.
Function
A scalar function, already resolved to one overload by the binder.
The name is the resolved function’s name and not the name the user wrote, so a + b is a
call to + and an alias in the catalog has already been followed.
Fields
Aggregate
An aggregate function.
An aggregate appears only as a direct element of Node::Aggregate’s aggregate list.
Anything downstream that wants the result refers to it with a ColumnBinding into the
aggregate’s table index, which is why that node has one. Plan::validate checks this,
and the textual form relies on it: an aggregate and a scalar function print the same way,
and it is the slot they are printed in that says which is which.
Fields
Window
A window function, evaluated by the Node::Window that lists it.
Fields
order: SliceThe order the call reads the rows of its frame in, into the sort key pool, empty when
the call wrote no ORDER BY inside its brackets.
This is not the window’s own ordering. The one in the OVER lays the partition out and
decides which rows are in the frame at all, and this one decides what order the call
sees them in once they are, which is why first_value(v ORDER BY v DESC) is the largest
v in the frame and not the first row of it.
Case
A searched CASE.
There is no simple CASE here. CASE x WHEN 1 THEN ... is rewritten to the searched form
by the binder, because two representations of one thing is two code paths in every pass
that touches either.
Fields
Lambda
A function written inline, which is only ever an argument of a function that takes one,
such as the second argument of list_transform.
Its parameters are bound as the columns of a table of their own, numbered the way an
operator’s output is, and read with Expr::LambdaParam. The type recorded for it is its
body’s, since there is no type for a function and the one its caller needs is the body’s.
Fields
LambdaParam(ColumnBinding)
One parameter of an enclosing Expr::Lambda.
Not an Expr::Column, although the body reads it the same way when it runs, because no
operator produces it. A pass that moves, prunes or renumbers columns has to be able to tell
one apart from a column without knowing which lambda it is inside, and a variant of its own
is what lets it.