sea_query/backend/
table_builder.rs

1use crate::*;
2
3pub trait TableBuilder:
4    IndexBuilder + ForeignKeyBuilder + QuotedBuilder + TableRefBuilder + QueryBuilder
5{
6    /// Translate [`TableCreateStatement`] into SQL statement.
7    fn prepare_table_create_statement(
8        &self,
9        create: &TableCreateStatement,
10        sql: &mut impl SqlWriter,
11    ) {
12        sql.write_str("CREATE ").unwrap();
13
14        self.prepare_create_temporary_table(create, sql);
15
16        sql.write_str("TABLE ").unwrap();
17
18        self.prepare_create_table_if_not_exists(create, sql);
19
20        if let Some(table_ref) = &create.table {
21            self.prepare_table_ref_table_stmt(table_ref, sql);
22        }
23
24        sql.write_str(" ( ").unwrap();
25        let mut first = true;
26
27        create.columns.iter().for_each(|column_def| {
28            if !first {
29                sql.write_str(", ").unwrap();
30            }
31            self.prepare_column_def(column_def, sql);
32            first = false;
33        });
34
35        create.indexes.iter().for_each(|index| {
36            if !first {
37                sql.write_str(", ").unwrap();
38            }
39            self.prepare_table_index_expression(index, sql);
40            first = false;
41        });
42
43        create.foreign_keys.iter().for_each(|foreign_key| {
44            if !first {
45                sql.write_str(", ").unwrap();
46            }
47            self.prepare_foreign_key_create_statement_internal(foreign_key, sql, Mode::Creation);
48            first = false;
49        });
50
51        create.check.iter().for_each(|check| {
52            if !first {
53                sql.write_str(", ").unwrap();
54            }
55            self.prepare_check_constraint(check, sql);
56            first = false;
57        });
58
59        sql.write_str(" )").unwrap();
60
61        self.prepare_table_opt(create, sql);
62
63        if let Some(extra) = &create.extra {
64            sql.write_str(" ").unwrap();
65            sql.write_str(extra).unwrap();
66        }
67    }
68
69    /// Translate [`TableRef`] into SQL statement.
70    fn prepare_table_ref_table_stmt(&self, table_ref: &TableRef, sql: &mut impl SqlWriter) {
71        match table_ref {
72            // Support only unaliased (but potentialy qualified) table names.
73            TableRef::Table(.., None) => self.prepare_table_ref_iden(table_ref, sql),
74            _ => panic!("Not supported"),
75        }
76    }
77
78    /// Translate [`ColumnDef`] into SQL statement.
79    fn prepare_column_def(&self, column_def: &ColumnDef, sql: &mut impl SqlWriter);
80
81    /// Translate [`ColumnDef`] into SQL statement.
82    fn prepare_column_def_internal(
83        &self,
84        _is_alter_column: bool,
85        column_def: &ColumnDef,
86        sql: &mut impl SqlWriter,
87    ) {
88        self.prepare_column_def(column_def, sql);
89    }
90
91    /// Translate [`ColumnType`] into SQL statement.
92    fn prepare_column_type(&self, column_type: &ColumnType, sql: &mut impl SqlWriter);
93
94    /// Translate [`ColumnSpec`] into SQL statement.
95    fn prepare_column_spec(&self, column_spec: &ColumnSpec, sql: &mut impl SqlWriter) {
96        let ColumnSpec {
97            nullable,
98            default,
99            auto_increment,
100            unique,
101            primary_key,
102            check,
103            generated,
104            extra,
105            comment,
106            using: _,
107        } = column_spec;
108
109        if let Some(nullable) = nullable {
110            sql.write_str(if *nullable { " NULL" } else { " NOT NULL" })
111                .unwrap();
112        }
113
114        if let Some(default) = default {
115            sql.write_str(" DEFAULT ").unwrap();
116            // Wrap expressions in parentheses.
117            // Most of database backends support this syntax.
118            //
119            // In MySQL 5.7, the DEFAULT clause doesn't accept any expressions,
120            // so it will be invalid SQL in any case.
121            //
122            // References:
123            // https://sqlite.org/lang_createtable.html
124            match default {
125                Expr::Value(_) | Expr::Constant(_) | Expr::Keyword(_) => {
126                    self.prepare_expr(default, sql)
127                }
128                _ => {
129                    sql.write_str("(").unwrap();
130                    self.prepare_expr(default, sql);
131                    sql.write_str(")").unwrap()
132                }
133            }
134        }
135
136        if let Some(generated) = generated {
137            self.prepare_generated_column(&generated.expr, generated.stored, sql);
138        }
139
140        if *primary_key {
141            sql.write_str(" PRIMARY KEY").unwrap();
142        }
143
144        if *auto_increment {
145            sql.write_str(self.column_spec_auto_increment_keyword())
146                .unwrap();
147        }
148
149        if *unique {
150            sql.write_str(" UNIQUE").unwrap();
151        }
152
153        if let Some(check) = check {
154            sql.write_str(" ").unwrap();
155            self.prepare_check_constraint(check, sql);
156        }
157
158        if let Some(extra) = extra {
159            sql.write_str(" ").unwrap();
160            sql.write_str(extra).unwrap();
161        }
162
163        if let Some(comment) = comment {
164            self.column_comment(comment, sql);
165        }
166    }
167
168    /// column comment
169    fn column_comment(&self, _comment: &str, _sql: &mut impl SqlWriter) {}
170
171    /// The keyword for setting a column to be auto increment.
172    fn column_spec_auto_increment_keyword(&self) -> &str;
173
174    /// Translate [`TableOpt`] into SQL statement.
175    fn prepare_table_opt(&self, create: &TableCreateStatement, sql: &mut impl SqlWriter) {
176        self.prepare_table_opt_def(create, sql)
177    }
178
179    /// Default function
180    fn prepare_table_opt_def(&self, create: &TableCreateStatement, sql: &mut impl SqlWriter) {
181        for table_opt in create.options.iter() {
182            sql.write_str(" ").unwrap();
183            match table_opt {
184                TableOpt::Engine(s) => {
185                    sql.write_str("ENGINE=").unwrap();
186                    sql.write_str(s).unwrap();
187                }
188                TableOpt::Collate(s) => {
189                    sql.write_str("COLLATE=").unwrap();
190                    sql.write_str(s).unwrap();
191                }
192                TableOpt::CharacterSet(s) => {
193                    sql.write_str("DEFAULT CHARSET=").unwrap();
194                    sql.write_str(s).unwrap();
195                }
196            }
197        }
198    }
199
200    /// Translate [`TablePartition`] into SQL statement.
201    fn prepare_table_partition(
202        &self,
203        _table_partition: &TablePartition,
204        _sql: &mut impl SqlWriter,
205    ) {
206    }
207
208    /// Translate [`TableDropStatement`] into SQL statement.
209    fn prepare_table_drop_statement(&self, drop: &TableDropStatement, sql: &mut impl SqlWriter) {
210        sql.write_str("DROP TABLE ").unwrap();
211
212        if drop.if_exists {
213            sql.write_str("IF EXISTS ").unwrap();
214        }
215
216        let mut tables = drop.tables.iter();
217        join_io!(
218            tables,
219            table,
220            join {
221                sql.write_str(", ").unwrap();
222            },
223            do {
224                self.prepare_table_ref_table_stmt(table, sql);
225            }
226        );
227
228        for drop_opt in drop.options.iter() {
229            self.prepare_table_drop_opt(drop_opt, sql);
230        }
231    }
232
233    /// Translate [`TableDropOpt`] into SQL statement.
234    fn prepare_table_drop_opt(&self, drop_opt: &TableDropOpt, sql: &mut impl SqlWriter) {
235        match drop_opt {
236            TableDropOpt::Restrict => sql.write_str(" RESTRICT").unwrap(),
237            TableDropOpt::Cascade => sql.write_str(" CASCADE").unwrap(),
238        }
239    }
240
241    /// Translate [`TableTruncateStatement`] into SQL statement.
242    fn prepare_table_truncate_statement(
243        &self,
244        truncate: &TableTruncateStatement,
245        sql: &mut impl SqlWriter,
246    ) {
247        sql.write_str("TRUNCATE TABLE ").unwrap();
248
249        if let Some(table) = &truncate.table {
250            self.prepare_table_ref_table_stmt(table, sql);
251        }
252    }
253
254    /// Translate the check constraint into SQL statement
255    fn prepare_check_constraint(&self, check: &Check, sql: &mut impl SqlWriter) {
256        if let Some(name) = &check.name {
257            sql.write_str("CONSTRAINT ").unwrap();
258            self.prepare_iden(name, sql);
259            sql.write_str(" ").unwrap();
260        }
261
262        sql.write_str("CHECK (").unwrap();
263        QueryBuilder::prepare_expr(self, &check.expr, sql);
264        sql.write_str(")").unwrap();
265    }
266
267    /// Translate the generated column into SQL statement
268    fn prepare_generated_column(&self, r#gen: &Expr, stored: bool, sql: &mut impl SqlWriter) {
269        sql.write_str("GENERATED ALWAYS AS (").unwrap();
270        QueryBuilder::prepare_expr(self, r#gen, sql);
271        sql.write_str(")").unwrap();
272        if stored {
273            sql.write_str(" STORED").unwrap();
274        } else {
275            sql.write_str(" VIRTUAL").unwrap();
276        }
277    }
278
279    /// Translate IF NOT EXISTS expression in [`TableCreateStatement`].
280    fn prepare_create_table_if_not_exists(
281        &self,
282        create: &TableCreateStatement,
283        sql: &mut impl SqlWriter,
284    ) {
285        if create.if_not_exists {
286            sql.write_str("IF NOT EXISTS ").unwrap();
287        }
288    }
289
290    /// Translate TEMPORARY expression in [`TableCreateStatement`].
291    fn prepare_create_temporary_table(
292        &self,
293        create: &TableCreateStatement,
294        sql: &mut impl SqlWriter,
295    ) {
296        if create.temporary {
297            sql.write_str("TEMPORARY ").unwrap();
298        }
299    }
300
301    /// Translate [`TableAlterStatement`] into SQL statement.
302    fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut impl SqlWriter);
303
304    /// Translate [`TableRenameStatement`] into SQL statement.
305    fn prepare_table_rename_statement(
306        &self,
307        rename: &TableRenameStatement,
308        sql: &mut impl SqlWriter,
309    );
310}