sea_query/backend/mysql/
table.rs

1use super::*;
2
3impl TableBuilder for MysqlQueryBuilder {
4    fn prepare_table_opt(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
5        // comment
6        if let Some(comment) = &create.comment {
7            let comment = self.escape_string(comment);
8            write!(sql, " COMMENT '{comment}'").unwrap();
9        }
10        self.prepare_table_opt_def(create, sql)
11    }
12
13    fn prepare_column_def(&self, column_def: &ColumnDef, sql: &mut dyn SqlWriter) {
14        column_def.name.prepare(sql.as_writer(), self.quote());
15
16        if let Some(column_type) = &column_def.types {
17            write!(sql, " ").unwrap();
18            self.prepare_column_type(column_type, sql);
19        }
20
21        for column_spec in column_def.spec.iter() {
22            write!(sql, " ").unwrap();
23            self.prepare_column_spec(column_spec, sql);
24        }
25    }
26
27    fn prepare_column_type(&self, column_type: &ColumnType, sql: &mut dyn SqlWriter) {
28        write!(
29            sql,
30            "{}",
31            match column_type {
32                ColumnType::Char(length) => match length {
33                    Some(length) => format!("char({length})"),
34                    None => "char".into(),
35                },
36                ColumnType::String(length) => match length {
37                    StringLen::N(length) => format!("varchar({length})"),
38                    StringLen::None => "varchar(255)".into(),
39                    StringLen::Max => "varchar(65535)".into(),
40                },
41                ColumnType::Text => "text".into(),
42                ColumnType::TinyInteger | ColumnType::TinyUnsigned => "tinyint".into(),
43                ColumnType::SmallInteger | ColumnType::SmallUnsigned => "smallint".into(),
44                ColumnType::Integer | ColumnType::Unsigned => "int".into(),
45                ColumnType::BigInteger | ColumnType::BigUnsigned => "bigint".into(),
46                ColumnType::Float => "float".into(),
47                ColumnType::Double => "double".into(),
48                ColumnType::Decimal(precision) => match precision {
49                    Some((precision, scale)) => format!("decimal({precision}, {scale})"),
50                    None => "decimal".into(),
51                },
52                ColumnType::DateTime => "datetime".into(),
53                ColumnType::Timestamp => "timestamp".into(),
54                ColumnType::TimestampWithTimeZone => "timestamp".into(),
55                ColumnType::Time => "time".into(),
56                ColumnType::Date => "date".into(),
57                ColumnType::Year => "year".into(),
58                ColumnType::Interval(_, _) => "unsupported".into(),
59                ColumnType::Binary(length) => format!("binary({length})"),
60                ColumnType::VarBinary(length) => match length {
61                    StringLen::N(length) => format!("varbinary({length})"),
62                    StringLen::None => "varbinary(255)".into(),
63                    StringLen::Max => "varbinary(65535)".into(),
64                },
65                ColumnType::Blob => "blob".into(),
66                ColumnType::Bit(length) => {
67                    match length {
68                        Some(length) => format!("bit({length})"),
69                        None => "bit".into(),
70                    }
71                }
72                ColumnType::VarBit(length) => {
73                    format!("bit({length})")
74                }
75                ColumnType::Boolean => "bool".into(),
76                ColumnType::Money(precision) => match precision {
77                    Some((precision, scale)) => format!("decimal({precision}, {scale})"),
78                    None => "decimal".into(),
79                },
80                ColumnType::Json => "json".into(),
81                ColumnType::JsonBinary => "json".into(),
82                ColumnType::Uuid => "binary(16)".into(),
83                ColumnType::Custom(iden) => iden.to_string(),
84                ColumnType::Enum { variants, .. } => format!(
85                    "ENUM('{}')",
86                    variants
87                        .iter()
88                        .map(|v| v.to_string())
89                        .collect::<Vec<_>>()
90                        .join("', '")
91                ),
92                ColumnType::Array(_) => unimplemented!("Array is not available in MySQL."),
93                ColumnType::Vector(_) => unimplemented!("Vector is not available in MySQL."),
94                ColumnType::Cidr => unimplemented!("Cidr is not available in MySQL."),
95                ColumnType::Inet => unimplemented!("Inet is not available in MySQL."),
96                ColumnType::MacAddr => unimplemented!("MacAddr is not available in MySQL."),
97                ColumnType::LTree => unimplemented!("LTree is not available in MySQL."),
98            }
99        )
100        .unwrap();
101        if matches!(
102            column_type,
103            ColumnType::TinyUnsigned
104                | ColumnType::SmallUnsigned
105                | ColumnType::Unsigned
106                | ColumnType::BigUnsigned
107        ) {
108            write!(sql, " ").unwrap();
109            write!(sql, "UNSIGNED").unwrap();
110        }
111    }
112
113    fn column_spec_auto_increment_keyword(&self) -> &str {
114        "AUTO_INCREMENT"
115    }
116
117    fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut dyn SqlWriter) {
118        if alter.options.is_empty() {
119            panic!("No alter option found")
120        };
121        write!(sql, "ALTER TABLE ").unwrap();
122        if let Some(table) = &alter.table {
123            self.prepare_table_ref_table_stmt(table, sql);
124            write!(sql, " ").unwrap();
125        }
126        alter.options.iter().fold(true, |first, option| {
127            if !first {
128                write!(sql, ", ").unwrap();
129            };
130            match option {
131                TableAlterOption::AddColumn(AddColumnOption {
132                    column,
133                    if_not_exists,
134                }) => {
135                    write!(sql, "ADD COLUMN ").unwrap();
136                    if *if_not_exists {
137                        write!(sql, "IF NOT EXISTS ").unwrap();
138                    }
139                    self.prepare_column_def(column, sql);
140                }
141                TableAlterOption::ModifyColumn(column_def) => {
142                    write!(sql, "MODIFY COLUMN ").unwrap();
143                    self.prepare_column_def(column_def, sql);
144                }
145                TableAlterOption::RenameColumn(from_name, to_name) => {
146                    write!(sql, "RENAME COLUMN ").unwrap();
147                    from_name.prepare(sql.as_writer(), self.quote());
148                    write!(sql, " TO ").unwrap();
149                    to_name.prepare(sql.as_writer(), self.quote());
150                }
151                TableAlterOption::DropColumn(column_name) => {
152                    write!(sql, "DROP COLUMN ").unwrap();
153                    column_name.prepare(sql.as_writer(), self.quote());
154                }
155                TableAlterOption::DropForeignKey(name) => {
156                    let mut foreign_key = TableForeignKey::new();
157                    foreign_key.name(name.to_string());
158                    let drop = ForeignKeyDropStatement {
159                        foreign_key,
160                        table: None,
161                    };
162                    self.prepare_foreign_key_drop_statement_internal(&drop, sql, Mode::TableAlter);
163                }
164                TableAlterOption::AddForeignKey(foreign_key) => {
165                    let create = ForeignKeyCreateStatement {
166                        foreign_key: foreign_key.to_owned(),
167                    };
168                    self.prepare_foreign_key_create_statement_internal(
169                        &create,
170                        sql,
171                        Mode::TableAlter,
172                    );
173                }
174            };
175            false
176        });
177    }
178
179    fn prepare_table_rename_statement(
180        &self,
181        rename: &TableRenameStatement,
182        sql: &mut dyn SqlWriter,
183    ) {
184        write!(sql, "RENAME TABLE ").unwrap();
185        if let Some(from_name) = &rename.from_name {
186            self.prepare_table_ref_table_stmt(from_name, sql);
187        }
188        write!(sql, " TO ").unwrap();
189        if let Some(to_name) = &rename.to_name {
190            self.prepare_table_ref_table_stmt(to_name, sql);
191        }
192    }
193
194    /// column comment
195    fn column_comment(&self, comment: &str, sql: &mut dyn SqlWriter) {
196        let comment = self.escape_string(comment);
197        write!(sql, "COMMENT '{comment}'").unwrap()
198    }
199}