Skip to main content

oxigdal_query/parser/
ast.rs

1//! Abstract Syntax Tree definitions for query language.
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6/// A complete query statement.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub enum Statement {
9    /// SELECT query.
10    Select(SelectStatement),
11}
12
13/// A SELECT statement.
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
15pub struct SelectStatement {
16    /// Projection list.
17    pub projection: Vec<SelectItem>,
18    /// FROM clause.
19    pub from: Option<TableReference>,
20    /// WHERE clause.
21    pub selection: Option<Expr>,
22    /// GROUP BY clause.
23    pub group_by: Vec<Expr>,
24    /// HAVING clause.
25    pub having: Option<Expr>,
26    /// ORDER BY clause.
27    pub order_by: Vec<OrderByExpr>,
28    /// LIMIT clause.
29    pub limit: Option<usize>,
30    /// OFFSET clause.
31    pub offset: Option<usize>,
32}
33
34/// A select item in the projection list.
35#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
36pub enum SelectItem {
37    /// Wildcard (*).
38    Wildcard,
39    /// Qualified wildcard (table.*).
40    QualifiedWildcard(String),
41    /// Expression with optional alias.
42    Expr {
43        /// The expression to select.
44        expr: Expr,
45        /// Optional alias for the expression.
46        alias: Option<String>,
47    },
48}
49
50/// A table reference in FROM clause.
51#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
52pub enum TableReference {
53    /// Base table.
54    Table {
55        /// Table name.
56        name: String,
57        /// Optional alias.
58        alias: Option<String>,
59    },
60    /// Join.
61    Join {
62        /// Left table.
63        left: Box<TableReference>,
64        /// Right table.
65        right: Box<TableReference>,
66        /// Join type.
67        join_type: JoinType,
68        /// Join condition.
69        on: Option<Expr>,
70    },
71    /// Subquery.
72    Subquery {
73        /// Subquery.
74        query: Box<SelectStatement>,
75        /// Alias.
76        alias: String,
77    },
78}
79
80/// Join type.
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
82pub enum JoinType {
83    /// Inner join.
84    Inner,
85    /// Left outer join.
86    Left,
87    /// Right outer join.
88    Right,
89    /// Full outer join.
90    Full,
91    /// Cross join.
92    Cross,
93}
94
95/// An expression.
96#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
97pub enum Expr {
98    /// Column reference.
99    Column {
100        /// Optional table qualifier.
101        table: Option<String>,
102        /// Column name.
103        name: String,
104    },
105    /// Literal value.
106    Literal(Literal),
107    /// Binary operation.
108    BinaryOp {
109        /// Left operand.
110        left: Box<Expr>,
111        /// Operator.
112        op: BinaryOperator,
113        /// Right operand.
114        right: Box<Expr>,
115    },
116    /// Unary operation.
117    UnaryOp {
118        /// Operator.
119        op: UnaryOperator,
120        /// Operand.
121        expr: Box<Expr>,
122    },
123    /// Function call.
124    Function {
125        /// Function name.
126        name: String,
127        /// Arguments.
128        args: Vec<Expr>,
129    },
130    /// CASE expression.
131    Case {
132        /// Optional operand (for CASE x WHEN ...).
133        operand: Option<Box<Expr>>,
134        /// WHEN conditions and results.
135        when_then: Vec<(Expr, Expr)>,
136        /// ELSE result.
137        else_result: Option<Box<Expr>>,
138    },
139    /// CAST expression.
140    Cast {
141        /// Expression to cast.
142        expr: Box<Expr>,
143        /// Target data type.
144        data_type: DataType,
145    },
146    /// IS NULL.
147    IsNull(Box<Expr>),
148    /// IS NOT NULL.
149    IsNotNull(Box<Expr>),
150    /// IN list.
151    InList {
152        /// Expression.
153        expr: Box<Expr>,
154        /// List of values.
155        list: Vec<Expr>,
156        /// Negated (NOT IN).
157        negated: bool,
158    },
159    /// BETWEEN.
160    Between {
161        /// Expression.
162        expr: Box<Expr>,
163        /// Lower bound.
164        low: Box<Expr>,
165        /// Upper bound.
166        high: Box<Expr>,
167        /// Negated (NOT BETWEEN).
168        negated: bool,
169    },
170    /// Subquery.
171    Subquery(Box<SelectStatement>),
172    /// Wildcard (*).
173    Wildcard,
174}
175
176/// A literal value.
177#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
178pub enum Literal {
179    /// Null value.
180    Null,
181    /// Boolean value.
182    Boolean(bool),
183    /// Integer value.
184    Integer(i64),
185    /// Float value.
186    Float(f64),
187    /// String value.
188    String(String),
189}
190
191/// Binary operator.
192#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
193pub enum BinaryOperator {
194    /// Addition (+).
195    Plus,
196    /// Subtraction (-).
197    Minus,
198    /// Multiplication (*).
199    Multiply,
200    /// Division (/).
201    Divide,
202    /// Modulo (%).
203    Modulo,
204    /// Equality (=).
205    Eq,
206    /// Inequality (<>).
207    NotEq,
208    /// Less than (<).
209    Lt,
210    /// Less than or equal (<=).
211    LtEq,
212    /// Greater than (>).
213    Gt,
214    /// Greater than or equal (>=).
215    GtEq,
216    /// Logical AND.
217    And,
218    /// Logical OR.
219    Or,
220    /// String concatenation (||).
221    Concat,
222    /// LIKE pattern matching (case-sensitive).
223    Like,
224    /// NOT LIKE pattern matching (case-sensitive).
225    NotLike,
226    /// ILIKE pattern matching (case-insensitive).
227    ILike,
228    /// NOT ILIKE pattern matching (case-insensitive).
229    NotILike,
230}
231
232/// Unary operator.
233#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
234pub enum UnaryOperator {
235    /// Negation (-).
236    Minus,
237    /// Logical NOT.
238    Not,
239}
240
241/// ORDER BY expression.
242#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
243pub struct OrderByExpr {
244    /// Expression to order by.
245    pub expr: Expr,
246    /// Ascending or descending.
247    pub asc: bool,
248    /// Nulls first or last.
249    pub nulls_first: bool,
250}
251
252/// Data type.
253#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
254pub enum DataType {
255    /// Boolean.
256    Boolean,
257    /// 8-bit signed integer.
258    Int8,
259    /// 16-bit signed integer.
260    Int16,
261    /// 32-bit signed integer.
262    Int32,
263    /// 64-bit signed integer.
264    Int64,
265    /// 8-bit unsigned integer.
266    UInt8,
267    /// 16-bit unsigned integer.
268    UInt16,
269    /// 32-bit unsigned integer.
270    UInt32,
271    /// 64-bit unsigned integer.
272    UInt64,
273    /// 32-bit float.
274    Float32,
275    /// 64-bit float.
276    Float64,
277    /// UTF-8 string.
278    String,
279    /// Binary data.
280    Binary,
281    /// Timestamp.
282    Timestamp,
283    /// Date.
284    Date,
285    /// Geometry.
286    Geometry,
287}
288
289impl fmt::Display for Statement {
290    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291        match self {
292            Statement::Select(select) => write!(f, "{}", select),
293        }
294    }
295}
296
297impl fmt::Display for SelectStatement {
298    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299        write!(f, "SELECT ")?;
300        for (i, item) in self.projection.iter().enumerate() {
301            if i > 0 {
302                write!(f, ", ")?;
303            }
304            write!(f, "{}", item)?;
305        }
306        if let Some(from) = &self.from {
307            write!(f, " FROM {}", from)?;
308        }
309        if let Some(selection) = &self.selection {
310            write!(f, " WHERE {}", selection)?;
311        }
312        if !self.group_by.is_empty() {
313            write!(f, " GROUP BY ")?;
314            for (i, expr) in self.group_by.iter().enumerate() {
315                if i > 0 {
316                    write!(f, ", ")?;
317                }
318                write!(f, "{}", expr)?;
319            }
320        }
321        if let Some(having) = &self.having {
322            write!(f, " HAVING {}", having)?;
323        }
324        if !self.order_by.is_empty() {
325            write!(f, " ORDER BY ")?;
326            for (i, expr) in self.order_by.iter().enumerate() {
327                if i > 0 {
328                    write!(f, ", ")?;
329                }
330                write!(f, "{}", expr)?;
331            }
332        }
333        if let Some(limit) = self.limit {
334            write!(f, " LIMIT {}", limit)?;
335        }
336        if let Some(offset) = self.offset {
337            write!(f, " OFFSET {}", offset)?;
338        }
339        Ok(())
340    }
341}
342
343impl fmt::Display for SelectItem {
344    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345        match self {
346            SelectItem::Wildcard => write!(f, "*"),
347            SelectItem::QualifiedWildcard(table) => write!(f, "{}.*", table),
348            SelectItem::Expr { expr, alias } => {
349                write!(f, "{}", expr)?;
350                if let Some(alias) = alias {
351                    write!(f, " AS {}", alias)?;
352                }
353                Ok(())
354            }
355        }
356    }
357}
358
359impl fmt::Display for TableReference {
360    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361        match self {
362            TableReference::Table { name, alias } => {
363                write!(f, "{}", name)?;
364                if let Some(alias) = alias {
365                    write!(f, " AS {}", alias)?;
366                }
367                Ok(())
368            }
369            TableReference::Join {
370                left,
371                right,
372                join_type,
373                on,
374            } => {
375                write!(f, "{} {} JOIN {}", left, join_type, right)?;
376                if let Some(on) = on {
377                    write!(f, " ON {}", on)?;
378                }
379                Ok(())
380            }
381            TableReference::Subquery { query, alias } => {
382                write!(f, "({}) AS {}", query, alias)
383            }
384        }
385    }
386}
387
388impl fmt::Display for JoinType {
389    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390        match self {
391            JoinType::Inner => write!(f, "INNER"),
392            JoinType::Left => write!(f, "LEFT"),
393            JoinType::Right => write!(f, "RIGHT"),
394            JoinType::Full => write!(f, "FULL"),
395            JoinType::Cross => write!(f, "CROSS"),
396        }
397    }
398}
399
400impl fmt::Display for Expr {
401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402        match self {
403            Expr::Column { table, name } => {
404                if let Some(table) = table {
405                    write!(f, "{}.{}", table, name)
406                } else {
407                    write!(f, "{}", name)
408                }
409            }
410            Expr::Literal(lit) => write!(f, "{}", lit),
411            Expr::BinaryOp { left, op, right } => {
412                write!(f, "({} {} {})", left, op, right)
413            }
414            Expr::UnaryOp { op, expr } => write!(f, "({} {})", op, expr),
415            Expr::Function { name, args } => {
416                write!(f, "{}(", name)?;
417                for (i, arg) in args.iter().enumerate() {
418                    if i > 0 {
419                        write!(f, ", ")?;
420                    }
421                    write!(f, "{}", arg)?;
422                }
423                write!(f, ")")
424            }
425            Expr::Case {
426                operand,
427                when_then,
428                else_result,
429            } => {
430                write!(f, "CASE")?;
431                if let Some(operand) = operand {
432                    write!(f, " {}", operand)?;
433                }
434                for (when, then) in when_then {
435                    write!(f, " WHEN {} THEN {}", when, then)?;
436                }
437                if let Some(else_result) = else_result {
438                    write!(f, " ELSE {}", else_result)?;
439                }
440                write!(f, " END")
441            }
442            Expr::Cast { expr, data_type } => {
443                write!(f, "CAST({} AS {:?})", expr, data_type)
444            }
445            Expr::IsNull(expr) => write!(f, "{} IS NULL", expr),
446            Expr::IsNotNull(expr) => write!(f, "{} IS NOT NULL", expr),
447            Expr::InList {
448                expr,
449                list,
450                negated,
451            } => {
452                write!(f, "{}", expr)?;
453                if *negated {
454                    write!(f, " NOT")?;
455                }
456                write!(f, " IN (")?;
457                for (i, item) in list.iter().enumerate() {
458                    if i > 0 {
459                        write!(f, ", ")?;
460                    }
461                    write!(f, "{}", item)?;
462                }
463                write!(f, ")")
464            }
465            Expr::Between {
466                expr,
467                low,
468                high,
469                negated,
470            } => {
471                write!(f, "{}", expr)?;
472                if *negated {
473                    write!(f, " NOT")?;
474                }
475                write!(f, " BETWEEN {} AND {}", low, high)
476            }
477            Expr::Subquery(query) => write!(f, "({})", query),
478            Expr::Wildcard => write!(f, "*"),
479        }
480    }
481}
482
483impl fmt::Display for Literal {
484    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
485        match self {
486            Literal::Null => write!(f, "NULL"),
487            Literal::Boolean(b) => write!(f, "{}", b),
488            Literal::Integer(i) => write!(f, "{}", i),
489            Literal::Float(fl) => write!(f, "{}", fl),
490            Literal::String(s) => write!(f, "'{}'", s),
491        }
492    }
493}
494
495impl fmt::Display for BinaryOperator {
496    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
497        match self {
498            BinaryOperator::Plus => write!(f, "+"),
499            BinaryOperator::Minus => write!(f, "-"),
500            BinaryOperator::Multiply => write!(f, "*"),
501            BinaryOperator::Divide => write!(f, "/"),
502            BinaryOperator::Modulo => write!(f, "%"),
503            BinaryOperator::Eq => write!(f, "="),
504            BinaryOperator::NotEq => write!(f, "<>"),
505            BinaryOperator::Lt => write!(f, "<"),
506            BinaryOperator::LtEq => write!(f, "<="),
507            BinaryOperator::Gt => write!(f, ">"),
508            BinaryOperator::GtEq => write!(f, ">="),
509            BinaryOperator::And => write!(f, "AND"),
510            BinaryOperator::Or => write!(f, "OR"),
511            BinaryOperator::Concat => write!(f, "||"),
512            BinaryOperator::Like => write!(f, "LIKE"),
513            BinaryOperator::NotLike => write!(f, "NOT LIKE"),
514            BinaryOperator::ILike => write!(f, "ILIKE"),
515            BinaryOperator::NotILike => write!(f, "NOT ILIKE"),
516        }
517    }
518}
519
520impl fmt::Display for UnaryOperator {
521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522        match self {
523            UnaryOperator::Minus => write!(f, "-"),
524            UnaryOperator::Not => write!(f, "NOT"),
525        }
526    }
527}
528
529impl fmt::Display for OrderByExpr {
530    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531        write!(f, "{}", self.expr)?;
532        if self.asc {
533            write!(f, " ASC")?;
534        } else {
535            write!(f, " DESC")?;
536        }
537        if self.nulls_first {
538            write!(f, " NULLS FIRST")?;
539        } else {
540            write!(f, " NULLS LAST")?;
541        }
542        Ok(())
543    }
544}