pub enum PipeOperator<X: Extension = NoExt> {
Show 16 variants
Where {
predicate: Expr<X>,
meta: Meta,
},
Select {
items: ThinVec<SelectItem<X>>,
meta: Meta,
},
Extend {
items: ThinVec<SelectItem<X>>,
meta: Meta,
},
As {
alias: TableAlias,
meta: Meta,
},
OrderBy {
keys: ThinVec<OrderByExpr<X>>,
meta: Meta,
},
Limit {
count: Box<Expr<X>>,
offset: Option<Box<Expr<X>>>,
meta: Meta,
},
Join {
join: Box<Join<X>>,
meta: Meta,
},
SetOperation {
op: SetOperator,
quantifier: Option<SetQuantifier>,
queries: ThinVec<Query<X>>,
meta: Meta,
},
Set {
assignments: ThinVec<UpdateAssignment<X>>,
meta: Meta,
},
Call {
call: Box<FunctionCall<X>>,
alias: Option<Box<TableAlias>>,
meta: Meta,
},
Aggregate {
aggregates: ThinVec<PipeAggregateExpr<X>>,
group_by: ThinVec<PipeAggregateExpr<X>>,
meta: Meta,
},
Drop {
columns: ThinVec<Ident>,
meta: Meta,
},
Rename {
renames: ThinVec<PipeRenameItem>,
meta: Meta,
},
Pivot {
aggregates: ThinVec<PivotExpr<X>>,
column: Box<PivotColumn<X>>,
meta: Meta,
},
Unpivot {
value: ThinVec<Ident>,
name: ThinVec<Ident>,
columns: ThinVec<UnpivotColumn<X>>,
meta: Meta,
},
TableSample {
sample: Box<TableSample<X>>,
meta: Meta,
},
}Expand description
One BigQuery/ZetaSQL |> pipe operator applied to a query result.
Each variant is one |> <KEYWORD> … step; a Query holds a list of
them applied left to right. Generic over the extension parameter X because most
operators carry expressions.
Variants§
Where
|> WHERE <predicate> — keep only the rows for which predicate holds.
The framework’s reference operator: the minimal single-expression body, mirroring
an ordinary WHERE clause’s one predicate. Its parse/render/test wiring is the
template every later operator arm follows.
Fields
Select
|> SELECT <select-items> — replace the current row shape with a new projection.
Reuses SelectItem, the ordinary SELECT-list item shape (an
expression with an optional alias, or a * / t.* wildcard), so a pipe projection
and a leading SELECT list carry identical nodes. ZetaSQL’s |> SELECT also admits
the DISTINCT and AS STRUCT | VALUE modifiers; those modifiers are intentionally
absent from this item-only shape.
Fields
items: ThinVec<SelectItem<X>>Child items in source order.
Extend
|> EXTEND <select-items> — append computed columns to the current row shape.
The same operand shape as Select (SelectItem):
the difference is semantic — EXTEND keeps the existing columns and adds these, where
SELECT replaces them — not structural, so the two share the item node rather than a
parallel copy.
Fields
items: ThinVec<SelectItem<X>>Child items in source order.
As
|> AS <alias> — bind a range-variable name (table alias) to the current result.
Reuses TableAlias, the correlation-name shape a FROM item
carries. ZetaSQL’s |> AS names only the range variable — it has no column-alias list
— so the reused node always carries an empty
columns: the parser never populates it, and a trailing
(a, b) is left unconsumed for the caller to reject.
Fields
alias: TableAliasAlias assigned by this syntax.
OrderBy
|> ORDER BY <sort-keys> — sort the current result.
Reuses OrderByExpr, the ordinary query ORDER BY sort-key
shape (<expr> [ASC | DESC | USING <op>] [NULLS FIRST | LAST]), so a pipe sort and a
query-tail sort carry identical keys.
Fields
keys: ThinVec<OrderByExpr<X>>keys in source order.
Limit
|> LIMIT <count> [OFFSET <skip>] — bound the current result to count rows,
optionally skipping the first skip.
The narrow ZetaSQL pipe form: a required row-count expression and an optional OFFSET
skip expression, both restricted to the ordinary LIMIT-operand grammar (an integer
literal or a ? placeholder). It deliberately does not reuse the full
Limit clause node — the pipe form has no FETCH FIRST, PERCENT,
WITH TIES, or MySQL LIMIT a, b spelling — so it models only the two operands the
surface carries rather than widening onto the clause shape.
The two Expr operands are boxed (unlike the reference Where’s
single inline predicate): a two-Expr inline payload would be the lone fat variant of
an otherwise-small enum whose common variants hold a one-word ThinVec, so ADR-0007’s
skew rule boxes it to keep PipeOperator lean — the allocation is paid only on the
rare pipe-LIMIT path.
Fields
Join
|> [<join-type>] JOIN <relation> [ON <predicate> | USING (<cols>)] — join the
current result to another relation.
Reuses the ordinary Join node wholesale (its
relation table factor, its
operator side/kind spelling, and the embedded
ON/USING constraint), so a pipe join and a FROM-clause join carry identical
nodes — the pipe form admits exactly the join grammar the dialect’s join parser
admits, nothing invented here. The whole Join is boxed (it is a 176-byte node,
far past PipeOperator’s 56-byte budget); the allocation is paid only on the
pipe-join path, exactly as Limit boxes its operands (ADR-0007).
Fields
SetOperation
|> {UNION | INTERSECT | EXCEPT} [ALL | DISTINCT] (<query>) [, (<query>) …] —
combine the current result with one or more parenthesized queries under a set
operation.
One variant carries the SetOperator tag rather than three
operator-named variants — reusing the same op: SetOperator shape the ordinary
query set operation (SetExpr::SetOperation) uses, so the three
pipe set operations share this node exactly as the three query set operations share
theirs. The quantifier is
Optional — None renders the bare operator, Some the explicit ALL/DISTINCT
— capturing all three surfaces for an exact round-trip (unlike the query set op’s
all: bool, which cannot distinguish a bare operator from an explicit DISTINCT).
The operand queries live in the ThinVec’s heap
buffer, so this variant costs only that one-word pointer inline.
Fields
op: SetOperatorOperator applied by this expression.
quantifier: Option<SetQuantifier>Optional quantifier for this syntax.
Set
|> SET <column> = <expr> [, …] — replace named columns of the current row shape
with new expressions.
Reuses UpdateAssignment, the UPDATE … SET assignment
node, but the parser builds only its Single
<column> = <expr> form: the ZetaSQL pipe surface has no multiple-column
( … ) = <source> tuple assignment and no DEFAULT right-hand side, so those
arms of the reused node are never populated here (one shape per construct, no
parallel copy).
Fields
assignments: ThinVec<UpdateAssignment<X>>assignments in source order.
Call
|> CALL <function>(<args>) [AS <alias>] — apply a table-valued function to the
current result, optionally binding a range-variable name to the output.
Reuses FunctionCall, the ordinary call node, for
<function>(<args>) (boxed — it is a 120-byte node, past the budget). The optional
trailing alias reuses TableAlias name-only, exactly as
As does: the pipe AS <alias> names a range variable with no
column-alias list, so columns is always empty and a
trailing (a, b) is left to reject. The alias is boxed because the variant already
carries the boxed call (an inline TableAlias would push it past the budget).
Fields
call: Box<FunctionCall<X>>The table-function call applied to the pipe input; see FunctionCall.
alias: Option<Box<TableAlias>>Alias assigned by this syntax.
Aggregate
|> AGGREGATE <aggregates> [GROUP BY <keys>] — collapse the current result into
aggregate rows, optionally grouped by the trailing keys.
Both lists carry PipeAggregateExpr — an expression with an optional output
alias and an optional ASC/DESC + NULLS FIRST/LAST ordering suffix,
matching sqlparser-rs’s single ExprWithAliasAndOrderBy shape for the two
lists (its full_table_exprs / group_by_expr). ZetaSQL’s pipe AGGREGATE folds
grouping and the aggregate-driven “GROUP AND ORDER BY” ordering into one operator,
so an aggregate or a grouping key may each name its own sort direction; a
dedicated combined item is used because neither SelectItem
(alias, no ordering) nor GroupByItem (grouping semantics,
no alias/ordering) carries both. The aggregates
list is empty for a grouping-only |> AGGREGATE GROUP BY x; the
group_by list is empty when no GROUP BY is
written. The GROUP AND ORDER BY keyword spelling and the bare (AS-less) item
alias are intentionally absent from this shape.
Fields
aggregates: ThinVec<PipeAggregateExpr<X>>aggregates in source order.
group_by: ThinVec<PipeAggregateExpr<X>>Grouping terms in source order.
Drop
|> DROP <column> [, …] — remove named columns from the current row shape.
The columns are a bare Ident list, not
ObjectNames: ZetaSQL’s DROP names output columns of the
current table by their unqualified name, so a qualified t.c has no meaning here.
Fields
Rename
|> RENAME <old> AS <new> [, …] — rename columns of the current row shape.
Each mapping is a PipeRenameItem pair of bare identifiers, kept distinct from a
projection alias (SelectItem::Expr’s alias): a rename
keeps the column’s value and changes only its name, where a projection alias names
a computed item. A dedicated two-Ident shape is used rather than
the DuckDB wildcard-modifier WildcardRename, whose source
is a qualifiable ObjectName and which belongs to the * RENAME (…) surface — reusing it here would both over-accept a qualified source and
conflate two unrelated features.
Fields
renames: ThinVec<PipeRenameItem>renames in source order.
Pivot
|> PIVOT (<aggregates> FOR <column> IN (<values>)) — rotate the distinct values
of one pivot column into columns, aggregating each cell.
Reuses the shared pivot sub-shapes — PivotExpr for the
aggregate list and PivotColumn for the single FOR <column> IN (<values>) head — rather than the whole Pivot node: the pipe
operator has no source relation (it pivots the pipe input) and none of the
statement-only WITH/ORDER BY/LIMIT tail, so it carries only the parenthesized
body’s two operands, keeping the table-factor PIVOT and the pipe PIVOT
unconflated. Exactly one FOR column (ZetaSQL admits no second head), and the
aggregate list is non-empty. The column is boxed — it
carries an Expr and would otherwise widen the variant past the
budget — while the aggregates ride the ThinVec’s heap buffer.
Fields
column: Box<PivotColumn<X>>Column referenced by this syntax.
Unpivot
|> UNPIVOT (<value> FOR <name> IN (<columns>)) — collapse a set of columns into
name/value row pairs (the inverse of Pivot).
Reuses the shared UnpivotColumn sub-shape for the IN
list and mirrors the Unpivot core’s value/name identifier
lists (each a ThinVec<Ident> so the multi-column (v1, v2) FOR n IN ((a, b), (c, d)) surface reuses one shape), rather than the whole Unpivot node: as with
Pivot the pipe operator has no source and no statement tail, so
it carries only the parenthesized body. The INCLUDE/EXCLUDE NULLS marker is
intentionally absent from this shape.
Fields
value: ThinVec<Ident>The output value column name(s) (<value> before FOR); one for the common
form, several for a multi-column unpivot.
columns: ThinVec<UnpivotColumn<X>>Columns in source order.
TableSample
|> TABLESAMPLE <method> (<args>) [REPEATABLE (<seed>)] — sample the current
result.
Reuses the whole TableSample node (the FROM-clause
sampling suffix), boxed — it is a wide node past the budget, and the allocation is
paid only on the pipe-sample path, exactly as Join boxes its reused
node. The pipe form admits precisely the argument grammar the table-factor
TABLESAMPLE admits (a bare numeric percentage rather than the BigQuery
PERCENT/ROWS unit keyword, which the reused shape has no field for).
Fields
sample: Box<TableSample<X>>The TABLESAMPLE clause; see TableSample.
Trait Implementations§
Source§impl<X: Clone + Extension> Clone for PipeOperator<X>
impl<X: Clone + Extension> Clone for PipeOperator<X>
Source§fn clone(&self) -> PipeOperator<X>
fn clone(&self) -> PipeOperator<X>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<'de, X> Deserialize<'de> for PipeOperator<X>where
X: Deserialize<'de> + Extension,
impl<'de, X> Deserialize<'de> for PipeOperator<X>where
X: Deserialize<'de> + Extension,
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl<X: Eq + Extension> Eq for PipeOperator<X>
Source§impl<X: Extension + Render> Render for PipeOperator<X>
impl<X: Extension + Render> Render for PipeOperator<X>
Source§fn render(&self, ctx: &RenderCtx<'_>, f: &mut Formatter<'_>) -> Result
fn render(&self, ctx: &RenderCtx<'_>, f: &mut Formatter<'_>) -> Result
Source§fn operand_binding_power(&self) -> Option<BindingPower>
fn operand_binding_power(&self) -> Option<BindingPower>
None (the default) for a self-delimiting node — an atom, call, or
constructor — that never needs parentheses. Read moreSource§impl<X> Serialize for PipeOperator<X>
impl<X> Serialize for PipeOperator<X>
Source§impl<X: Extension> Spanned for PipeOperator<X>
impl<X: Extension> Spanned for PipeOperator<X>
impl<X: PartialEq + Extension> StructuralPartialEq for PipeOperator<X>
Auto Trait Implementations§
impl<X> Freeze for PipeOperator<X>where
X: Freeze,
impl<X> RefUnwindSafe for PipeOperator<X>where
X: RefUnwindSafe,
impl<X> Send for PipeOperator<X>where
X: Send,
impl<X> Sync for PipeOperator<X>where
X: Sync,
impl<X> Unpin for PipeOperator<X>where
X: Unpin,
impl<X> UnsafeUnpin for PipeOperator<X>where
X: UnsafeUnpin,
impl<X> UnwindSafe for PipeOperator<X>where
X: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> DynAstExt for T
impl<T> DynAstExt for T
Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&dyn Any for downcasting a node back to its concrete type.Source§fn dyn_clone(&self) -> Box<dyn DynAstExt>
fn dyn_clone(&self) -> Box<dyn DynAstExt>
Clone (whose
Self-returning signature cannot go through a vtable).Source§fn dyn_eq(&self, other: &dyn DynAstExt) -> bool
fn dyn_eq(&self, other: &dyn DynAstExt) -> bool
PartialEq (whose &Self argument cannot go through a vtable). Equal
iff other holds the same concrete type and that type deems the values
equal; differently-typed nodes are never equal.