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}
235
236#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
237pub enum UnaryOp {
238    Not,
239    Minus,
240}
241
242#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
243pub enum TruthValue {
244    True,
245    False,
246    Unknown,
247}
248
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
250pub enum Quantifier {
251    Any,
252    All,
253}