Skip to main content

sea_query/table/
create.rs

1use crate::{
2    ColumnDef, Expr, IntoColumnDef, SchemaStatementBuilder, backend::SchemaBuilder, foreign_key::*,
3    index::*, table::constraint::Check, types::*,
4};
5
6/// Create a table
7///
8/// # Examples
9///
10/// ```
11/// use sea_query::{*, tests_cfg::*};
12///
13/// let table = Table::create()
14///     .table(Char::Table)
15///     .if_not_exists()
16///     .comment("table's comment")
17///     .col(ColumnDef::new(Char::Id).integer().not_null().auto_increment().primary_key())
18///     .col(ColumnDef::new(Char::FontSize).integer().not_null().comment("font's size"))
19///     .col(ColumnDef::new(Char::Character).string().not_null())
20///     .col(ColumnDef::new(Char::SizeW).integer().not_null())
21///     .col(ColumnDef::new(Char::SizeH).integer().not_null())
22///     .col(ColumnDef::new(Char::FontId).integer().default(Value::Int(None)))
23///     .foreign_key(
24///         ForeignKey::create()
25///             .name("FK_2e303c3a712662f1fc2a4d0aad6")
26///             .from(Char::Table, Char::FontId)
27///             .to(Font::Table, Font::Id)
28///             .on_delete(ForeignKeyAction::Cascade)
29///             .on_update(ForeignKeyAction::Cascade)
30///     )
31///     .to_owned();
32///
33/// assert_eq!(
34///     table.to_string(MysqlQueryBuilder),
35///     [
36///         r#"CREATE TABLE IF NOT EXISTS `character` ("#,
37///             r#"`id` int NOT NULL PRIMARY KEY AUTO_INCREMENT,"#,
38///             r#"`font_size` int NOT NULL COMMENT 'font\'s size',"#,
39///             r#"`character` varchar(255) NOT NULL,"#,
40///             r#"`size_w` int NOT NULL,"#,
41///             r#"`size_h` int NOT NULL,"#,
42///             r#"`font_id` int DEFAULT NULL,"#,
43///             r#"CONSTRAINT `FK_2e303c3a712662f1fc2a4d0aad6`"#,
44///                 r#"FOREIGN KEY (`font_id`) REFERENCES `font` (`id`)"#,
45///                 r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
46///         r#") COMMENT 'table\'s comment'"#,
47///     ].join(" ")
48/// );
49/// assert_eq!(
50///     table.to_string(PostgresQueryBuilder),
51///     [
52///         r#"CREATE TABLE IF NOT EXISTS "character" ("#,
53///             r#""id" integer GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,"#,
54///             r#""font_size" integer NOT NULL,"#,
55///             r#""character" varchar NOT NULL,"#,
56///             r#""size_w" integer NOT NULL,"#,
57///             r#""size_h" integer NOT NULL,"#,
58///             r#""font_id" integer DEFAULT NULL,"#,
59///             r#"CONSTRAINT "FK_2e303c3a712662f1fc2a4d0aad6""#,
60///                 r#"FOREIGN KEY ("font_id") REFERENCES "font" ("id")"#,
61///                 r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
62///         r#")"#,
63///     ].join(" ")
64/// );
65/// assert_eq!(
66///     table.to_string(SqliteQueryBuilder),
67///     [
68///        r#"CREATE TABLE IF NOT EXISTS "character" ("#,
69///            r#""id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"#,
70///            r#""font_size" integer NOT NULL,"#,
71///            r#""character" varchar NOT NULL,"#,
72///            r#""size_w" integer NOT NULL,"#,
73///            r#""size_h" integer NOT NULL,"#,
74///            r#""font_id" integer DEFAULT NULL,"#,
75///            r#"FOREIGN KEY ("font_id") REFERENCES "font" ("id") ON DELETE CASCADE ON UPDATE CASCADE"#,
76///        r#")"#,
77///     ].join(" ")
78/// );
79/// ```
80#[derive(Default, Debug, Clone)]
81pub struct TableCreateStatement {
82    pub(crate) table: Option<TableRef>,
83    pub(crate) columns: Vec<ColumnDef>,
84    pub(crate) options: Vec<TableOpt>,
85    pub(crate) partition_by: Option<PartitionBy>,
86    pub(crate) partition_of: Option<TableRef>,
87    pub(crate) partition_values: Option<PartitionValues>,
88    pub(crate) partitions: Vec<PartitionDefinition>,
89    pub(crate) indexes: Vec<IndexCreateStatement>,
90    pub(crate) foreign_keys: Vec<ForeignKeyCreateStatement>,
91    pub(crate) if_not_exists: bool,
92    pub(crate) check: Vec<Check>,
93    pub(crate) comment: Option<String>,
94    pub(crate) extra: Option<String>,
95    pub(crate) temporary: bool,
96}
97
98/// All available table options
99#[derive(Debug, Clone)]
100#[non_exhaustive]
101pub enum TableOpt {
102    Engine(String),
103    Collate(String),
104    CharacterSet(String),
105}
106
107/// All available table partition options
108#[derive(Debug, Clone)]
109pub enum PartitionBy {
110    Range(Vec<DynIden>),
111    List(Vec<DynIden>),
112    Hash(Vec<DynIden>),
113    Key(Vec<DynIden>),
114}
115
116#[derive(Debug, Clone)]
117pub enum PartitionValues {
118    In(Vec<Expr>),
119    FromTo(Vec<Expr>, Vec<Expr>),
120    LessThan(Vec<Expr>),
121    With(u32, u32),
122}
123
124#[derive(Debug, Clone)]
125pub(crate) struct PartitionDefinition {
126    pub(crate) name: DynIden,
127    pub(crate) values: Option<PartitionValues>,
128}
129
130impl TableCreateStatement {
131    /// Construct create table statement
132    pub fn new() -> Self {
133        Self::default()
134    }
135
136    /// Create table if table not exists
137    pub fn if_not_exists(&mut self) -> &mut Self {
138        self.if_not_exists = true;
139        self
140    }
141
142    /// Set table name
143    pub fn table<T>(&mut self, table: T) -> &mut Self
144    where
145        T: IntoTableRef,
146    {
147        self.table = Some(table.into_table_ref());
148        self
149    }
150
151    /// Set table comment
152    pub fn comment<T>(&mut self, comment: T) -> &mut Self
153    where
154        T: Into<String>,
155    {
156        self.comment = Some(comment.into());
157        self
158    }
159
160    /// Add a new table column
161    pub fn col<C: IntoColumnDef>(&mut self, column: C) -> &mut Self {
162        let mut column = column.into_column_def();
163        column.table.clone_from(&self.table);
164        self.columns.push(column);
165        self
166    }
167
168    pub fn check<T>(&mut self, value: T) -> &mut Self
169    where
170        T: Into<Check>,
171    {
172        self.check.push(value.into());
173        self
174    }
175
176    /// Add an index. MySQL only.
177    ///
178    /// # Examples
179    ///
180    /// ```
181    /// use sea_query::{tests_cfg::*, *};
182    ///
183    /// assert_eq!(
184    ///     Table::create()
185    ///         .table(Glyph::Table)
186    ///         .col(ColumnDef::new(Glyph::Id).integer().not_null())
187    ///         .index(Index::create().unique().name("idx-glyph-id").col(Glyph::Id))
188    ///         .to_string(MysqlQueryBuilder),
189    ///     [
190    ///         "CREATE TABLE `glyph` (",
191    ///         "`id` int NOT NULL,",
192    ///         "UNIQUE KEY `idx-glyph-id` (`id`)",
193    ///         ")",
194    ///     ]
195    ///     .join(" ")
196    /// );
197    /// ```
198    pub fn index(&mut self, index: &mut IndexCreateStatement) -> &mut Self {
199        self.indexes.push(index.take());
200        self
201    }
202
203    /// Add an primary key.
204    ///
205    /// # Examples
206    ///
207    /// ```
208    /// use sea_query::{tests_cfg::*, *};
209    ///
210    /// let mut statement = Table::create();
211    /// statement
212    ///     .table(Glyph::Table)
213    ///     .col(ColumnDef::new(Glyph::Id).integer().not_null())
214    ///     .col(ColumnDef::new(Glyph::Image).string().not_null())
215    ///     .primary_key(Index::create().col(Glyph::Id).col(Glyph::Image));
216    /// assert_eq!(
217    ///     statement.to_string(MysqlQueryBuilder),
218    ///     [
219    ///         "CREATE TABLE `glyph` (",
220    ///         "`id` int NOT NULL,",
221    ///         "`image` varchar(255) NOT NULL,",
222    ///         "PRIMARY KEY (`id`, `image`)",
223    ///         ")",
224    ///     ]
225    ///     .join(" ")
226    /// );
227    /// assert_eq!(
228    ///     statement.to_string(PostgresQueryBuilder),
229    ///     [
230    ///         "CREATE TABLE \"glyph\" (",
231    ///         "\"id\" integer NOT NULL,",
232    ///         "\"image\" varchar NOT NULL,",
233    ///         "PRIMARY KEY (\"id\", \"image\")",
234    ///         ")",
235    ///     ]
236    ///     .join(" ")
237    /// );
238    /// assert_eq!(
239    ///     statement.to_string(SqliteQueryBuilder),
240    ///     [
241    ///         r#"CREATE TABLE "glyph" ("#,
242    ///         r#""id" integer NOT NULL,"#,
243    ///         r#""image" varchar NOT NULL,"#,
244    ///         r#"PRIMARY KEY ("id", "image")"#,
245    ///         r#")"#,
246    ///     ]
247    ///     .join(" ")
248    /// );
249    /// ```
250    pub fn primary_key(&mut self, index: &mut IndexCreateStatement) -> &mut Self {
251        let mut index = index.take();
252        index.primary = true;
253        self.indexes.push(index);
254        self
255    }
256
257    /// Add a foreign key
258    pub fn foreign_key(&mut self, foreign_key: &mut ForeignKeyCreateStatement) -> &mut Self {
259        self.foreign_keys.push(foreign_key.take());
260        self
261    }
262
263    /// Set database engine. MySQL only.
264    pub fn engine<T>(&mut self, string: T) -> &mut Self
265    where
266        T: Into<String>,
267    {
268        self.opt(TableOpt::Engine(string.into()));
269        self
270    }
271
272    /// Set database collate. MySQL only.
273    pub fn collate<T>(&mut self, string: T) -> &mut Self
274    where
275        T: Into<String>,
276    {
277        self.opt(TableOpt::Collate(string.into()));
278        self
279    }
280
281    /// Set database character set. MySQL only.
282    pub fn character_set<T>(&mut self, name: T) -> &mut Self
283    where
284        T: Into<String>,
285    {
286        self.opt(TableOpt::CharacterSet(name.into()));
287        self
288    }
289
290    fn opt(&mut self, option: TableOpt) -> &mut Self {
291        self.options.push(option);
292        self
293    }
294
295    #[allow(dead_code)]
296    fn partition(&mut self, partition: PartitionDefinition) -> &mut Self {
297        self.partitions.push(partition);
298        self
299    }
300
301    /// Set partition by range. Postgres and MySQL only.
302    ///
303    /// # Examples
304    ///
305    /// ```
306    /// use sea_query::{tests_cfg::*, *};
307    ///
308    /// assert_eq!(
309    ///     Table::create()
310    ///         .table(Glyph::Table)
311    ///         .col(ColumnDef::new(Glyph::Id).integer().not_null())
312    ///         .partition_by_range([Glyph::Id])
313    ///         .to_string(PostgresQueryBuilder),
314    ///     r#"CREATE TABLE "glyph" ( "id" integer NOT NULL ) PARTITION BY RANGE ("id")"#
315    /// );
316    /// ```
317    pub fn partition_by_range<I, T>(&mut self, cols: I) -> &mut Self
318    where
319        I: IntoIterator<Item = T>,
320        T: IntoIden,
321    {
322        self.partition_by = Some(PartitionBy::Range(
323            cols.into_iter().map(|c| c.into_iden()).collect(),
324        ));
325        self
326    }
327
328    /// Set partition by list. Postgres and MySQL only.
329    ///
330    /// # Examples
331    ///
332    /// ```
333    /// use sea_query::{tests_cfg::*, *};
334    ///
335    /// assert_eq!(
336    ///     Table::create()
337    ///         .table(Glyph::Table)
338    ///         .col(ColumnDef::new(Glyph::Id).integer().not_null())
339    ///         .partition_by_list([Glyph::Id])
340    ///         .to_string(PostgresQueryBuilder),
341    ///     r#"CREATE TABLE "glyph" ( "id" integer NOT NULL ) PARTITION BY LIST ("id")"#
342    /// );
343    /// ```
344    pub fn partition_by_list<I, T>(&mut self, cols: I) -> &mut Self
345    where
346        I: IntoIterator<Item = T>,
347        T: IntoIden,
348    {
349        self.partition_by = Some(PartitionBy::List(
350            cols.into_iter().map(|c| c.into_iden()).collect(),
351        ));
352        self
353    }
354
355    /// Set partition by hash. Postgres and MySQL only.
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// use sea_query::{tests_cfg::*, *};
361    ///
362    /// assert_eq!(
363    ///     Table::create()
364    ///         .table(Glyph::Table)
365    ///         .col(ColumnDef::new(Glyph::Id).integer().not_null())
366    ///         .partition_by_hash([Glyph::Id])
367    ///         .to_string(PostgresQueryBuilder),
368    ///     r#"CREATE TABLE "glyph" ( "id" integer NOT NULL ) PARTITION BY HASH ("id")"#
369    /// );
370    /// ```
371    pub fn partition_by_hash<I, T>(&mut self, cols: I) -> &mut Self
372    where
373        I: IntoIterator<Item = T>,
374        T: IntoIden,
375    {
376        self.partition_by = Some(PartitionBy::Hash(
377            cols.into_iter().map(|c| c.into_iden()).collect(),
378        ));
379        self
380    }
381
382    /// Set partition by key. MySQL only.
383    ///
384    /// # Examples
385    ///
386    /// ```
387    /// use sea_query::{tests_cfg::*, *};
388    ///
389    /// assert_eq!(
390    ///     Table::create()
391    ///         .table(Glyph::Table)
392    ///         .col(ColumnDef::new(Glyph::Id).integer().not_null())
393    ///         .partition_by_key([Glyph::Id])
394    ///         .to_string(MysqlQueryBuilder),
395    ///     "CREATE TABLE `glyph` ( `id` int NOT NULL ) PARTITION BY KEY (`id`)"
396    /// );
397    /// ```
398    pub fn partition_by_key<I, T>(&mut self, cols: I) -> &mut Self
399    where
400        I: IntoIterator<Item = T>,
401        T: IntoIden,
402    {
403        self.partition_by = Some(PartitionBy::Key(
404            cols.into_iter().map(|c| c.into_iden()).collect(),
405        ));
406        self
407    }
408
409    /// Set partition of table. Postgres only.
410    ///
411    /// # Examples
412    ///
413    /// ```
414    /// use sea_query::{tests_cfg::*, *};
415    ///
416    /// assert_eq!(
417    ///     Table::create()
418    ///         .table(Alias::new("glyph_1"))
419    ///         .partition_of(Glyph::Table)
420    ///         .values_from_to([1], [10])
421    ///         .to_string(PostgresQueryBuilder),
422    ///     r#"CREATE TABLE "glyph_1" PARTITION OF "glyph" FOR VALUES FROM (1) TO (10)"#
423    /// );
424    /// ```
425    pub fn partition_of<T>(&mut self, table: T) -> &mut Self
426    where
427        T: IntoTableRef,
428    {
429        self.partition_of = Some(table.into_table_ref());
430        self
431    }
432
433    /// Set partition values IN. Postgres partition tables only.
434    ///
435    /// MySQL partition definitions can use [`PartitionValues::In`] with
436    /// [`Self::add_partition`].
437    ///
438    /// # Examples
439    ///
440    /// ```
441    /// use sea_query::{tests_cfg::*, *};
442    ///
443    /// assert_eq!(
444    ///     Table::create()
445    ///         .table(Alias::new("glyph_1"))
446    ///         .partition_of(Glyph::Table)
447    ///         .values_in([1, 2, 3])
448    ///         .to_string(PostgresQueryBuilder),
449    ///     r#"CREATE TABLE "glyph_1" PARTITION OF "glyph" FOR VALUES IN (1, 2, 3)"#
450    /// );
451    /// ```
452    pub fn values_in<I, T>(&mut self, values: I) -> &mut Self
453    where
454        I: IntoIterator<Item = T>,
455        T: Into<Expr>,
456    {
457        self.partition_values = Some(PartitionValues::In(
458            values.into_iter().map(|v| v.into()).collect(),
459        ));
460        self
461    }
462
463    /// Set partition values FROM ... TO .... Postgres only.
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// use sea_query::{tests_cfg::*, *};
469    ///
470    /// assert_eq!(
471    ///     Table::create()
472    ///         .table(Alias::new("glyph_1"))
473    ///         .partition_of(Glyph::Table)
474    ///         .values_from_to([1], [10])
475    ///         .to_string(PostgresQueryBuilder),
476    ///     r#"CREATE TABLE "glyph_1" PARTITION OF "glyph" FOR VALUES FROM (1) TO (10)"#
477    /// );
478    /// ```
479    pub fn values_from_to<I, T, J, U>(&mut self, from: I, to: J) -> &mut Self
480    where
481        I: IntoIterator<Item = T>,
482        T: Into<Expr>,
483        J: IntoIterator<Item = U>,
484        U: Into<Expr>,
485    {
486        self.partition_values = Some(PartitionValues::FromTo(
487            from.into_iter().map(|v| v.into()).collect(),
488            to.into_iter().map(|v| v.into()).collect(),
489        ));
490        self
491    }
492
493    /// Set partition values LESS THAN. MySQL partition definitions only.
494    ///
495    /// Use [`PartitionValues::LessThan`] with [`Self::add_partition`] for MySQL
496    /// table partition definitions.
497    pub fn values_less_than<I, T>(&mut self, values: I) -> &mut Self
498    where
499        I: IntoIterator<Item = T>,
500        T: Into<Expr>,
501    {
502        self.partition_values = Some(PartitionValues::LessThan(
503            values.into_iter().map(|v| v.into()).collect(),
504        ));
505        self
506    }
507
508    /// Set partition values WITH (modulus, remainder). Postgres only.
509    ///
510    /// # Examples
511    ///
512    /// ```
513    /// use sea_query::{tests_cfg::*, *};
514    ///
515    /// assert_eq!(
516    ///     Table::create()
517    ///         .table(Alias::new("glyph_p1"))
518    ///         .partition_of(Glyph::Table)
519    ///         .values_with(4, 0)
520    ///         .to_string(PostgresQueryBuilder),
521    ///     r#"CREATE TABLE "glyph_p1" PARTITION OF "glyph" FOR VALUES WITH (MODULUS 4, REMAINDER 0)"#
522    /// );
523    /// ```
524    pub fn values_with(&mut self, modulus: u32, remainder: u32) -> &mut Self {
525        self.partition_values = Some(PartitionValues::With(modulus, remainder));
526        self
527    }
528
529    /// Add a partition definition. MySQL only.
530    ///
531    /// # Examples
532    ///
533    /// ```
534    /// use sea_query::{tests_cfg::*, *};
535    ///
536    /// assert_eq!(
537    ///     Table::create()
538    ///         .table(Glyph::Table)
539    ///         .col(ColumnDef::new(Glyph::Id).integer().not_null())
540    ///         .partition_by_range([Glyph::Id])
541    ///         .add_partition(
542    ///             Alias::new("p0"),
543    ///             Some(PartitionValues::LessThan(vec![10.into()]))
544    ///         )
545    ///         .to_string(MysqlQueryBuilder),
546    ///     "CREATE TABLE `glyph` ( `id` int NOT NULL ) PARTITION BY RANGE (`id`) ( PARTITION `p0` VALUES LESS THAN (10) )"
547    /// );
548    /// ```
549    pub fn add_partition<T>(&mut self, name: T, values: Option<PartitionValues>) -> &mut Self
550    where
551        T: IntoIden,
552    {
553        self.partitions.push(PartitionDefinition {
554            name: name.into_iden(),
555            values,
556        });
557        self
558    }
559
560    pub fn get_table_name(&self) -> Option<&TableRef> {
561        self.table.as_ref()
562    }
563
564    pub fn get_columns(&self) -> &Vec<ColumnDef> {
565        self.columns.as_ref()
566    }
567
568    pub fn get_comment(&self) -> Option<&String> {
569        self.comment.as_ref()
570    }
571
572    pub fn get_foreign_key_create_stmts(&self) -> &Vec<ForeignKeyCreateStatement> {
573        self.foreign_keys.as_ref()
574    }
575
576    pub fn get_indexes(&self) -> &Vec<IndexCreateStatement> {
577        self.indexes.as_ref()
578    }
579
580    /// Rewriting extra param. You should take care self about concat extra params. Add extra after options.
581    /// Example for PostgresSQL [Citus](https://github.com/citusdata/citus) extension:
582    /// ```
583    /// use sea_query::{tests_cfg::*, *};
584    /// let table = Table::create()
585    ///     .table(Char::Table)
586    ///     .col(
587    ///         ColumnDef::new(Char::Id)
588    ///             .uuid()
589    ///             .extra("DEFAULT uuid_generate_v4()")
590    ///             .primary_key()
591    ///             .not_null(),
592    ///     )
593    ///     .col(
594    ///         ColumnDef::new(Char::CreatedAt)
595    ///             .timestamp_with_time_zone()
596    ///             .extra("DEFAULT NOW()")
597    ///             .not_null(),
598    ///     )
599    ///     .col(ColumnDef::new(Char::UserData).json_binary().not_null())
600    ///     .extra("USING columnar")
601    ///     .take();
602    /// assert_eq!(
603    ///     table.to_string(PostgresQueryBuilder),
604    ///     [
605    ///         r#"CREATE TABLE "character" ("#,
606    ///         r#""id" uuid NOT NULL PRIMARY KEY DEFAULT uuid_generate_v4(),"#,
607    ///         r#""created_at" timestamp with time zone NOT NULL DEFAULT NOW(),"#,
608    ///         r#""user_data" jsonb NOT NULL"#,
609    ///         r#") USING columnar"#,
610    ///     ]
611    ///     .join(" ")
612    /// );
613    /// ```
614    pub fn extra<T>(&mut self, extra: T) -> &mut Self
615    where
616        T: Into<String>,
617    {
618        self.extra = Some(extra.into());
619        self
620    }
621
622    pub fn get_extra(&self) -> Option<&String> {
623        self.extra.as_ref()
624    }
625
626    /// Create temporary table
627    ///
628    /// Ref:
629    /// - PostgreSQL: <https://www.postgresql.org/docs/17/sql-createtable.html#SQL-CREATETABLE-TEMPORARY>
630    /// - MySQL: <https://dev.mysql.com/doc/refman/9.2/en/create-temporary-table.html>
631    /// - MariaDB: <https://mariadb.com/kb/en/create-table/#create-temporary-table>
632    /// - SQLite: <https://sqlite.org/lang_createtable.html>
633    ///
634    /// # Examples
635    ///
636    /// ```
637    /// use sea_query::{tests_cfg::*, *};
638    ///
639    /// let statement = Table::create()
640    ///     .table(Font::Table)
641    ///     .temporary()
642    ///     .col(
643    ///         ColumnDef::new(Font::Id)
644    ///             .integer()
645    ///             .not_null()
646    ///             .primary_key()
647    ///             .auto_increment(),
648    ///     )
649    ///     .col(ColumnDef::new(Font::Name).string().not_null())
650    ///     .take();
651    ///
652    /// assert_eq!(
653    ///     statement.to_string(MysqlQueryBuilder),
654    ///     [
655    ///         "CREATE TEMPORARY TABLE `font` (",
656    ///         "`id` int NOT NULL PRIMARY KEY AUTO_INCREMENT,",
657    ///         "`name` varchar(255) NOT NULL",
658    ///         ")",
659    ///     ]
660    ///     .join(" ")
661    /// );
662    /// assert_eq!(
663    ///     statement.to_string(PostgresQueryBuilder),
664    ///     [
665    ///         r#"CREATE TEMPORARY TABLE "font" ("#,
666    ///         r#""id" integer GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,"#,
667    ///         r#""name" varchar NOT NULL"#,
668    ///         r#")"#,
669    ///     ]
670    ///     .join(" ")
671    /// );
672    /// assert_eq!(
673    ///     statement.to_string(SqliteQueryBuilder),
674    ///     [
675    ///         r#"CREATE TEMPORARY TABLE "font" ("#,
676    ///         r#""id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"#,
677    ///         r#""name" varchar NOT NULL"#,
678    ///         r#")"#,
679    ///     ]
680    ///     .join(" ")
681    /// );
682    /// ```
683    pub fn temporary(&mut self) -> &mut Self {
684        self.temporary = true;
685        self
686    }
687
688    pub fn take(&mut self) -> Self {
689        Self {
690            table: self.table.take(),
691            columns: std::mem::take(&mut self.columns),
692            options: std::mem::take(&mut self.options),
693            partition_by: self.partition_by.take(),
694            partition_of: self.partition_of.take(),
695            partition_values: self.partition_values.take(),
696            partitions: std::mem::take(&mut self.partitions),
697            indexes: std::mem::take(&mut self.indexes),
698            foreign_keys: std::mem::take(&mut self.foreign_keys),
699            if_not_exists: self.if_not_exists,
700            check: std::mem::take(&mut self.check),
701            comment: std::mem::take(&mut self.comment),
702            extra: std::mem::take(&mut self.extra),
703            temporary: self.temporary,
704        }
705    }
706}
707
708impl SchemaStatementBuilder for TableCreateStatement {
709    fn build<T: SchemaBuilder>(&self, schema_builder: T) -> String {
710        let mut sql = String::with_capacity(256);
711        schema_builder.prepare_table_create_statement(self, &mut sql);
712        sql
713    }
714}
715
716impl TableCreateStatement {
717    pub fn build<T: SchemaBuilder>(&self, schema_builder: T) -> String {
718        <Self as SchemaStatementBuilder>::build(self, schema_builder)
719    }
720
721    pub fn to_string<T: SchemaBuilder>(&self, schema_builder: T) -> String {
722        <Self as SchemaStatementBuilder>::to_string(self, schema_builder)
723    }
724}