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 dyn SqlWriter,
11    ) {
12        write!(sql, "CREATE ").unwrap();
13
14        self.prepare_create_temporary_table(create, sql);
15
16        write!(sql, "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        write!(sql, " ( ").unwrap();
25        let mut first = true;
26
27        create.columns.iter().for_each(|column_def| {
28            if !first {
29                write!(sql, ", ").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                write!(sql, ", ").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                write!(sql, ", ").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                write!(sql, ", ").unwrap();
54            }
55            self.prepare_check_constraint(check, sql);
56            first = false;
57        });
58
59        write!(sql, " )").unwrap();
60
61        self.prepare_table_opt(create, sql);
62
63        if let Some(extra) = &create.extra {
64            write!(sql, " {extra}").unwrap();
65        }
66    }
67
68    /// Translate [`TableRef`] into SQL statement.
69    fn prepare_table_ref_table_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
70        match table_ref {
71            TableRef::Table(_)
72            | TableRef::SchemaTable(_, _)
73            | TableRef::DatabaseSchemaTable(_, _, _) => 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 dyn 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 dyn 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 dyn SqlWriter);
93
94    /// Translate [`ColumnSpec`] into SQL statement.
95    fn prepare_column_spec(&self, column_spec: &ColumnSpec, sql: &mut dyn SqlWriter) {
96        match column_spec {
97            ColumnSpec::Null => write!(sql, "NULL").unwrap(),
98            ColumnSpec::NotNull => write!(sql, "NOT NULL").unwrap(),
99            ColumnSpec::Default(value) => {
100                write!(sql, "DEFAULT ").unwrap();
101                QueryBuilder::prepare_simple_expr(self, value, sql);
102            }
103            ColumnSpec::AutoIncrement => {
104                write!(sql, "{}", self.column_spec_auto_increment_keyword()).unwrap()
105            }
106            ColumnSpec::UniqueKey => write!(sql, "UNIQUE").unwrap(),
107            ColumnSpec::PrimaryKey => write!(sql, "PRIMARY KEY").unwrap(),
108            ColumnSpec::Check(check) => self.prepare_check_constraint(check, sql),
109            ColumnSpec::Generated { expr, stored } => {
110                self.prepare_generated_column(expr, *stored, sql)
111            }
112            ColumnSpec::Extra(string) => write!(sql, "{string}").unwrap(),
113            ColumnSpec::Comment(comment) => self.column_comment(comment, sql),
114            ColumnSpec::Using(_) => {}
115        }
116    }
117
118    /// column comment
119    fn column_comment(&self, _comment: &str, _sql: &mut dyn SqlWriter) {}
120
121    /// The keyword for setting a column to be auto increment.
122    fn column_spec_auto_increment_keyword(&self) -> &str;
123
124    /// Translate [`TableOpt`] into SQL statement.
125    fn prepare_table_opt(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
126        self.prepare_table_opt_def(create, sql)
127    }
128
129    /// Default function
130    fn prepare_table_opt_def(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
131        for table_opt in create.options.iter() {
132            write!(sql, " ").unwrap();
133            write!(
134                sql,
135                "{}",
136                match table_opt {
137                    TableOpt::Engine(s) => format!("ENGINE={s}"),
138                    TableOpt::Collate(s) => format!("COLLATE={s}"),
139                    TableOpt::CharacterSet(s) => format!("DEFAULT CHARSET={s}"),
140                }
141            )
142            .unwrap()
143        }
144    }
145
146    /// Translate [`TablePartition`] into SQL statement.
147    fn prepare_table_partition(&self, _table_partition: &TablePartition, _sql: &mut dyn SqlWriter) {
148    }
149
150    /// Translate [`TableDropStatement`] into SQL statement.
151    fn prepare_table_drop_statement(&self, drop: &TableDropStatement, sql: &mut dyn SqlWriter) {
152        write!(sql, "DROP TABLE ").unwrap();
153
154        if drop.if_exists {
155            write!(sql, "IF EXISTS ").unwrap();
156        }
157
158        drop.tables.iter().fold(true, |first, table| {
159            if !first {
160                write!(sql, ", ").unwrap();
161            }
162            self.prepare_table_ref_table_stmt(table, sql);
163            false
164        });
165
166        for drop_opt in drop.options.iter() {
167            self.prepare_table_drop_opt(drop_opt, sql);
168        }
169    }
170
171    /// Translate [`TableDropOpt`] into SQL statement.
172    fn prepare_table_drop_opt(&self, drop_opt: &TableDropOpt, sql: &mut dyn SqlWriter) {
173        write!(
174            sql,
175            " {}",
176            match drop_opt {
177                TableDropOpt::Restrict => "RESTRICT",
178                TableDropOpt::Cascade => "CASCADE",
179            }
180        )
181        .unwrap();
182    }
183
184    /// Translate [`TableTruncateStatement`] into SQL statement.
185    fn prepare_table_truncate_statement(
186        &self,
187        truncate: &TableTruncateStatement,
188        sql: &mut dyn SqlWriter,
189    ) {
190        write!(sql, "TRUNCATE TABLE ").unwrap();
191
192        if let Some(table) = &truncate.table {
193            self.prepare_table_ref_table_stmt(table, sql);
194        }
195    }
196
197    /// Translate the check constraint into SQL statement
198    fn prepare_check_constraint(&self, check: &SimpleExpr, sql: &mut dyn SqlWriter) {
199        write!(sql, "CHECK (").unwrap();
200        QueryBuilder::prepare_simple_expr(self, check, sql);
201        write!(sql, ")").unwrap();
202    }
203
204    /// Translate the generated column into SQL statement
205    fn prepare_generated_column(&self, gen: &SimpleExpr, stored: bool, sql: &mut dyn SqlWriter) {
206        write!(sql, "GENERATED ALWAYS AS (").unwrap();
207        QueryBuilder::prepare_simple_expr(self, gen, sql);
208        write!(sql, ")").unwrap();
209        if stored {
210            write!(sql, " STORED").unwrap();
211        } else {
212            write!(sql, " VIRTUAL").unwrap();
213        }
214    }
215
216    /// Translate IF NOT EXISTS expression in [`TableCreateStatement`].
217    fn prepare_create_table_if_not_exists(
218        &self,
219        create: &TableCreateStatement,
220        sql: &mut dyn SqlWriter,
221    ) {
222        if create.if_not_exists {
223            write!(sql, "IF NOT EXISTS ").unwrap();
224        }
225    }
226
227    /// Translate TEMPORARY expression in [`TableCreateStatement`].
228    fn prepare_create_temporary_table(
229        &self,
230        create: &TableCreateStatement,
231        sql: &mut dyn SqlWriter,
232    ) {
233        if create.temporary {
234            write!(sql, "TEMPORARY ").unwrap();
235        }
236    }
237
238    /// Translate [`TableAlterStatement`] into SQL statement.
239    fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut dyn SqlWriter);
240
241    /// Translate [`TableRenameStatement`] into SQL statement.
242    fn prepare_table_rename_statement(
243        &self,
244        rename: &TableRenameStatement,
245        sql: &mut dyn SqlWriter,
246    );
247}