1#[cfg(not(feature = "std"))]
17use alloc::{boxed::Box, string::ToString, vec::Vec};
18use core::fmt;
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23use crate::ast::{display_comma_separated, display_separated, DataType, Expr, Ident, ObjectName};
24use crate::tokenizer::Token;
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29pub enum AlterTableOperation {
30 AddConstraint(TableConstraint),
32 AddColumn { column_def: ColumnDef },
34 DropConstraint { name: Ident },
36 DropColumn {
38 column_name: Ident,
39 if_exists: bool,
40 cascade: bool,
41 },
42 RenamePartitions {
44 old_partitions: Vec<Expr>,
45 new_partitions: Vec<Expr>,
46 },
47 AddPartitions {
49 if_not_exists: bool,
50 new_partitions: Vec<Expr>,
51 },
52 DropPartitions {
53 partitions: Vec<Expr>,
54 if_exists: bool,
55 },
56 RenameColumn {
58 old_column_name: Ident,
59 new_column_name: Ident,
60 },
61 RenameTable { table_name: ObjectName },
63 ChangeColumn {
65 old_name: Ident,
66 new_name: Ident,
67 data_type: DataType,
68 options: Vec<ColumnOption>,
69 },
70 RenameConstraint { old_name: Ident, new_name: Ident },
74 AlterColumn {
76 column_name: Ident,
77 op: AlterColumnOperation,
78 },
79}
80
81impl fmt::Display for AlterTableOperation {
82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83 match self {
84 AlterTableOperation::AddPartitions {
85 if_not_exists,
86 new_partitions,
87 } => write!(
88 f,
89 "ADD{ine} PARTITION ({})",
90 display_comma_separated(new_partitions),
91 ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
92 ),
93 AlterTableOperation::AddConstraint(c) => write!(f, "ADD {}", c),
94 AlterTableOperation::AddColumn { column_def } => {
95 write!(f, "ADD COLUMN {}", column_def.to_string())
96 }
97 AlterTableOperation::AlterColumn { column_name, op } => {
98 write!(f, "ALTER COLUMN {} {}", column_name, op)
99 }
100 AlterTableOperation::DropPartitions {
101 partitions,
102 if_exists,
103 } => write!(
104 f,
105 "DROP{ie} PARTITION ({})",
106 display_comma_separated(partitions),
107 ie = if *if_exists { " IF EXISTS" } else { "" }
108 ),
109 AlterTableOperation::DropConstraint { name } => write!(f, "DROP CONSTRAINT {}", name),
110 AlterTableOperation::DropColumn {
111 column_name,
112 if_exists,
113 cascade,
114 } => write!(
115 f,
116 "DROP COLUMN {}{}{}",
117 if *if_exists { "IF EXISTS " } else { "" },
118 column_name,
119 if *cascade { " CASCADE" } else { "" }
120 ),
121 AlterTableOperation::RenamePartitions {
122 old_partitions,
123 new_partitions,
124 } => write!(
125 f,
126 "PARTITION ({}) RENAME TO PARTITION ({})",
127 display_comma_separated(old_partitions),
128 display_comma_separated(new_partitions)
129 ),
130 AlterTableOperation::RenameColumn {
131 old_column_name,
132 new_column_name,
133 } => write!(
134 f,
135 "RENAME COLUMN {} TO {}",
136 old_column_name, new_column_name
137 ),
138 AlterTableOperation::RenameTable { table_name } => {
139 write!(f, "RENAME TO {}", table_name)
140 }
141 AlterTableOperation::ChangeColumn {
142 old_name,
143 new_name,
144 data_type,
145 options,
146 } => {
147 write!(f, "CHANGE COLUMN {} {} {}", old_name, new_name, data_type)?;
148 if options.is_empty() {
149 Ok(())
150 } else {
151 write!(f, " {}", display_separated(options, " "))
152 }
153 }
154 AlterTableOperation::RenameConstraint { old_name, new_name } => {
155 write!(f, "RENAME CONSTRAINT {} TO {}", old_name, new_name)
156 }
157 }
158 }
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Hash)]
163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
164pub enum AlterColumnOperation {
165 SetNotNull,
167 DropNotNull,
169 SetDefault { value: Expr },
171 DropDefault,
173 SetDataType {
175 data_type: DataType,
176 using: Option<Expr>,
178 },
179}
180
181impl fmt::Display for AlterColumnOperation {
182 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183 match self {
184 AlterColumnOperation::SetNotNull => write!(f, "SET NOT NULL",),
185 AlterColumnOperation::DropNotNull => write!(f, "DROP NOT NULL",),
186 AlterColumnOperation::SetDefault { value } => {
187 write!(f, "SET DEFAULT {}", value)
188 }
189 AlterColumnOperation::DropDefault {} => {
190 write!(f, "DROP DEFAULT")
191 }
192 AlterColumnOperation::SetDataType { data_type, using } => {
193 if let Some(expr) = using {
194 write!(f, "SET DATA TYPE {} USING {}", data_type, expr)
195 } else {
196 write!(f, "SET DATA TYPE {}", data_type)
197 }
198 }
199 }
200 }
201}
202
203#[derive(Debug, Clone, PartialEq, Eq, Hash)]
206#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
207pub enum TableConstraint {
208 Unique {
210 name: Option<Ident>,
211 columns: Vec<Ident>,
212 is_primary: bool,
214 },
215 ForeignKey {
221 name: Option<Ident>,
222 columns: Vec<Ident>,
223 foreign_table: ObjectName,
224 referred_columns: Vec<Ident>,
225 on_delete: Option<ReferentialAction>,
226 on_update: Option<ReferentialAction>,
227 },
228 Check {
230 name: Option<Ident>,
231 expr: Box<Expr>,
232 },
233}
234
235impl fmt::Display for TableConstraint {
236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237 match self {
238 TableConstraint::Unique {
239 name,
240 columns,
241 is_primary,
242 } => write!(
243 f,
244 "{}{} ({})",
245 display_constraint_name(name),
246 if *is_primary { "PRIMARY KEY" } else { "UNIQUE" },
247 display_comma_separated(columns)
248 ),
249 TableConstraint::ForeignKey {
250 name,
251 columns,
252 foreign_table,
253 referred_columns,
254 on_delete,
255 on_update,
256 } => {
257 write!(
258 f,
259 "{}FOREIGN KEY ({}) REFERENCES {}({})",
260 display_constraint_name(name),
261 display_comma_separated(columns),
262 foreign_table,
263 display_comma_separated(referred_columns),
264 )?;
265 if let Some(action) = on_delete {
266 write!(f, " ON DELETE {}", action)?;
267 }
268 if let Some(action) = on_update {
269 write!(f, " ON UPDATE {}", action)?;
270 }
271 Ok(())
272 }
273 TableConstraint::Check { name, expr } => {
274 write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
275 }
276 }
277 }
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, Hash)]
282#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
283pub struct ColumnDef {
284 pub name: Ident,
285 pub data_type: DataType,
286 pub collation: Option<ObjectName>,
287 pub options: Vec<ColumnOptionDef>,
288}
289
290impl fmt::Display for ColumnDef {
291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292 write!(f, "{} {}", self.name, self.data_type)?;
293 for option in &self.options {
294 write!(f, " {}", option)?;
295 }
296 Ok(())
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Eq, Hash)]
317#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
318pub struct ColumnOptionDef {
319 pub name: Option<Ident>,
320 pub option: ColumnOption,
321}
322
323impl fmt::Display for ColumnOptionDef {
324 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
325 write!(f, "{}{}", display_constraint_name(&self.name), self.option)
326 }
327}
328
329#[derive(Debug, Clone, PartialEq, Eq, Hash)]
332#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
333pub enum ColumnOption {
334 Null,
336 NotNull,
338 Default(Expr),
340 Unique { is_primary: bool },
342 ForeignKey {
348 foreign_table: ObjectName,
349 referred_columns: Vec<Ident>,
350 on_delete: Option<ReferentialAction>,
351 on_update: Option<ReferentialAction>,
352 },
353 Check(Expr),
355 DialectSpecific(Vec<Token>),
359}
360
361impl fmt::Display for ColumnOption {
362 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
363 use ColumnOption::*;
364 match self {
365 Null => write!(f, "NULL"),
366 NotNull => write!(f, "NOT NULL"),
367 Default(expr) => write!(f, "DEFAULT {}", expr),
368 Unique { is_primary } => {
369 write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })
370 }
371 ForeignKey {
372 foreign_table,
373 referred_columns,
374 on_delete,
375 on_update,
376 } => {
377 write!(f, "REFERENCES {}", foreign_table)?;
378 if !referred_columns.is_empty() {
379 write!(f, " ({})", display_comma_separated(referred_columns))?;
380 }
381 if let Some(action) = on_delete {
382 write!(f, " ON DELETE {}", action)?;
383 }
384 if let Some(action) = on_update {
385 write!(f, " ON UPDATE {}", action)?;
386 }
387 Ok(())
388 }
389 Check(expr) => write!(f, "CHECK ({})", expr),
390 DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
391 }
392 }
393}
394
395fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
396 struct ConstraintName<'a>(&'a Option<Ident>);
397 impl<'a> fmt::Display for ConstraintName<'a> {
398 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
399 if let Some(name) = self.0 {
400 write!(f, "CONSTRAINT {} ", name)?;
401 }
402 Ok(())
403 }
404 }
405 ConstraintName(name)
406}
407
408#[derive(Debug, Clone, PartialEq, Eq, Hash)]
413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
414pub enum ReferentialAction {
415 Restrict,
416 Cascade,
417 SetNull,
418 NoAction,
419 SetDefault,
420}
421
422impl fmt::Display for ReferentialAction {
423 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
424 f.write_str(match self {
425 ReferentialAction::Restrict => "RESTRICT",
426 ReferentialAction::Cascade => "CASCADE",
427 ReferentialAction::SetNull => "SET NULL",
428 ReferentialAction::NoAction => "NO ACTION",
429 ReferentialAction::SetDefault => "SET DEFAULT",
430 })
431 }
432}