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            ColumnSpec::Using(_) => {}
111        }
112    }
113
114    /// column comment
115    fn column_comment(&self, _comment: &str, _sql: &mut dyn SqlWriter) {}
116
117    /// The keyword for setting a column to be auto increment.
118    fn column_spec_auto_increment_keyword(&self) -> &str;
119
120    /// Translate [`TableOpt`] into SQL statement.
121    fn prepare_table_opt(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
122        self.prepare_table_opt_def(create, sql)
123    }
124
125    /// Default function
126    fn prepare_table_opt_def(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
127        for table_opt in create.options.iter() {
128            write!(sql, " ").unwrap();
129            write!(
130                sql,
131                "{}",
132                match table_opt {
133                    TableOpt::Engine(s) => format!("ENGINE={s}"),
134                    TableOpt::Collate(s) => format!("COLLATE={s}"),
135                    TableOpt::CharacterSet(s) => format!("DEFAULT CHARSET={s}"),
136                }
137            )
138            .unwrap()
139        }
140    }
141
142    /// Translate [`TablePartition`] into SQL statement.
143    fn prepare_table_partition(&self, _table_partition: &TablePartition, _sql: &mut dyn SqlWriter) {
144    }
145
146    /// Translate [`TableDropStatement`] into SQL statement.
147    fn prepare_table_drop_statement(&self, drop: &TableDropStatement, sql: &mut dyn SqlWriter) {
148        write!(sql, "DROP TABLE ").unwrap();
149
150        if drop.if_exists {
151            write!(sql, "IF EXISTS ").unwrap();
152        }
153
154        drop.tables.iter().fold(true, |first, table| {
155            if !first {
156                write!(sql, ", ").unwrap();
157            }
158            self.prepare_table_ref_table_stmt(table, sql);
159            false
160        });
161
162        for drop_opt in drop.options.iter() {
163            self.prepare_table_drop_opt(drop_opt, sql);
164        }
165    }
166
167    /// Translate [`TableDropOpt`] into SQL statement.
168    fn prepare_table_drop_opt(&self, drop_opt: &TableDropOpt, sql: &mut dyn SqlWriter) {
169        write!(
170            sql,
171            " {}",
172            match drop_opt {
173                TableDropOpt::Restrict => "RESTRICT",
174                TableDropOpt::Cascade => "CASCADE",
175            }
176        )
177        .unwrap();
178    }
179
180    /// Translate [`TableTruncateStatement`] into SQL statement.
181    fn prepare_table_truncate_statement(
182        &self,
183        truncate: &TableTruncateStatement,
184        sql: &mut dyn SqlWriter,
185    ) {
186        write!(sql, "TRUNCATE TABLE ").unwrap();
187
188        if let Some(table) = &truncate.table {
189            self.prepare_table_ref_table_stmt(table, sql);
190        }
191    }
192
193    /// Translate the check constraint into SQL statement
194    fn prepare_check_constraint(&self, check: &SimpleExpr, sql: &mut dyn SqlWriter) {
195        write!(sql, "CHECK (").unwrap();
196        QueryBuilder::prepare_simple_expr(self, check, sql);
197        write!(sql, ")").unwrap();
198    }
199
200    /// Translate the generated column into SQL statement
201    fn prepare_generated_column(&self, gen: &SimpleExpr, stored: bool, sql: &mut dyn SqlWriter) {
202        write!(sql, "GENERATED ALWAYS AS (").unwrap();
203        QueryBuilder::prepare_simple_expr(self, gen, sql);
204        write!(sql, ")").unwrap();
205        if stored {
206            write!(sql, " STORED").unwrap();
207        } else {
208            write!(sql, " VIRTUAL").unwrap();
209        }
210    }
211
212    /// Translate IF NOT EXISTS expression in [`TableCreateStatement`].
213    fn prepare_create_table_if_not_exists(
214        &self,
215        create: &TableCreateStatement,
216        sql: &mut dyn SqlWriter,
217    ) {
218        if create.if_not_exists {
219            write!(sql, "IF NOT EXISTS ").unwrap();
220        }
221    }
222
223    /// Translate [`TableAlterStatement`] into SQL statement.
224    fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut dyn SqlWriter);
225
226    /// Translate [`TableRenameStatement`] into SQL statement.
227    fn prepare_table_rename_statement(
228        &self,
229        rename: &TableRenameStatement,
230        sql: &mut dyn SqlWriter,
231    );
232}