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 TABLE ").unwrap();
13
14        self.prepare_create_table_if_not_exists(create, sql);
15
16        if let Some(table_ref) = &create.table {
17            self.prepare_table_ref_table_stmt(table_ref, sql);
18        }
19
20        write!(sql, " ( ").unwrap();
21        let mut first = true;
22
23        create.columns.iter().for_each(|column_def| {
24            if !first {
25                write!(sql, ", ").unwrap();
26            }
27            self.prepare_column_def(column_def, sql);
28            first = false;
29        });
30
31        create.indexes.iter().for_each(|index| {
32            if !first {
33                write!(sql, ", ").unwrap();
34            }
35            self.prepare_table_index_expression(index, sql);
36            first = false;
37        });
38
39        create.foreign_keys.iter().for_each(|foreign_key| {
40            if !first {
41                write!(sql, ", ").unwrap();
42            }
43            self.prepare_foreign_key_create_statement_internal(foreign_key, sql, Mode::Creation);
44            first = false;
45        });
46
47        create.check.iter().for_each(|check| {
48            if !first {
49                write!(sql, ", ").unwrap();
50            }
51            self.prepare_check_constraint(check, sql);
52            first = false;
53        });
54
55        write!(sql, " )").unwrap();
56
57        self.prepare_table_opt(create, sql);
58
59        if let Some(extra) = &create.extra {
60            write!(sql, " {extra}").unwrap();
61        }
62    }
63
64    /// Translate [`TableRef`] into SQL statement.
65    fn prepare_table_ref_table_stmt(&self, table_ref: &TableRef, sql: &mut dyn SqlWriter) {
66        match table_ref {
67            TableRef::Table(_)
68            | TableRef::SchemaTable(_, _)
69            | TableRef::DatabaseSchemaTable(_, _, _) => self.prepare_table_ref_iden(table_ref, sql),
70            _ => panic!("Not supported"),
71        }
72    }
73
74    /// Translate [`ColumnDef`] into SQL statement.
75    fn prepare_column_def(&self, column_def: &ColumnDef, sql: &mut dyn SqlWriter);
76
77    /// Translate [`ColumnDef`] into SQL statement.
78    fn prepare_column_def_internal(
79        &self,
80        _is_alter_column: bool,
81        column_def: &ColumnDef,
82        sql: &mut dyn SqlWriter,
83    ) {
84        self.prepare_column_def(column_def, sql);
85    }
86
87    /// Translate [`ColumnType`] into SQL statement.
88    fn prepare_column_type(&self, column_type: &ColumnType, sql: &mut dyn SqlWriter);
89
90    /// Translate [`ColumnSpec`] into SQL statement.
91    fn prepare_column_spec(&self, column_spec: &ColumnSpec, sql: &mut dyn SqlWriter) {
92        match column_spec {
93            ColumnSpec::Null => write!(sql, "NULL").unwrap(),
94            ColumnSpec::NotNull => write!(sql, "NOT NULL").unwrap(),
95            ColumnSpec::Default(value) => {
96                write!(sql, "DEFAULT ").unwrap();
97                QueryBuilder::prepare_simple_expr(self, value, sql);
98            }
99            ColumnSpec::AutoIncrement => {
100                write!(sql, "{}", self.column_spec_auto_increment_keyword()).unwrap()
101            }
102            ColumnSpec::UniqueKey => write!(sql, "UNIQUE").unwrap(),
103            ColumnSpec::PrimaryKey => write!(sql, "PRIMARY KEY").unwrap(),
104            ColumnSpec::Check(check) => self.prepare_check_constraint(check, sql),
105            ColumnSpec::Generated { expr, stored } => {
106                self.prepare_generated_column(expr, *stored, sql)
107            }
108            ColumnSpec::Extra(string) => write!(sql, "{string}").unwrap(),
109            ColumnSpec::Comment(comment) => self.column_comment(comment, sql),
110        }
111    }
112
113    /// column comment
114    fn column_comment(&self, _comment: &str, _sql: &mut dyn SqlWriter) {}
115
116    /// The keyword for setting a column to be auto increment.
117    fn column_spec_auto_increment_keyword(&self) -> &str;
118
119    /// Translate [`TableOpt`] into SQL statement.
120    fn prepare_table_opt(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
121        self.prepare_table_opt_def(create, sql)
122    }
123
124    /// Default function
125    fn prepare_table_opt_def(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
126        for table_opt in create.options.iter() {
127            write!(sql, " ").unwrap();
128            write!(
129                sql,
130                "{}",
131                match table_opt {
132                    TableOpt::Engine(s) => format!("ENGINE={s}"),
133                    TableOpt::Collate(s) => format!("COLLATE={s}"),
134                    TableOpt::CharacterSet(s) => format!("DEFAULT CHARSET={s}"),
135                }
136            )
137            .unwrap()
138        }
139    }
140
141    /// Translate [`TablePartition`] into SQL statement.
142    fn prepare_table_partition(&self, _table_partition: &TablePartition, _sql: &mut dyn SqlWriter) {
143    }
144
145    /// Translate [`TableDropStatement`] into SQL statement.
146    fn prepare_table_drop_statement(&self, drop: &TableDropStatement, sql: &mut dyn SqlWriter) {
147        write!(sql, "DROP TABLE ").unwrap();
148
149        if drop.if_exists {
150            write!(sql, "IF EXISTS ").unwrap();
151        }
152
153        drop.tables.iter().fold(true, |first, table| {
154            if !first {
155                write!(sql, ", ").unwrap();
156            }
157            self.prepare_table_ref_table_stmt(table, sql);
158            false
159        });
160
161        for drop_opt in drop.options.iter() {
162            self.prepare_table_drop_opt(drop_opt, sql);
163        }
164    }
165
166    /// Translate [`TableDropOpt`] into SQL statement.
167    fn prepare_table_drop_opt(&self, drop_opt: &TableDropOpt, sql: &mut dyn SqlWriter) {
168        write!(
169            sql,
170            " {}",
171            match drop_opt {
172                TableDropOpt::Restrict => "RESTRICT",
173                TableDropOpt::Cascade => "CASCADE",
174            }
175        )
176        .unwrap();
177    }
178
179    /// Translate [`TableTruncateStatement`] into SQL statement.
180    fn prepare_table_truncate_statement(
181        &self,
182        truncate: &TableTruncateStatement,
183        sql: &mut dyn SqlWriter,
184    ) {
185        write!(sql, "TRUNCATE TABLE ").unwrap();
186
187        if let Some(table) = &truncate.table {
188            self.prepare_table_ref_table_stmt(table, sql);
189        }
190    }
191
192    /// Translate the check constraint into SQL statement
193    fn prepare_check_constraint(&self, check: &SimpleExpr, sql: &mut dyn SqlWriter) {
194        write!(sql, "CHECK (").unwrap();
195        QueryBuilder::prepare_simple_expr(self, check, sql);
196        write!(sql, ")").unwrap();
197    }
198
199    /// Translate the generated column into SQL statement
200    fn prepare_generated_column(&self, gen: &SimpleExpr, stored: bool, sql: &mut dyn SqlWriter) {
201        write!(sql, "GENERATED ALWAYS AS (").unwrap();
202        QueryBuilder::prepare_simple_expr(self, gen, sql);
203        write!(sql, ")").unwrap();
204        if stored {
205            write!(sql, " STORED").unwrap();
206        } else {
207            write!(sql, " VIRTUAL").unwrap();
208        }
209    }
210
211    /// Translate IF NOT EXISTS expression in [`TableCreateStatement`].
212    fn prepare_create_table_if_not_exists(
213        &self,
214        create: &TableCreateStatement,
215        sql: &mut dyn SqlWriter,
216    ) {
217        if create.if_not_exists {
218            write!(sql, "IF NOT EXISTS ").unwrap();
219        }
220    }
221
222    /// Translate [`TableAlterStatement`] into SQL statement.
223    fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut dyn SqlWriter);
224
225    /// Translate [`TableRenameStatement`] into SQL statement.
226    fn prepare_table_rename_statement(
227        &self,
228        rename: &TableRenameStatement,
229        sql: &mut dyn SqlWriter,
230    );
231}