Skip to main content

wasm_dbms_sql/
ast.rs

1//! Abstract syntax tree of the supported SQL dialect.
2//!
3//! [`parse`](crate::parse) produces these types. They describe the statement
4//! exactly as written: names are not checked against a schema and literals are
5//! not converted to column types yet. The grammar they model is documented in
6//! the SQL reference of the wasm-dbms book.
7
8/// A parsed SQL statement.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum Statement {
11    /// `SELECT ...`
12    ///
13    /// Boxed because a `SELECT` is much larger than the other statements.
14    Select(Box<Select>),
15    /// `INSERT INTO ...`
16    Insert(Insert),
17    /// `UPDATE ...`
18    Update(Update),
19    /// `DELETE FROM ...`
20    Delete(Delete),
21    /// `BEGIN [TRANSACTION]`
22    Begin,
23    /// `COMMIT [TRANSACTION]`
24    Commit,
25    /// `ROLLBACK [TRANSACTION]`
26    Rollback,
27}
28
29/// A `SELECT` statement.
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct Select {
32    /// Whether `DISTINCT` follows `SELECT`.
33    pub distinct: bool,
34    /// The select list.
35    pub projection: Projection,
36    /// The `FROM` table.
37    pub from: TableRef,
38    /// The `JOIN` clauses, in source order.
39    pub joins: Vec<JoinClause>,
40    /// The `WHERE` condition.
41    pub filter: Option<Condition>,
42    /// The `GROUP BY` columns.
43    pub group_by: Vec<ColumnRef>,
44    /// The `HAVING` condition.
45    pub having: Option<Condition>,
46    /// The `ORDER BY` items, most significant first.
47    pub order_by: Vec<OrderItem>,
48    /// The `LIMIT` row count.
49    pub limit: Option<RowCount>,
50    /// The `OFFSET` row count.
51    pub offset: Option<RowCount>,
52}
53
54/// The select list of a [`Select`].
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub enum Projection {
57    /// `*`: every column.
58    All,
59    /// An explicit list of columns and aggregates.
60    Items(Vec<SelectItem>),
61}
62
63/// One entry of an explicit select list: `operand [AS alias]`.
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct SelectItem {
66    /// The selected column or aggregate.
67    pub operand: Operand,
68    /// The output name given with `AS`.
69    pub alias: Option<String>,
70}
71
72/// Something that yields a value per row or per group.
73#[derive(Debug, Clone, PartialEq, Eq)]
74pub enum Operand {
75    /// A column reference.
76    Column(ColumnRef),
77    /// An aggregate function call.
78    Aggregate(Aggregate),
79}
80
81/// A column name, optionally qualified: `column` or `table.column`.
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub struct ColumnRef {
84    /// The table name or table alias before the dot.
85    pub table: Option<String>,
86    /// The column name.
87    pub column: String,
88}
89
90/// An aggregate function call such as `COUNT(*)` or `SUM(price)`.
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub struct Aggregate {
93    /// The aggregate function.
94    pub function: AggregateKind,
95    /// The aggregated column; `None` only for `COUNT(*)`.
96    pub column: Option<ColumnRef>,
97}
98
99/// The supported aggregate functions.
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum AggregateKind {
102    Count,
103    Sum,
104    Avg,
105    Min,
106    Max,
107}
108
109/// A table in `FROM` or `JOIN`: `name [[AS] alias]`.
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct TableRef {
112    /// The table name.
113    pub name: String,
114    /// The alias that replaces the table name as column qualifier.
115    pub alias: Option<String>,
116}
117
118/// A `JOIN table ON left = right` clause.
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct JoinClause {
121    /// The join type.
122    pub kind: JoinKind,
123    /// The joined table.
124    pub table: TableRef,
125    /// The column written on the left of `=`.
126    pub left: ColumnRef,
127    /// The column written on the right of `=`.
128    pub right: ColumnRef,
129}
130
131/// The supported join types.
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub enum JoinKind {
134    /// `JOIN` or `INNER JOIN`
135    Inner,
136    /// `LEFT [OUTER] JOIN`
137    Left,
138    /// `RIGHT [OUTER] JOIN`
139    Right,
140    /// `FULL [OUTER] JOIN`
141    Full,
142}
143
144/// A boolean condition of a `WHERE` or `HAVING` clause.
145#[derive(Debug, Clone, PartialEq, Eq)]
146pub enum Condition {
147    /// `left AND right`
148    And(Box<Condition>, Box<Condition>),
149    /// `left OR right`
150    Or(Box<Condition>, Box<Condition>),
151    /// `NOT inner`
152    Not(Box<Condition>),
153    /// `operand op value`
154    Compare {
155        operand: Operand,
156        op: CompareOp,
157        value: ValueExpr,
158    },
159    /// `operand [NOT] IN (values)`
160    In {
161        operand: Operand,
162        values: Vec<ValueExpr>,
163        negated: bool,
164    },
165    /// `operand [NOT] LIKE pattern`
166    Like {
167        operand: Operand,
168        pattern: ValueExpr,
169        negated: bool,
170    },
171    /// `operand IS [NOT] NULL`
172    IsNull { operand: Operand, negated: bool },
173}
174
175/// A comparison operator.
176#[derive(Debug, Clone, Copy, PartialEq, Eq)]
177pub enum CompareOp {
178    /// `=`
179    Eq,
180    /// `!=` or `<>`
181    NotEq,
182    /// `<`
183    Lt,
184    /// `<=`
185    LtEq,
186    /// `>`
187    Gt,
188    /// `>=`
189    GtEq,
190}
191
192/// A value written in the statement: a literal or a `?` placeholder.
193#[derive(Debug, Clone, PartialEq, Eq)]
194pub enum ValueExpr {
195    /// A literal value.
196    Literal(Literal),
197    /// The `?` placeholder with this 0-based position in the statement.
198    Parameter(usize),
199}
200
201/// A literal value, before conversion to a column type.
202#[derive(Debug, Clone, PartialEq, Eq)]
203pub enum Literal {
204    /// An integer, with its sign applied.
205    Integer(i128),
206    /// A decimal number as written (`[-]digits.digits`).
207    Float(String),
208    /// The content of a single-quoted string.
209    String(String),
210    /// `TRUE` or `FALSE`
211    Boolean(bool),
212    /// `NULL`
213    Null,
214}
215
216/// One `ORDER BY` entry: `operand [ASC | DESC]`.
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub struct OrderItem {
219    /// The column, select-list alias, or aggregate to sort by.
220    pub operand: Operand,
221    /// Whether `DESC` was given.
222    pub descending: bool,
223}
224
225/// The argument of `LIMIT` or `OFFSET`.
226#[derive(Debug, Clone, PartialEq, Eq)]
227pub enum RowCount {
228    /// A non-negative integer literal.
229    Value(u64),
230    /// The `?` placeholder with this 0-based position in the statement.
231    Parameter(usize),
232}
233
234/// An `INSERT INTO table (columns) VALUES (values)` statement.
235#[derive(Debug, Clone, PartialEq, Eq)]
236pub struct Insert {
237    /// The target table.
238    pub table: String,
239    /// The listed columns.
240    pub columns: Vec<String>,
241    /// One value per listed column, in the same order.
242    pub values: Vec<ValueExpr>,
243}
244
245/// An `UPDATE table SET assignments WHERE condition` statement.
246#[derive(Debug, Clone, PartialEq, Eq)]
247pub struct Update {
248    /// The target table.
249    pub table: String,
250    /// The `SET` assignments.
251    pub assignments: Vec<Assignment>,
252    /// The mandatory `WHERE` condition.
253    pub filter: Condition,
254}
255
256/// One `column = value` entry of an `UPDATE ... SET` list.
257#[derive(Debug, Clone, PartialEq, Eq)]
258pub struct Assignment {
259    /// The column to write.
260    pub column: String,
261    /// The new value.
262    pub value: ValueExpr,
263}
264
265/// A `DELETE FROM table WHERE condition [CASCADE | RESTRICT]` statement.
266#[derive(Debug, Clone, PartialEq, Eq)]
267pub struct Delete {
268    /// The target table.
269    pub table: String,
270    /// The mandatory `WHERE` condition.
271    pub filter: Condition,
272    /// Whether `CASCADE` was given; `RESTRICT` is the default.
273    pub cascade: bool,
274}