1use super::*;
2
3impl TableBuilder for MysqlQueryBuilder {
4 fn prepare_table_opt(&self, create: &TableCreateStatement, sql: &mut dyn SqlWriter) {
5 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 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}