Skip to main content

oak_sql/ast/statements/
ddl_nodes.rs

1use crate::ast::{
2    expr::{Expression, Identifier, TableName},
3    statements::query::SelectStatement,
4};
5use core::range::Range;
6use oak_core::source::{SourceBuffer, ToSource};
7use std::sync::Arc;
8
9/// Represents a CREATE statement.
10#[derive(Debug, Clone)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct CreateStatement {
13    /// The type of object to create (TABLE, VIEW, etc.).
14    pub object_type: CreateObjectType,
15    /// The name of the object.
16    pub name: Identifier,
17    /// Whether to include IF NOT EXISTS.
18    pub if_not_exists: bool,
19    /// The body of the CREATE statement.
20    pub body: CreateBody,
21    /// The span of the CREATE statement.
22    #[serde(with = "oak_core::serde_range")]
23    pub span: Range<usize>,
24}
25
26/// Represents the body of a CREATE statement.
27#[derive(Debug, Clone)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub enum CreateBody {
30    /// A TABLE body with column definitions.
31    Table {
32        /// The column definitions.
33        columns: Vec<ColumnDefinition>,
34        /// The span of the TABLE body.
35        #[serde(with = "oak_core::serde_range")]
36        span: Range<usize>,
37    },
38    /// A VIEW body with a query.
39    View {
40        /// The query for the view.
41        query: Box<SelectStatement>,
42        /// The span of the VIEW body.
43        #[serde(with = "oak_core::serde_range")]
44        span: Range<usize>,
45    },
46    /// An INDEX body.
47    Index {
48        /// The table to create the index on.
49        table_name: TableName,
50        /// The columns to index.
51        columns: Vec<Identifier>,
52        /// Whether it's a UNIQUE index.
53        unique: bool,
54        /// The span of the INDEX body.
55        #[serde(with = "oak_core::serde_range")]
56        span: Range<usize>,
57    },
58    /// A DATABASE body.
59    Database {
60        /// The span of the DATABASE body.
61        #[serde(with = "oak_core::serde_range")]
62        span: Range<usize>,
63    },
64}
65
66impl ToSource for CreateStatement {
67    fn to_source(&self, buffer: &mut SourceBuffer) {
68        buffer.push("CREATE");
69        if let CreateBody::Index { unique: true, .. } = &self.body {
70            buffer.push("UNIQUE");
71        }
72        self.object_type.to_source(buffer);
73        if self.if_not_exists {
74            buffer.push("IF");
75            buffer.push("NOT");
76            buffer.push("EXISTS");
77        }
78        self.name.to_source(buffer);
79        match &self.body {
80            CreateBody::Table { columns, .. } => {
81                if !columns.is_empty() {
82                    buffer.push("(");
83                    for (i, col) in columns.iter().enumerate() {
84                        if i > 0 {
85                            buffer.push(",");
86                        }
87                        col.to_source(buffer);
88                    }
89                    buffer.push(")");
90                }
91            }
92            CreateBody::View { query, .. } => {
93                buffer.push("AS");
94                query.to_source(buffer);
95            }
96            CreateBody::Index { table_name, columns, .. } => {
97                buffer.push("ON");
98                table_name.to_source(buffer);
99                buffer.push("(");
100                for (i, col) in columns.iter().enumerate() {
101                    if i > 0 {
102                        buffer.push(",");
103                    }
104                    col.to_source(buffer);
105                }
106                buffer.push(")");
107            }
108            CreateBody::Database { .. } => {}
109        }
110    }
111}
112
113/// Represents a column definition in a CREATE TABLE statement.
114#[derive(Debug, Clone)]
115#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
116pub struct ColumnDefinition {
117    /// The name of the column.
118    pub name: Identifier,
119    /// The data type of the column.
120    pub data_type: Arc<str>,
121    /// Any column constraints.
122    pub constraints: Vec<ColumnConstraint>,
123    /// The span of the column definition.
124    #[serde(with = "oak_core::serde_range")]
125    pub span: Range<usize>,
126}
127
128impl ToSource for ColumnDefinition {
129    fn to_source(&self, buffer: &mut SourceBuffer) {
130        self.name.to_source(buffer);
131        buffer.push(&self.data_type);
132        for constraint in &self.constraints {
133            constraint.to_source(buffer);
134        }
135    }
136}
137
138/// Represents a constraint on a column.
139#[derive(Debug, Clone)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141pub enum ColumnConstraint {
142    /// PRIMARY KEY constraint.
143    PrimaryKey {
144        #[serde(with = "oak_core::serde_range")]
145        span: Range<usize>,
146    },
147    /// NOT NULL constraint.
148    NotNull {
149        #[serde(with = "oak_core::serde_range")]
150        span: Range<usize>,
151    },
152    /// NULL constraint.
153    Nullable {
154        #[serde(with = "oak_core::serde_range")]
155        span: Range<usize>,
156    },
157    /// UNIQUE constraint.
158    Unique {
159        #[serde(with = "oak_core::serde_range")]
160        span: Range<usize>,
161    },
162    /// DEFAULT constraint with an expression.
163    Default(Expression, #[serde(with = "oak_core::serde_range")] Range<usize>),
164    /// CHECK constraint with an expression.
165    Check(Expression, #[serde(with = "oak_core::serde_range")] Range<usize>),
166    /// AUTOINCREMENT constraint.
167    AutoIncrement {
168        #[serde(with = "oak_core::serde_range")]
169        span: Range<usize>,
170    },
171}
172
173impl ToSource for ColumnConstraint {
174    fn to_source(&self, buffer: &mut SourceBuffer) {
175        match self {
176            ColumnConstraint::PrimaryKey { .. } => {
177                buffer.push("PRIMARY");
178                buffer.push("KEY");
179            }
180            ColumnConstraint::NotNull { .. } => {
181                buffer.push("NOT");
182                buffer.push("NULL");
183            }
184            ColumnConstraint::Nullable { .. } => buffer.push("NULL"),
185            ColumnConstraint::Unique { .. } => buffer.push("UNIQUE"),
186            ColumnConstraint::Default(expr, _) => {
187                buffer.push("DEFAULT");
188                expr.to_source(buffer);
189            }
190            ColumnConstraint::Check(expr, _) => {
191                buffer.push("CHECK");
192                buffer.push("(");
193                expr.to_source(buffer);
194                buffer.push(")");
195            }
196            ColumnConstraint::AutoIncrement { .. } => buffer.push("AUTOINCREMENT"),
197        }
198    }
199}
200
201/// Represents the type of object to create.
202#[derive(Debug, Clone, Copy, PartialEq, Eq)]
203#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
204pub enum CreateObjectType {
205    /// TABLE object.
206    Table,
207    /// VIEW object.
208    View,
209    /// INDEX object.
210    Index,
211    /// DATABASE object.
212    Database,
213}
214
215impl ToSource for CreateObjectType {
216    fn to_source(&self, buffer: &mut SourceBuffer) {
217        match self {
218            CreateObjectType::Table => buffer.push("TABLE"),
219            CreateObjectType::View => buffer.push("VIEW"),
220            CreateObjectType::Index => buffer.push("INDEX"),
221            CreateObjectType::Database => buffer.push("DATABASE"),
222        }
223    }
224}
225
226/// Represents a DROP statement.
227#[derive(Debug, Clone)]
228#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
229pub struct DropStatement {
230    /// The type of object to drop.
231    pub object_type: DropObjectType,
232    /// The name of the object.
233    pub name: Identifier,
234    /// Whether to include IF EXISTS.
235    pub if_exists: bool,
236    /// The span of the DROP statement.
237    #[serde(with = "oak_core::serde_range")]
238    pub span: Range<usize>,
239}
240
241impl ToSource for DropStatement {
242    fn to_source(&self, buffer: &mut SourceBuffer) {
243        buffer.push("DROP");
244        self.object_type.to_source(buffer);
245        if self.if_exists {
246            buffer.push("IF");
247            buffer.push("EXISTS");
248        }
249        self.name.to_source(buffer);
250    }
251}
252
253/// Represents the type of object to drop.
254#[derive(Debug, Clone, Copy, PartialEq, Eq)]
255#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
256pub enum DropObjectType {
257    /// TABLE object.
258    Table,
259    /// VIEW object.
260    View,
261    /// INDEX object.
262    Index,
263    /// DATABASE object.
264    Database,
265}
266
267impl ToSource for DropObjectType {
268    fn to_source(&self, buffer: &mut SourceBuffer) {
269        match self {
270            DropObjectType::Table => buffer.push("TABLE"),
271            DropObjectType::View => buffer.push("VIEW"),
272            DropObjectType::Index => buffer.push("INDEX"),
273            DropObjectType::Database => buffer.push("DATABASE"),
274        }
275    }
276}
277
278/// Represents an ALTER statement.
279#[derive(Debug, Clone)]
280#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
281pub struct AlterStatement {
282    /// The table to alter.
283    pub table_name: TableName,
284    /// The action to perform.
285    pub action: Option<AlterAction>,
286    /// The span of the ALTER statement.
287    #[serde(with = "oak_core::serde_range")]
288    pub span: Range<usize>,
289}
290
291/// Represents an action in an ALTER TABLE statement.
292#[derive(Debug, Clone)]
293#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
294pub enum AlterAction {
295    /// ADD COLUMN action.
296    AddColumn {
297        /// The name of the column to add.
298        name: Identifier,
299        /// The data type of the column.
300        data_type: Option<Arc<str>>,
301        /// The span of the ADD COLUMN action.
302        #[serde(with = "oak_core::serde_range")]
303        span: Range<usize>,
304    },
305    /// DROP COLUMN action.
306    DropColumn {
307        /// The name of the column to drop.
308        name: Identifier,
309        /// The span of the DROP COLUMN action.
310        #[serde(with = "oak_core::serde_range")]
311        span: Range<usize>,
312    },
313    /// RENAME TO action.
314    RenameTo {
315        /// The new name for the table.
316        new_name: Identifier,
317        /// The span of the RENAME TO action.
318        #[serde(with = "oak_core::serde_range")]
319        span: Range<usize>,
320    },
321}
322
323impl ToSource for AlterStatement {
324    fn to_source(&self, buffer: &mut SourceBuffer) {
325        buffer.push("ALTER");
326        buffer.push("TABLE");
327        self.table_name.to_source(buffer);
328        if let Some(action) = &self.action {
329            match action {
330                AlterAction::AddColumn { name, data_type, .. } => {
331                    buffer.push("ADD");
332                    buffer.push("COLUMN");
333                    name.to_source(buffer);
334                    if let Some(dt) = data_type {
335                        buffer.push(dt);
336                    }
337                }
338                AlterAction::DropColumn { name, .. } => {
339                    buffer.push("DROP");
340                    buffer.push("COLUMN");
341                    name.to_source(buffer);
342                }
343                AlterAction::RenameTo { new_name, .. } => {
344                    buffer.push("RENAME");
345                    buffer.push("TO");
346                    new_name.to_source(buffer);
347                }
348            }
349        }
350    }
351}