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
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Expr {
8    pub kind: ExprKind,
9    pub span: Span,
10}
11
12impl Expr {
13    pub fn new(kind: ExprKind, span: Span) -> Self {
14        Self { kind, span }
15    }
16}
17
18impl Spanned for Expr {
19    fn span(&self) -> Span {
20        self.span
21    }
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25#[serde(tag = "variant")]
26#[allow(clippy::large_enum_variant)]
27pub enum ExprKind {
28    Literal {
29        literal: Literal,
30    },
31    ColumnRef {
32        table: Option<String>,
33        column: String,
34    },
35    BinaryOp {
36        left: Box<Expr>,
37        op: BinaryOp,
38        right: Box<Expr>,
39    },
40    UnaryOp {
41        op: UnaryOp,
42        operand: Box<Expr>,
43    },
44    Case {
45        operand: Option<Box<Expr>>,
46        branches: Vec<CaseWhen>,
47        else_expr: Option<Box<Expr>>,
48    },
49    FunctionCall {
50        name: String,
51        args: Vec<Expr>,
52        distinct: bool,
53        star: bool,
54        #[serde(default)]
55        over: Option<WindowSpec>,
56    },
57    Cast {
58        expr: Box<Expr>,
59        target_type: DataType,
60    },
61    Between {
62        expr: Box<Expr>,
63        low: Box<Expr>,
64        high: Box<Expr>,
65        negated: bool,
66    },
67    Like {
68        expr: Box<Expr>,
69        pattern: Box<Expr>,
70        escape: Option<Box<Expr>>,
71        negated: bool,
72        #[serde(default)]
73        kind: PatternMatchKind,
74    },
75    InList {
76        expr: Box<Expr>,
77        list: Vec<Expr>,
78        negated: bool,
79    },
80    IsNull {
81        expr: Box<Expr>,
82        negated: bool,
83    },
84    VectorLiteral {
85        values: Vec<f64>,
86    },
87    ScalarSubquery {
88        subquery: Box<super::Statement>,
89    },
90    InSubquery {
91        expr: Box<Expr>,
92        subquery: Box<super::Statement>,
93        negated: bool,
94    },
95    Exists {
96        subquery: Box<super::Statement>,
97        negated: bool,
98    },
99    Quantified {
100        expr: Box<Expr>,
101        op: BinaryOp,
102        quantifier: Quantifier,
103        subquery: Box<super::Statement>,
104    },
105}
106
107/// A window specification attached to a function call through `OVER (...)`.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct WindowSpec {
110    #[serde(default)]
111    pub partition_by: Vec<Expr>,
112    #[serde(default)]
113    pub order_by: Vec<OrderByExpr>,
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct CaseWhen {
118    pub when: Expr,
119    pub then: Expr,
120}
121
122#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
123pub enum PatternMatchKind {
124    #[default]
125    Like,
126    ILike,
127    Glob,
128    SimilarTo,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
132#[serde(tag = "variant", content = "value")]
133pub enum Literal {
134    Number(String),
135    String(String),
136    Boolean(bool),
137    Null,
138    /// SQL-TS interval text, preserved for a downstream semantic layer.
139    ///
140    /// Appended to preserve existing bincode discriminants.
141    Interval(String),
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
145pub enum BinaryOp {
146    Add,
147    Sub,
148    Mul,
149    Div,
150    Mod,
151    Eq,
152    Neq,
153    Lt,
154    Gt,
155    LtEq,
156    GtEq,
157    And,
158    Or,
159    StringConcat,
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
163pub enum UnaryOp {
164    Not,
165    Minus,
166}
167
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
169pub enum Quantifier {
170    Any,
171    All,
172}