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        /// Source span of the constraint.
145        #[serde(with = "oak_core::serde_range")]
146        span: Range<usize>,
147    },
148    /// NOT NULL constraint.
149    NotNull {
150        /// Source span of the constraint.
151        #[serde(with = "oak_core::serde_range")]
152        span: Range<usize>,
153    },
154    /// NULL constraint.
155    Nullable {
156        /// Source span of the constraint.
157        #[serde(with = "oak_core::serde_range")]
158        span: Range<usize>,
159    },
160    /// UNIQUE constraint.
161    Unique {
162        /// Source span of the constraint.
163        #[serde(with = "oak_core::serde_range")]
164        span: Range<usize>,
165    },
166    /// DEFAULT constraint with an expression.
167    Default(Expression, #[serde(with = "oak_core::serde_range")] Range<usize>),
168    /// CHECK constraint with an expression.
169    Check(Expression, #[serde(with = "oak_core::serde_range")] Range<usize>),
170    /// AUTOINCREMENT constraint.
171    AutoIncrement {
172        /// Source span of the constraint.
173        #[serde(with = "oak_core::serde_range")]
174        span: Range<usize>,
175    },
176}
177
178impl ToSource for ColumnConstraint {
179    fn to_source(&self, buffer: &mut SourceBuffer) {
180        match self {
181            ColumnConstraint::PrimaryKey { .. } => {
182                buffer.push("PRIMARY");
183                buffer.push("KEY");
184            }
185            ColumnConstraint::NotNull { .. } => {
186                buffer.push("NOT");
187                buffer.push("NULL");
188            }
189            ColumnConstraint::Nullable { .. } => buffer.push("NULL"),
190            ColumnConstraint::Unique { .. } => buffer.push("UNIQUE"),
191            ColumnConstraint::Default(expr, _) => {
192                buffer.push("DEFAULT");
193                expr.to_source(buffer);
194            }
195            ColumnConstraint::Check(expr, _) => {
196                buffer.push("CHECK");
197                buffer.push("(");
198                expr.to_source(buffer);
199                buffer.push(")");
200            }
201            ColumnConstraint::AutoIncrement { .. } => buffer.push("AUTOINCREMENT"),
202        }
203    }
204}
205
206/// Represents the type of object to create.
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
209pub enum CreateObjectType {
210    /// TABLE object.
211    Table,
212    /// VIEW object.
213    View,
214    /// INDEX object.
215    Index,
216    /// DATABASE object.
217    Database,
218}
219
220impl ToSource for CreateObjectType {
221    fn to_source(&self, buffer: &mut SourceBuffer) {
222        match self {
223            CreateObjectType::Table => buffer.push("TABLE"),
224            CreateObjectType::View => buffer.push("VIEW"),
225            CreateObjectType::Index => buffer.push("INDEX"),
226            CreateObjectType::Database => buffer.push("DATABASE"),
227        }
228    }
229}
230
231/// Represents a DROP statement.
232#[derive(Debug, Clone)]
233#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
234pub struct DropStatement {
235    /// The type of object to drop.
236    pub object_type: DropObjectType,
237    /// The name of the object.
238    pub name: Identifier,
239    /// Whether to include IF EXISTS.
240    pub if_exists: bool,
241    /// The span of the DROP statement.
242    #[serde(with = "oak_core::serde_range")]
243    pub span: Range<usize>,
244}
245
246impl ToSource for DropStatement {
247    fn to_source(&self, buffer: &mut SourceBuffer) {
248        buffer.push("DROP");
249        self.object_type.to_source(buffer);
250        if self.if_exists {
251            buffer.push("IF");
252            buffer.push("EXISTS");
253        }
254        self.name.to_source(buffer);
255    }
256}
257
258/// Represents the type of object to drop.
259#[derive(Debug, Clone, Copy, PartialEq, Eq)]
260#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
261pub enum DropObjectType {
262    /// TABLE object.
263    Table,
264    /// VIEW object.
265    View,
266    /// INDEX object.
267    Index,
268    /// DATABASE object.
269    Database,
270}
271
272impl ToSource for DropObjectType {
273    fn to_source(&self, buffer: &mut SourceBuffer) {
274        match self {
275            DropObjectType::Table => buffer.push("TABLE"),
276            DropObjectType::View => buffer.push("VIEW"),
277            DropObjectType::Index => buffer.push("INDEX"),
278            DropObjectType::Database => buffer.push("DATABASE"),
279        }
280    }
281}
282
283/// Represents an ALTER statement.
284#[derive(Debug, Clone)]
285#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
286pub struct AlterStatement {
287    /// The table to alter.
288    pub table_name: TableName,
289    /// The action to perform.
290    pub action: Option<AlterAction>,
291    /// The span of the ALTER statement.
292    #[serde(with = "oak_core::serde_range")]
293    pub span: Range<usize>,
294}
295
296/// Represents an action in an ALTER TABLE statement.
297#[derive(Debug, Clone)]
298#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
299pub enum AlterAction {
300    /// ADD COLUMN action.
301    AddColumn {
302        /// The name of the column to add.
303        name: Identifier,
304        /// The data type of the column.
305        data_type: Option<Arc<str>>,
306        /// The span of the ADD COLUMN action.
307        #[serde(with = "oak_core::serde_range")]
308        span: Range<usize>,
309    },
310    /// DROP COLUMN action.
311    DropColumn {
312        /// The name of the column to drop.
313        name: Identifier,
314        /// The span of the DROP COLUMN action.
315        #[serde(with = "oak_core::serde_range")]
316        span: Range<usize>,
317    },
318    /// RENAME TO action.
319    RenameTo {
320        /// The new name for the table.
321        new_name: Identifier,
322        /// The span of the RENAME TO action.
323        #[serde(with = "oak_core::serde_range")]
324        span: Range<usize>,
325    },
326}
327
328impl ToSource for AlterStatement {
329    fn to_source(&self, buffer: &mut SourceBuffer) {
330        buffer.push("ALTER");
331        buffer.push("TABLE");
332        self.table_name.to_source(buffer);
333        if let Some(action) = &self.action {
334            match action {
335                AlterAction::AddColumn { name, data_type, .. } => {
336                    buffer.push("ADD");
337                    buffer.push("COLUMN");
338                    name.to_source(buffer);
339                    if let Some(dt) = data_type {
340                        buffer.push(dt);
341                    }
342                }
343                AlterAction::DropColumn { name, .. } => {
344                    buffer.push("DROP");
345                    buffer.push("COLUMN");
346                    name.to_source(buffer);
347                }
348                AlterAction::RenameTo { new_name, .. } => {
349                    buffer.push("RENAME");
350                    buffer.push("TO");
351                    new_name.to_source(buffer);
352                }
353            }
354        }
355    }
356}