Skip to main content

oak_sql/ast/statements/
query_nodes.rs

1use crate::ast::expr::{Expression, Identifier, TableName};
2use core::range::Range;
3use oak_core::source::{SourceBuffer, ToSource};
4
5/// Represents a SELECT statement.
6#[derive(Debug, Clone)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct SelectStatement {
9    /// The items to select (columns, expressions, or `*`).
10    pub items: Vec<SelectItem>,
11    /// The table to select from.
12    pub from: Option<TableName>,
13    /// Any JOIN clauses.
14    pub joins: Vec<JoinClause>,
15    /// The WHERE clause selection expression.
16    pub expr: Option<Expression>, // WHERE clause
17    /// The GROUP BY clause.
18    pub group_by: Option<GroupByClause>,
19    /// The HAVING clause.
20    pub having: Option<HavingClause>,
21    /// The ORDER BY clause.
22    pub order_by: Option<OrderByClause>,
23    /// The LIMIT clause.
24    pub limit: Option<LimitClause>,
25    /// The span of the SELECT statement.
26    #[serde(with = "oak_core::serde_range")]
27    pub span: Range<usize>,
28}
29
30impl ToSource for SelectStatement {
31    fn to_source(&self, buffer: &mut SourceBuffer) {
32        buffer.push("SELECT");
33        for (i, item) in self.items.iter().enumerate() {
34            if i > 0 {
35                buffer.push(",");
36            }
37            item.to_source(buffer);
38        }
39        if let Some(from) = &self.from {
40            buffer.push("FROM");
41            from.to_source(buffer);
42        }
43        for join in &self.joins {
44            join.to_source(buffer);
45        }
46        if let Some(expr) = &self.expr {
47            buffer.push("WHERE");
48            expr.to_source(buffer);
49        }
50        if let Some(group_by) = &self.group_by {
51            group_by.to_source(buffer);
52        }
53        if let Some(having) = &self.having {
54            having.to_source(buffer);
55        }
56        if let Some(order_by) = &self.order_by {
57            order_by.to_source(buffer);
58        }
59        if let Some(limit) = &self.limit {
60            limit.to_source(buffer);
61        }
62    }
63}
64
65/// Represents an item in a SELECT list.
66#[derive(Debug, Clone)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68pub enum SelectItem {
69    /// Select all columns (`*`).
70    Star {
71        /// The span of the `*`.
72        #[serde(with = "oak_core::serde_range")]
73        span: Range<usize>,
74    },
75    /// Select an expression with an optional alias.
76    Expression {
77        /// The expression to select.
78        expr: Expression,
79        /// The optional alias for the expression.
80        alias: Option<Identifier>,
81        /// The span of the select item.
82        #[serde(with = "oak_core::serde_range")]
83        span: Range<usize>,
84    },
85}
86
87impl ToSource for SelectItem {
88    fn to_source(&self, buffer: &mut SourceBuffer) {
89        match self {
90            SelectItem::Star { .. } => buffer.push("*"),
91            SelectItem::Expression { expr, alias, .. } => {
92                expr.to_source(buffer);
93                if let Some(alias) = alias {
94                    buffer.push("AS");
95                    alias.to_source(buffer);
96                }
97            }
98        }
99    }
100}
101
102/// JOIN clause.
103#[derive(Debug, Clone)]
104#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
105pub struct JoinClause {
106    /// The type of join (e.g., INNER, LEFT).
107    pub join_type: JoinType,
108    /// The table being joined.
109    pub table: TableName,
110    /// The join condition (ON clause).
111    pub on: Option<Expression>,
112    /// The span of the JOIN clause.
113    #[serde(with = "oak_core::serde_range")]
114    pub span: Range<usize>,
115}
116
117impl ToSource for JoinClause {
118    fn to_source(&self, buffer: &mut SourceBuffer) {
119        self.join_type.to_source(buffer);
120        buffer.push("JOIN");
121        self.table.to_source(buffer);
122        if let Some(on) = &self.on {
123            buffer.push("ON");
124            on.to_source(buffer);
125        }
126    }
127}
128
129/// Type of SQL join.
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132pub enum JoinType {
133    /// INNER JOIN.
134    Inner,
135    /// LEFT JOIN.
136    Left,
137    /// RIGHT JOIN.
138    Right,
139    /// FULL JOIN.
140    Full,
141}
142
143impl ToSource for JoinType {
144    fn to_source(&self, buffer: &mut SourceBuffer) {
145        match self {
146            JoinType::Inner => buffer.push("INNER"),
147            JoinType::Left => buffer.push("LEFT"),
148            JoinType::Right => buffer.push("RIGHT"),
149            JoinType::Full => buffer.push("FULL"),
150        }
151    }
152}
153
154/// GROUP BY clause.
155#[derive(Debug, Clone)]
156#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
157pub struct GroupByClause {
158    /// The columns to group by.
159    pub columns: Vec<Expression>,
160    /// The span of the GROUP BY clause.
161    #[serde(with = "oak_core::serde_range")]
162    pub span: Range<usize>,
163}
164
165impl ToSource for GroupByClause {
166    fn to_source(&self, buffer: &mut SourceBuffer) {
167        buffer.push("GROUP");
168        buffer.push("BY");
169        for (i, col) in self.columns.iter().enumerate() {
170            if i > 0 {
171                buffer.push(",");
172            }
173            col.to_source(buffer);
174        }
175    }
176}
177
178/// HAVING clause.
179#[derive(Debug, Clone)]
180#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
181pub struct HavingClause {
182    /// The condition for the HAVING clause.
183    pub condition: Expression,
184    /// The span of the HAVING clause.
185    #[serde(with = "oak_core::serde_range")]
186    pub span: Range<usize>,
187}
188
189impl ToSource for HavingClause {
190    fn to_source(&self, buffer: &mut SourceBuffer) {
191        buffer.push("HAVING");
192        self.condition.to_source(buffer);
193    }
194}
195
196/// ORDER BY clause.
197#[derive(Debug, Clone)]
198#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
199pub struct OrderByClause {
200    /// The items to order by.
201    pub items: Vec<OrderByItem>,
202    /// The span of the ORDER BY clause.
203    #[serde(with = "oak_core::serde_range")]
204    pub span: Range<usize>,
205}
206
207impl ToSource for OrderByClause {
208    fn to_source(&self, buffer: &mut SourceBuffer) {
209        buffer.push("ORDER");
210        buffer.push("BY");
211        for (i, item) in self.items.iter().enumerate() {
212            if i > 0 {
213                buffer.push(",");
214            }
215            item.to_source(buffer);
216        }
217    }
218}
219
220/// An item in an ORDER BY clause.
221#[derive(Debug, Clone)]
222#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
223pub struct OrderByItem {
224    /// The expression to order by.
225    pub expr: Expression,
226    /// The direction of the ordering.
227    pub direction: OrderDirection,
228    /// The span of the ORDER BY item.
229    #[serde(with = "oak_core::serde_range")]
230    pub span: Range<usize>,
231}
232
233impl ToSource for OrderByItem {
234    fn to_source(&self, buffer: &mut SourceBuffer) {
235        self.expr.to_source(buffer);
236        self.direction.to_source(buffer);
237    }
238}
239
240/// Direction of ordering.
241#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
243pub enum OrderDirection {
244    /// Ascending order.
245    Asc,
246    /// Descending order.
247    Desc,
248}
249
250impl ToSource for OrderDirection {
251    fn to_source(&self, buffer: &mut SourceBuffer) {
252        match self {
253            OrderDirection::Asc => buffer.push("ASC"),
254            OrderDirection::Desc => buffer.push("DESC"),
255        }
256    }
257}
258
259/// LIMIT clause.
260#[derive(Debug, Clone)]
261#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
262pub struct LimitClause {
263    /// The limit value.
264    pub limit: Expression,
265    /// The optional offset value.
266    pub offset: Option<Expression>,
267    /// The span of the LIMIT clause.
268    #[serde(with = "oak_core::serde_range")]
269    pub span: Range<usize>,
270}
271
272impl ToSource for LimitClause {
273    fn to_source(&self, buffer: &mut SourceBuffer) {
274        buffer.push("LIMIT");
275        self.limit.to_source(buffer);
276        if let Some(offset) = &self.offset {
277            buffer.push("OFFSET");
278            offset.to_source(buffer);
279        }
280    }
281}