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