// 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
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}
///|
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
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
} 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
} 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
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
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}
///|
/// 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]
order_by : Array[OrderItem]
limit : Int?
} derive(Eq, Debug)
///|
pub extend Select with Eq::{equal, not_equal}
///|
pub extend Select with @debug.Debug::{to_repr}