// Logical AST produced by the subset parser. The binder lowers this
// to column-index based physical expressions (see binder.mbt).
///|
pub(all) enum AggFn {
Sum
Avg
Count // count(expr): counts non-null inputs
CountStar // count(*): counts rows
CountDistinct
SdSamp // stddev / stddev_samp
SdPop // stddev_pop
StringAgg // string_agg(value, sep): sep folded to a literal at parse
VarSamp // variance / var_samp
VarPop // var_pop
Median
Min
Max
} derive(Eq, Debug)
///|
pub extend AggFn with Eq::{equal, not_equal}
///|
pub extend AggFn with @debug.Debug::{to_repr}
///|
pub(all) enum ExtractField {
Year
Month
Day
} derive(Eq, Debug)
///|
pub extend ExtractField with Eq::{equal, not_equal}
///|
pub extend ExtractField with @debug.Debug::{to_repr}
///|
/// INTERVAL literal unit (`interval '90' day`); only date arithmetic
/// consumes it.
pub(all) enum IntervalUnit {
Days
Months
Years
} derive(Eq, Debug)
///|
pub extend IntervalUnit with Eq::{equal, not_equal}
///|
pub extend IntervalUnit with @debug.Debug::{to_repr}
///|
pub(all) enum LExpr {
Col(String)
ColQ(String, String) // qualifier.name (table name or alias)
Lit(@types.Scalar)
Arith(@types.ArithOp, LExpr, LExpr)
Cmp(@types.CmpOp, LExpr, LExpr)
And(LExpr, LExpr)
Or(LExpr, LExpr)
Not(LExpr)
Between(LExpr, LExpr, LExpr) // value, low, high (both inclusive)
In(LExpr, Array[LExpr]) // binder desugars into an OR-chain of equalities
NotIn(LExpr, Array[LExpr]) // desugars into NOT of the In chain
Like(LExpr, LExpr) // pattern must fold to a string constant
NotLike(LExpr, LExpr) // pattern must fold to a string constant
IsNull(LExpr, Bool) // IS NULL (false) / IS NOT NULL (true)
Star // bare `*` as a whole select item: expands to every FROM column
Extract(ExtractField, LExpr) // EXTRACT(year|month|day FROM date)
Case(Array[(LExpr, LExpr)], LExpr?) // searched CASE: (when, then)*, else?
Agg(AggFn, LExpr?) // None only for count(*)
ScalarSub(Select) // non-correlated scalar subquery, folded to a constant
InSelect(LExpr, Select, Bool) // value IN / NOT IN (SELECT ...), non-correlated
Exists(Select, Bool) // [NOT] EXISTS (SELECT ...), non-correlated, folded at bind
Func(String, Array[LExpr]) // scalar function call (name lowercased)
Cast(LExpr, @types.DataType) // CAST(expr AS type)
IntervalLit(Int64, IntervalUnit) // INTERVAL day|month|year
} derive(Eq, Debug)
///|
pub extend LExpr with Eq::{equal, not_equal}
///|
pub extend LExpr with @debug.Debug::{to_repr}
///|
pub(all) struct SelectItem {
expr : LExpr
label : String?
} derive(Eq, Debug)
///|
pub extend SelectItem with Eq::{equal, not_equal}
///|
pub extend SelectItem with @debug.Debug::{to_repr}
///|
pub(all) struct OrderItem {
key : LExpr
desc : Bool
nulls_first : Bool? // None = engine default (NULLS LAST)
} derive(Eq, Debug)
///|
pub extend OrderItem with Eq::{equal, not_equal}
///|
pub extend OrderItem with @debug.Debug::{to_repr}
///|
/// How a FROM item attaches to the accumulated rows before it. The
/// first item's kind is meaningless (Inner, ignored).
pub(all) enum JoinKind {
Inner // comma lists and JOIN ... ON
Left // LEFT [OUTER] JOIN ... ON
Right // RIGHT [OUTER] JOIN ... ON: preserves the joining table
Full // FULL [OUTER] JOIN ... ON: preserves both sides
Semi // synthetic: correlated EXISTS decorrelated by the binder
Anti // synthetic: correlated NOT IN decorrelated: a NULL probe key is UNKNOWN and drops the row
AntiLoose // synthetic: correlated NOT EXISTS: only a match drops the row
Cross // CROSS JOIN
} derive(Eq, Debug)
///|
pub extend JoinKind with Eq::{equal, not_equal}
///|
pub extend JoinKind with @debug.Debug::{to_repr}
///|
pub(all) enum TableRef {
Named(String) // catalog table
Sub(Select) // derived table: FROM ( SELECT ... ) AS alias
} derive(Eq, Debug)
///|
pub extend TableRef with Eq::{equal, not_equal}
///|
pub extend TableRef with @debug.Debug::{to_repr}
///|
pub(all) struct FromItem {
table : TableRef
tbl_alias : String? // `tbl name` / `tbl AS name`; column qualifier
col_aliases : Array[String]? // derived-table column list: AS t (a, b)
join : JoinKind
on : LExpr? // ON condition for explicit joins
} derive(Eq, Debug)
///|
pub extend FromItem with Eq::{equal, not_equal}
///|
pub extend FromItem with @debug.Debug::{to_repr}
///|
/// The function of one window definition. Agg carries the aggregate
/// name with its input (None only for count(*)); the parser only lets
/// aggregates and the three ranking functions take OVER.
pub(all) enum WinFn {
RowNumber
Rank
DenseRank
Agg(AggFn, LExpr?)
} derive(Eq, Debug)
///|
pub extend WinFn with Eq::{equal, not_equal}
///|
pub extend WinFn with @debug.Debug::{to_repr}
///|
/// One `fn(...) OVER (PARTITION BY ... ORDER BY ...)` definition in the
/// select list. The select item itself carries an index marker; the
/// binder lowers the spec against the item's binding space.
pub(all) struct WindowSpec {
fn_ : WinFn
partition : Array[LExpr]
order : Array[(LExpr, Bool, Bool?)] // expr, desc, nulls_first
} derive(Eq, Debug)
///|
pub extend WindowSpec with Eq::{equal, not_equal}
///|
pub extend WindowSpec with @debug.Debug::{to_repr}
///|
/// W2 subset: the full select pipeline over a FROM chain joined in
/// written order (left-deep; comma lists behave as INNER joins with the
/// join conditions supplied by WHERE).
pub(all) struct Select {
from : Array[FromItem]
filter : LExpr?
group_by : Array[LExpr]
having : LExpr?
items : Array[SelectItem]
windows : Array[WindowSpec] // select-list window definitions, index = marker index
order_by : Array[OrderItem]
limit : Int32?
offset : Int32? // rows skipped before LIMIT applies
distinct : Bool // SELECT DISTINCT: dedupe the projected rows
setop : (SetOpKind, Bool, Select)? // setop right; bool = ALL
} derive(Eq, Debug)
///|
/// The set-operation kind joining a select into the chain before it.
pub(all) enum SetOpKind {
Union
Intersect
Except
} derive(Eq, Debug)
///|
pub extend SetOpKind with Eq::{equal, not_equal}
///|
pub extend SetOpKind with @debug.Debug::{to_repr}
///|
pub extend Select with Eq::{equal, not_equal}
///|
pub extend Select with @debug.Debug::{to_repr}