proof_of_sql_parser/
intermediate_ast.rs

1//! This module contains the AST nodes for the intermediate representation of a Proof of SQL query.
2/***
3* These AST nodes are closely following vervolg:
4* https://docs.rs/vervolg/latest/vervolg/ast/enum.Statement.html
5***/
6
7use crate::{posql_time::PoSQLTimestamp, Identifier};
8use alloc::{boxed::Box, string::String, vec::Vec};
9use bigdecimal::BigDecimal;
10use core::{
11    fmt,
12    fmt::{Display, Formatter},
13    hash::Hash,
14};
15use serde::{Deserialize, Serialize};
16
17/// Representation of a `SetExpression`, a collection of rows, each having one or more columns.
18#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
19pub enum SetExpression {
20    /// Query result as `SetExpression`
21    Query {
22        /// Result expressions e.g. `a` and `b` in `SELECT a, b FROM table`
23        result_exprs: Vec<SelectResultExpr>,
24        /// Table expression e.g. `table` in `SELECT a, b FROM table`
25        from: Vec<Box<TableExpression>>,
26        /// Filter expression e.g. `a > 5` in `SELECT a, b FROM table WHERE a > 5`
27        /// If None, no filter is applied
28        where_expr: Option<Box<Expression>>,
29        /// Group by expressions e.g. `a` in `SELECT a, COUNT(*) FROM table GROUP BY a`
30        group_by: Vec<Identifier>,
31    },
32}
33
34#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
35/// What to select in a query
36pub enum SelectResultExpr {
37    /// All columns in a table e.g. `SELECT * FROM table`
38    ALL,
39    /// A single expression e.g. `SELECT a FROM table`
40    AliasedResultExpr(AliasedResultExpr),
41}
42
43#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
44/// An expression with an alias e.g. `a + 1 AS b`
45pub struct AliasedResultExpr {
46    /// The expression e.g. `a + 1`, `COUNT(*)`, etc.
47    pub expr: Box<Expression>,
48    /// The alias e.g. `count` in `COUNT(*) AS count`
49    pub alias: Identifier,
50}
51
52impl From<AliasedResultExpr> for SelectResultExpr {
53    fn from(value: AliasedResultExpr) -> Self {
54        SelectResultExpr::AliasedResultExpr(AliasedResultExpr {
55            expr: value.expr,
56            alias: value.alias,
57        })
58    }
59}
60
61impl AliasedResultExpr {
62    /// Create a new `AliasedResultExpr`
63    #[must_use]
64    pub fn new(expr: Expression, alias: Identifier) -> Self {
65        Self {
66            expr: Box::new(expr),
67            alias,
68        }
69    }
70
71    /// Try to get the identifier of the expression if it is a column
72    /// Otherwise return None
73    #[must_use]
74    pub fn try_as_identifier(&self) -> Option<&Identifier> {
75        match self.expr.as_ref() {
76            Expression::Column(column) => Some(column),
77            _ => None,
78        }
79    }
80}
81
82/// Representations of base queries
83#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
84pub enum TableExpression {
85    /// The row set of a given table; possibly providing an alias
86    Named {
87        /// The qualified table Identifier
88        table: Identifier,
89        /// Namespace / schema for the table
90        schema: Option<Identifier>,
91    },
92}
93
94/// Binary operators for simple expressions
95#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
96pub enum BinaryOperator {
97    /// Numeric addition
98    Add,
99
100    /// Numeric subtraction
101    Subtract,
102
103    /// Numeric multiplication
104    Multiply,
105
106    /// Numeric division
107    Division,
108
109    /// Logical And
110    And,
111
112    /// Logical Or
113    Or,
114
115    /// Comparison =
116    Equal,
117
118    /// Comparison <
119    LessThan,
120
121    /// Comparison >
122    GreaterThan,
123}
124
125/// Possible unary operators for simple expressions
126#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
127pub enum UnaryOperator {
128    /// Logical inversion
129    Not,
130}
131
132// Aggregation operators
133#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
134/// Aggregation operators
135pub enum AggregationOperator {
136    /// Maximum
137    Max,
138    /// Minimum
139    Min,
140    /// Sum
141    Sum,
142    /// Count
143    Count,
144    /// Return the first value
145    First,
146}
147
148impl Display for AggregationOperator {
149    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
150        match self {
151            AggregationOperator::Max => write!(f, "max"),
152            AggregationOperator::Min => write!(f, "min"),
153            AggregationOperator::Sum => write!(f, "sum"),
154            AggregationOperator::Count => write!(f, "count"),
155            AggregationOperator::First => write!(f, "first"),
156        }
157    }
158}
159
160/// Boolean Expressions
161#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Hash)]
162pub enum Expression {
163    /// Literal
164    Literal(Literal),
165
166    /// Column
167    Column(Identifier),
168
169    /// Unary operation
170    Unary {
171        /// The unary operator
172        op: UnaryOperator,
173        /// The expression to apply the operator to
174        expr: Box<Expression>,
175    },
176
177    /// Binary operation
178    Binary {
179        /// The binary operator
180        op: BinaryOperator,
181        /// The left hand side of the operation
182        left: Box<Expression>,
183        /// The right hand side of the operation
184        right: Box<Expression>,
185    },
186
187    /// * expression
188    Wildcard,
189
190    /// Aggregation operation
191    Aggregation {
192        /// The aggregation operator
193        op: AggregationOperator,
194        /// The expression to aggregate
195        expr: Box<Expression>,
196    },
197}
198
199impl Expression {
200    /// Create a new `SUM()`
201    #[must_use]
202    pub fn sum(self) -> Box<Self> {
203        Box::new(Expression::Aggregation {
204            op: AggregationOperator::Sum,
205            expr: Box::new(self),
206        })
207    }
208
209    /// Create a new `MAX()`
210    #[must_use]
211    pub fn max(self) -> Box<Self> {
212        Box::new(Expression::Aggregation {
213            op: AggregationOperator::Max,
214            expr: Box::new(self),
215        })
216    }
217
218    /// Create a new `MIN()`
219    #[must_use]
220    pub fn min(self) -> Box<Self> {
221        Box::new(Expression::Aggregation {
222            op: AggregationOperator::Min,
223            expr: Box::new(self),
224        })
225    }
226
227    /// Create a new `COUNT()`
228    #[must_use]
229    pub fn count(self) -> Box<Self> {
230        Box::new(Expression::Aggregation {
231            op: AggregationOperator::Count,
232            expr: Box::new(self),
233        })
234    }
235
236    /// Create a new `FIRST()`
237    #[cfg_attr(coverage_nightly, coverage(off))]
238    #[must_use]
239    pub fn first(self) -> Box<Self> {
240        Box::new(Expression::Aggregation {
241            op: AggregationOperator::First,
242            expr: Box::new(self),
243        })
244    }
245    /// Create an `AliasedResultExpr` from an `Expression` using the provided alias.
246    /// # Panics
247    ///
248    /// This function will panic if the provided `alias` cannot be parsed into an `Identifier`.
249    /// It will also panic if `self` cannot be boxed.
250    #[must_use]
251    pub fn alias(self, alias: &str) -> AliasedResultExpr {
252        AliasedResultExpr {
253            expr: Box::new(self),
254            alias: alias.parse().unwrap(),
255        }
256    }
257}
258impl core::ops::Add<Box<Expression>> for Box<Expression> {
259    type Output = Box<Expression>;
260
261    fn add(self, rhs: Box<Expression>) -> Box<Expression> {
262        Box::new(Expression::Binary {
263            op: BinaryOperator::Add,
264            left: self,
265            right: rhs,
266        })
267    }
268}
269impl core::ops::Mul<Box<Expression>> for Box<Expression> {
270    type Output = Box<Expression>;
271
272    fn mul(self, rhs: Box<Expression>) -> Box<Expression> {
273        Box::new(Expression::Binary {
274            op: BinaryOperator::Multiply,
275            left: self,
276            right: rhs,
277        })
278    }
279}
280impl core::ops::Div<Box<Expression>> for Box<Expression> {
281    type Output = Box<Expression>;
282
283    fn div(self, rhs: Box<Expression>) -> Box<Expression> {
284        Box::new(Expression::Binary {
285            op: BinaryOperator::Division,
286            left: self,
287            right: rhs,
288        })
289    }
290}
291impl core::ops::Sub<Box<Expression>> for Box<Expression> {
292    type Output = Box<Expression>;
293
294    fn sub(self, rhs: Box<Expression>) -> Box<Expression> {
295        Box::new(Expression::Binary {
296            op: BinaryOperator::Subtract,
297            left: self,
298            right: rhs,
299        })
300    }
301}
302
303/// `OrderBy`
304#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
305pub struct OrderBy {
306    /// which column to order by
307    pub expr: Identifier,
308    /// in which direction to order
309    pub direction: OrderByDirection,
310}
311
312/// `OrderByDirection` values
313#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
314pub enum OrderByDirection {
315    /// Ascending
316    Asc,
317    /// Descending
318    Desc,
319}
320
321impl Display for OrderByDirection {
322    // This trait requires `fmt` with this exact signature.
323    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
324        match self {
325            OrderByDirection::Asc => write!(f, "asc"),
326            OrderByDirection::Desc => write!(f, "desc"),
327        }
328    }
329}
330
331/// Limits for a limit clause
332#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
333pub struct Slice {
334    /// number of rows to return
335    ///
336    /// if `u64::MAX`, specify all rows
337    pub number_rows: u64,
338
339    /// number of rows to skip
340    ///
341    /// if 0, specify the first row as starting point
342    /// if negative, specify the offset from the end
343    /// (e.g. -1 is the last row, -2 is the second to last row, etc.)
344    pub offset_value: i64,
345}
346
347/// Literal values
348#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Hash)]
349pub enum Literal {
350    /// Boolean Literal
351    Boolean(bool),
352    /// i64 Literal
353    BigInt(i64),
354    /// i128 Literal
355    Int128(i128),
356    /// String Literal
357    VarChar(String),
358    /// Binary Data Literal
359    VarBinary(Vec<u8>),
360    /// Decimal Literal
361    Decimal(BigDecimal),
362    /// Timestamp Literal
363    Timestamp(PoSQLTimestamp),
364}
365
366impl From<bool> for Literal {
367    fn from(val: bool) -> Self {
368        Literal::Boolean(val)
369    }
370}
371
372/// TODO: add docs
373macro_rules! impl_int_to_literal {
374    ($tt:ty) => {
375        impl From<$tt> for Literal {
376            fn from(val: $tt) -> Self {
377                Literal::BigInt(i64::from(val))
378            }
379        }
380    };
381}
382
383impl_int_to_literal!(i8);
384impl_int_to_literal!(u8);
385impl_int_to_literal!(i16);
386impl_int_to_literal!(u16);
387impl_int_to_literal!(i32);
388impl_int_to_literal!(u32);
389impl_int_to_literal!(i64);
390
391impl From<i128> for Literal {
392    fn from(val: i128) -> Self {
393        Literal::Int128(val)
394    }
395}
396
397/// TODO: add docs
398macro_rules! impl_string_to_literal {
399    ($tt:ty) => {
400        impl From<$tt> for Literal {
401            fn from(val: $tt) -> Self {
402                Literal::VarChar(val.into())
403            }
404        }
405    };
406}
407
408impl_string_to_literal!(&str);
409impl_string_to_literal!(String);
410
411impl From<BigDecimal> for Literal {
412    fn from(val: BigDecimal) -> Self {
413        Literal::Decimal(val)
414    }
415}
416
417impl From<PoSQLTimestamp> for Literal {
418    fn from(time: PoSQLTimestamp) -> Self {
419        Literal::Timestamp(time)
420    }
421}
422
423/// Helper function to append an item to a vector
424pub(crate) fn append<T>(list: Vec<T>, item: T) -> Vec<T> {
425    let mut result = list;
426    result.push(item);
427    result
428}