Skip to main content

alopex_sql/ast/
expr.rs

1use super::ddl::DataType;
2use super::dml::OrderByExpr;
3use super::span::{Span, Spanned};
4use serde::{Deserialize, Serialize};
5
6pub(crate) const INTERNAL_TRUTH_TRUE: &str = "__alopex_truth_true";
7pub(crate) const INTERNAL_TRUTH_FALSE: &str = "__alopex_truth_false";
8pub(crate) const INTERNAL_TRUTH_UNKNOWN: &str = "__alopex_truth_unknown";
9pub(crate) const INTERNAL_ROW_EQ: &str = "__alopex_row_eq";
10pub(crate) const INTERNAL_ROW_NEQ: &str = "__alopex_row_neq";
11pub(crate) const INTERNAL_ROW_LT: &str = "__alopex_row_lt";
12pub(crate) const INTERNAL_ROW_LTEQ: &str = "__alopex_row_lteq";
13pub(crate) const INTERNAL_ROW_GT: &str = "__alopex_row_gt";
14pub(crate) const INTERNAL_ROW_GTEQ: &str = "__alopex_row_gteq";
15pub(crate) const INTERNAL_ROW_DISTINCT: &str = "__alopex_row_distinct";
16pub(crate) const INTERNAL_ROW_BETWEEN: &str = "__alopex_row_between";
17pub(crate) const INTERNAL_ROW_IN: &str = "__alopex_row_in";
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Expr {
21    pub kind: ExprKind,
22    pub span: Span,
23}
24
25impl Expr {
26    pub fn new(kind: ExprKind, span: Span) -> Self {
27        Self { kind, span }
28    }
29}
30
31impl Spanned for Expr {
32    fn span(&self) -> Span {
33        self.span
34    }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38#[serde(tag = "variant")]
39#[allow(clippy::large_enum_variant)]
40pub enum ExprKind {
41    Literal {
42        literal: Literal,
43    },
44    ColumnRef {
45        table: Option<String>,
46        column: String,
47    },
48    BinaryOp {
49        left: Box<Expr>,
50        op: BinaryOp,
51        right: Box<Expr>,
52    },
53    UnaryOp {
54        op: UnaryOp,
55        operand: Box<Expr>,
56    },
57    Case {
58        operand: Option<Box<Expr>>,
59        branches: Vec<CaseWhen>,
60        else_expr: Option<Box<Expr>>,
61    },
62    FunctionCall {
63        name: String,
64        args: Vec<Expr>,
65        distinct: bool,
66        star: bool,
67        /// Aggregate-local ordering from `agg(expr ORDER BY ...)` (issue #148).
68        #[serde(default)]
69        order_by: Vec<OrderByExpr>,
70        /// Ordered-set aggregate ordering from `WITHIN GROUP (ORDER BY ...)`.
71        #[serde(default)]
72        within_group: Vec<OrderByExpr>,
73        /// Aggregate row filter from `FILTER (WHERE predicate)`.
74        #[serde(default)]
75        filter: Option<Box<Expr>>,
76        #[serde(default)]
77        over: Option<WindowSpec>,
78    },
79    Cast {
80        expr: Box<Expr>,
81        target_type: DataType,
82    },
83    /// A cast that returns NULL when conversion is impossible.
84    TryCast {
85        expr: Box<Expr>,
86        target_type: DataType,
87    },
88    Between {
89        expr: Box<Expr>,
90        low: Box<Expr>,
91        high: Box<Expr>,
92        negated: bool,
93    },
94    Like {
95        expr: Box<Expr>,
96        pattern: Box<Expr>,
97        escape: Option<Box<Expr>>,
98        negated: bool,
99        #[serde(default)]
100        kind: PatternMatchKind,
101    },
102    InList {
103        expr: Box<Expr>,
104        list: Vec<Expr>,
105        negated: bool,
106    },
107    IsNull {
108        expr: Box<Expr>,
109        negated: bool,
110    },
111    /// A parenthesized row-value constructor used by row predicates.
112    Row {
113        items: Vec<Expr>,
114    },
115    /// `IS [NOT] TRUE/FALSE/UNKNOWN`.
116    TruthPredicate {
117        expr: Box<Expr>,
118        value: TruthValue,
119        negated: bool,
120    },
121    /// Null-safe scalar or row equality.
122    IsDistinctFrom {
123        left: Box<Expr>,
124        right: Box<Expr>,
125        negated: bool,
126    },
127    VectorLiteral {
128        values: Vec<f64>,
129    },
130    ScalarSubquery {
131        subquery: Box<super::Statement>,
132    },
133    InSubquery {
134        expr: Box<Expr>,
135        subquery: Box<super::Statement>,
136        negated: bool,
137    },
138    Exists {
139        subquery: Box<super::Statement>,
140        negated: bool,
141    },
142    Quantified {
143        expr: Box<Expr>,
144        op: BinaryOp,
145        quantifier: Quantifier,
146        subquery: Box<super::Statement>,
147    },
148}
149
150/// A window specification attached to a function call through `OVER name` or
151/// `OVER (...)`.
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct WindowSpec {
154    /// Optional named specification inherited by this window.
155    #[serde(default)]
156    pub base: Option<String>,
157    #[serde(default)]
158    pub partition_by: Vec<Expr>,
159    #[serde(default)]
160    pub order_by: Vec<OrderByExpr>,
161    /// Optional explicit frame. `None` selects the SQL implicit frame.
162    #[serde(default)]
163    pub frame: Option<WindowFrame>,
164}
165
166/// An explicit SQL window frame.
167#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
168pub struct WindowFrame {
169    pub units: WindowFrameUnits,
170    pub start_bound: WindowFrameBound,
171    pub end_bound: WindowFrameBound,
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
175pub enum WindowFrameUnits {
176    Rows,
177    Range,
178}
179
180#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
181#[serde(tag = "variant", content = "value")]
182pub enum WindowFrameBound {
183    UnboundedPreceding,
184    Preceding(u64),
185    CurrentRow,
186    Following(u64),
187    UnboundedFollowing,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct CaseWhen {
192    pub when: Expr,
193    pub then: Expr,
194}
195
196#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
197pub enum PatternMatchKind {
198    #[default]
199    Like,
200    ILike,
201    Glob,
202    SimilarTo,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
206#[serde(tag = "variant", content = "value")]
207pub enum Literal {
208    Number(String),
209    String(String),
210    Boolean(bool),
211    Null,
212    /// SQL-TS interval text, preserved for a downstream semantic layer.
213    ///
214    /// Appended to preserve existing bincode discriminants.
215    Interval(String),
216}
217
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
219pub enum BinaryOp {
220    Add,
221    Sub,
222    Mul,
223    Div,
224    Mod,
225    Eq,
226    Neq,
227    Lt,
228    Gt,
229    LtEq,
230    GtEq,
231    And,
232    Or,
233    StringConcat,
234    BitAnd,
235    BitOr,
236    BitXor,
237    ShiftLeft,
238    ShiftRight,
239}
240
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
242pub enum UnaryOp {
243    Not,
244    Minus,
245    BitNot,
246}
247
248#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
249pub enum TruthValue {
250    True,
251    False,
252    Unknown,
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
256pub enum Quantifier {
257    Any,
258    All,
259}