1#[cfg(not(feature = "std"))]
17use alloc::{boxed::Box, string::String, vec::Vec};
18use core::fmt;
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23#[cfg(feature = "visitor")]
24use sqlparser_derive::{Visit, VisitMut};
25
26use crate::ast::value::escape_single_quote_string;
27use crate::ast::{
28 display_comma_separated, display_separated, DataType, Expr, Ident, ObjectName, SequenceOptions,
29};
30use crate::tokenizer::Token;
31
32#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
36pub enum AlterTableOperation {
37 AddConstraint(TableConstraint),
39 AddColumn {
41 column_keyword: bool,
43 if_not_exists: bool,
45 column_def: ColumnDef,
47 },
48 DropConstraint {
50 if_exists: bool,
51 name: Ident,
52 cascade: bool,
53 },
54 DropColumn {
56 column_name: Ident,
57 if_exists: bool,
58 cascade: bool,
59 },
60 DropPrimaryKey,
64 RenamePartitions {
66 old_partitions: Vec<Expr>,
67 new_partitions: Vec<Expr>,
68 },
69 AddPartitions {
71 if_not_exists: bool,
72 new_partitions: Vec<Partition>,
73 },
74 DropPartitions {
75 partitions: Vec<Expr>,
76 if_exists: bool,
77 },
78 RenameColumn {
80 old_column_name: Ident,
81 new_column_name: Ident,
82 },
83 RenameTable { table_name: ObjectName },
85 ChangeColumn {
87 old_name: Ident,
88 new_name: Ident,
89 data_type: DataType,
90 options: Vec<ColumnOption>,
91 },
92 RenameConstraint { old_name: Ident, new_name: Ident },
96 AlterColumn {
98 column_name: Ident,
99 op: AlterColumnOperation,
100 },
101 SwapWith { table_name: ObjectName },
105}
106
107#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
109#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
110pub enum AlterIndexOperation {
111 RenameIndex { index_name: ObjectName },
112}
113
114impl fmt::Display for AlterTableOperation {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 match self {
117 AlterTableOperation::AddPartitions {
118 if_not_exists,
119 new_partitions,
120 } => write!(
121 f,
122 "ADD{ine} {}",
123 display_separated(new_partitions, " "),
124 ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
125 ),
126 AlterTableOperation::AddConstraint(c) => write!(f, "ADD {c}"),
127 AlterTableOperation::AddColumn {
128 column_keyword,
129 if_not_exists,
130 column_def,
131 } => {
132 write!(f, "ADD")?;
133 if *column_keyword {
134 write!(f, " COLUMN")?;
135 }
136 if *if_not_exists {
137 write!(f, " IF NOT EXISTS")?;
138 }
139 write!(f, " {column_def}")?;
140
141 Ok(())
142 }
143 AlterTableOperation::AlterColumn { column_name, op } => {
144 write!(f, "ALTER COLUMN {column_name} {op}")
145 }
146 AlterTableOperation::DropPartitions {
147 partitions,
148 if_exists,
149 } => write!(
150 f,
151 "DROP{ie} PARTITION ({})",
152 display_comma_separated(partitions),
153 ie = if *if_exists { " IF EXISTS" } else { "" }
154 ),
155 AlterTableOperation::DropConstraint {
156 if_exists,
157 name,
158 cascade,
159 } => {
160 write!(
161 f,
162 "DROP CONSTRAINT {}{}{}",
163 if *if_exists { "IF EXISTS " } else { "" },
164 name,
165 if *cascade { " CASCADE" } else { "" },
166 )
167 }
168 AlterTableOperation::DropPrimaryKey => write!(f, "DROP PRIMARY KEY"),
169 AlterTableOperation::DropColumn {
170 column_name,
171 if_exists,
172 cascade,
173 } => write!(
174 f,
175 "DROP COLUMN {}{}{}",
176 if *if_exists { "IF EXISTS " } else { "" },
177 column_name,
178 if *cascade { " CASCADE" } else { "" }
179 ),
180 AlterTableOperation::RenamePartitions {
181 old_partitions,
182 new_partitions,
183 } => write!(
184 f,
185 "PARTITION ({}) RENAME TO PARTITION ({})",
186 display_comma_separated(old_partitions),
187 display_comma_separated(new_partitions)
188 ),
189 AlterTableOperation::RenameColumn {
190 old_column_name,
191 new_column_name,
192 } => write!(f, "RENAME COLUMN {old_column_name} TO {new_column_name}"),
193 AlterTableOperation::RenameTable { table_name } => {
194 write!(f, "RENAME TO {table_name}")
195 }
196 AlterTableOperation::ChangeColumn {
197 old_name,
198 new_name,
199 data_type,
200 options,
201 } => {
202 write!(f, "CHANGE COLUMN {old_name} {new_name} {data_type}")?;
203 if options.is_empty() {
204 Ok(())
205 } else {
206 write!(f, " {}", display_separated(options, " "))
207 }
208 }
209 AlterTableOperation::RenameConstraint { old_name, new_name } => {
210 write!(f, "RENAME CONSTRAINT {old_name} TO {new_name}")
211 }
212 AlterTableOperation::SwapWith { table_name } => {
213 write!(f, "SWAP WITH {table_name}")
214 }
215 }
216 }
217}
218
219impl fmt::Display for AlterIndexOperation {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 match self {
222 AlterIndexOperation::RenameIndex { index_name } => {
223 write!(f, "RENAME TO {index_name}")
224 }
225 }
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
232#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
233pub enum AlterColumnOperation {
234 SetNotNull,
236 DropNotNull,
238 SetDefault { value: Expr },
240 DropDefault,
242 SetDataType {
244 data_type: DataType,
245 using: Option<Expr>,
247 },
248}
249
250impl fmt::Display for AlterColumnOperation {
251 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
252 match self {
253 AlterColumnOperation::SetNotNull => write!(f, "SET NOT NULL",),
254 AlterColumnOperation::DropNotNull => write!(f, "DROP NOT NULL",),
255 AlterColumnOperation::SetDefault { value } => {
256 write!(f, "SET DEFAULT {value}")
257 }
258 AlterColumnOperation::DropDefault {} => {
259 write!(f, "DROP DEFAULT")
260 }
261 AlterColumnOperation::SetDataType { data_type, using } => {
262 if let Some(expr) = using {
263 write!(f, "SET DATA TYPE {data_type} USING {expr}")
264 } else {
265 write!(f, "SET DATA TYPE {data_type}")
266 }
267 }
268 }
269 }
270}
271
272#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
276#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
277pub enum TableConstraint {
278 Unique {
280 name: Option<Ident>,
281 columns: Vec<Ident>,
282 is_primary: bool,
284 },
285 ForeignKey {
291 name: Option<Ident>,
292 columns: Vec<Ident>,
293 foreign_table: ObjectName,
294 referred_columns: Vec<Ident>,
295 on_delete: Option<ReferentialAction>,
296 on_update: Option<ReferentialAction>,
297 },
298 Check {
300 name: Option<Ident>,
301 expr: Box<Expr>,
302 },
303 Index {
310 display_as_key: bool,
312 name: Option<Ident>,
314 index_type: Option<IndexType>,
318 columns: Vec<Ident>,
320 },
321 FulltextOrSpatial {
335 fulltext: bool,
337 index_type_display: KeyOrIndexDisplay,
339 opt_index_name: Option<Ident>,
341 columns: Vec<Ident>,
343 },
344}
345
346impl fmt::Display for TableConstraint {
347 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
348 match self {
349 TableConstraint::Unique {
350 name,
351 columns,
352 is_primary,
353 } => write!(
354 f,
355 "{}{} ({})",
356 display_constraint_name(name),
357 if *is_primary { "PRIMARY KEY" } else { "UNIQUE" },
358 display_comma_separated(columns)
359 ),
360 TableConstraint::ForeignKey {
361 name,
362 columns,
363 foreign_table,
364 referred_columns,
365 on_delete,
366 on_update,
367 } => {
368 write!(
369 f,
370 "{}FOREIGN KEY ({}) REFERENCES {}({})",
371 display_constraint_name(name),
372 display_comma_separated(columns),
373 foreign_table,
374 display_comma_separated(referred_columns),
375 )?;
376 if let Some(action) = on_delete {
377 write!(f, " ON DELETE {action}")?;
378 }
379 if let Some(action) = on_update {
380 write!(f, " ON UPDATE {action}")?;
381 }
382 Ok(())
383 }
384 TableConstraint::Check { name, expr } => {
385 write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
386 }
387 TableConstraint::Index {
388 display_as_key,
389 name,
390 index_type,
391 columns,
392 } => {
393 write!(f, "{}", if *display_as_key { "KEY" } else { "INDEX" })?;
394 if let Some(name) = name {
395 write!(f, " {name}")?;
396 }
397 if let Some(index_type) = index_type {
398 write!(f, " USING {index_type}")?;
399 }
400 write!(f, " ({})", display_comma_separated(columns))?;
401
402 Ok(())
403 }
404 Self::FulltextOrSpatial {
405 fulltext,
406 index_type_display,
407 opt_index_name,
408 columns,
409 } => {
410 if *fulltext {
411 write!(f, "FULLTEXT")?;
412 } else {
413 write!(f, "SPATIAL")?;
414 }
415
416 if !matches!(index_type_display, KeyOrIndexDisplay::None) {
417 write!(f, " {index_type_display}")?;
418 }
419
420 if let Some(name) = opt_index_name {
421 write!(f, " {name}")?;
422 }
423
424 write!(f, " ({})", display_comma_separated(columns))?;
425
426 Ok(())
427 }
428 }
429 }
430}
431
432#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
440#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
441#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
442pub enum KeyOrIndexDisplay {
443 None,
445 Key,
447 Index,
449}
450
451impl fmt::Display for KeyOrIndexDisplay {
452 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
453 match self {
454 KeyOrIndexDisplay::None => {
455 write!(f, "")
456 }
457 KeyOrIndexDisplay::Key => {
458 write!(f, "KEY")
459 }
460 KeyOrIndexDisplay::Index => {
461 write!(f, "INDEX")
462 }
463 }
464 }
465}
466
467#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
477#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
478pub enum IndexType {
479 BTree,
480 Hash,
481 }
483
484impl fmt::Display for IndexType {
485 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
486 match self {
487 Self::BTree => write!(f, "BTREE"),
488 Self::Hash => write!(f, "HASH"),
489 }
490 }
491}
492#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
493#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
494#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
495pub struct ProcedureParam {
496 pub name: Ident,
497 pub data_type: DataType,
498}
499
500impl fmt::Display for ProcedureParam {
501 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
502 write!(f, "{} {}", self.name, self.data_type)
503 }
504}
505
506#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
510pub struct ColumnDef {
511 pub name: Ident,
512 pub data_type: DataType,
513 pub collation: Option<ObjectName>,
514 pub options: Vec<ColumnOptionDef>,
515}
516
517impl fmt::Display for ColumnDef {
518 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
519 write!(f, "{} {}", self.name, self.data_type)?;
520 if let Some(collation) = &self.collation {
521 write!(f, " COLLATE {collation}")?;
522 }
523 for option in &self.options {
524 write!(f, " {option}")?;
525 }
526 Ok(())
527 }
528}
529
530#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
548#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
549pub struct ColumnOptionDef {
550 pub name: Option<Ident>,
551 pub option: ColumnOption,
552}
553
554impl fmt::Display for ColumnOptionDef {
555 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
556 write!(f, "{}{}", display_constraint_name(&self.name), self.option)
557 }
558}
559
560#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
565pub enum ColumnOption {
566 Null,
568 NotNull,
570 Default(Expr),
572 Unique {
574 is_primary: bool,
575 },
576 ForeignKey {
582 foreign_table: ObjectName,
583 referred_columns: Vec<Ident>,
584 on_delete: Option<ReferentialAction>,
585 on_update: Option<ReferentialAction>,
586 },
587 Check(Expr),
589 DialectSpecific(Vec<Token>),
593 CharacterSet(ObjectName),
594 Comment(String),
595 OnUpdate(Expr),
596 Generated {
599 generated_as: GeneratedAs,
600 sequence_options: Option<Vec<SequenceOptions>>,
601 generation_expr: Option<Expr>,
602 },
603}
604
605impl fmt::Display for ColumnOption {
606 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
607 use ColumnOption::*;
608 match self {
609 Null => write!(f, "NULL"),
610 NotNull => write!(f, "NOT NULL"),
611 Default(expr) => write!(f, "DEFAULT {expr}"),
612 Unique { is_primary } => {
613 write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })
614 }
615 ForeignKey {
616 foreign_table,
617 referred_columns,
618 on_delete,
619 on_update,
620 } => {
621 write!(f, "REFERENCES {foreign_table}")?;
622 if !referred_columns.is_empty() {
623 write!(f, " ({})", display_comma_separated(referred_columns))?;
624 }
625 if let Some(action) = on_delete {
626 write!(f, " ON DELETE {action}")?;
627 }
628 if let Some(action) = on_update {
629 write!(f, " ON UPDATE {action}")?;
630 }
631 Ok(())
632 }
633 Check(expr) => write!(f, "CHECK ({expr})"),
634 DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
635 CharacterSet(n) => write!(f, "CHARACTER SET {n}"),
636 Comment(v) => write!(f, "COMMENT '{}'", escape_single_quote_string(v)),
637 OnUpdate(expr) => write!(f, "ON UPDATE {expr}"),
638 Generated {
639 generated_as,
640 sequence_options,
641 generation_expr,
642 } => match generated_as {
643 GeneratedAs::Always => {
644 write!(f, "GENERATED ALWAYS AS IDENTITY")?;
645 if sequence_options.is_some() {
646 let so = sequence_options.as_ref().unwrap();
647 if !so.is_empty() {
648 write!(f, " (")?;
649 }
650 for sequence_option in so {
651 write!(f, "{sequence_option}")?;
652 }
653 if !so.is_empty() {
654 write!(f, " )")?;
655 }
656 }
657 Ok(())
658 }
659 GeneratedAs::ByDefault => {
660 write!(f, "GENERATED BY DEFAULT AS IDENTITY")?;
661 if sequence_options.is_some() {
662 let so = sequence_options.as_ref().unwrap();
663 if !so.is_empty() {
664 write!(f, " (")?;
665 }
666 for sequence_option in so {
667 write!(f, "{sequence_option}")?;
668 }
669 if !so.is_empty() {
670 write!(f, " )")?;
671 }
672 }
673 Ok(())
674 }
675 GeneratedAs::ExpStored => {
676 let expr = generation_expr.as_ref().unwrap();
677 write!(f, "GENERATED ALWAYS AS ({expr}) STORED")
678 }
679 },
680 }
681 }
682}
683
684#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
687#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
688#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
689pub enum GeneratedAs {
690 Always,
691 ByDefault,
692 ExpStored,
693}
694
695fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
696 struct ConstraintName<'a>(&'a Option<Ident>);
697 impl<'a> fmt::Display for ConstraintName<'a> {
698 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
699 if let Some(name) = self.0 {
700 write!(f, "CONSTRAINT {name} ")?;
701 }
702 Ok(())
703 }
704 }
705 ConstraintName(name)
706}
707
708#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
714#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
715pub enum ReferentialAction {
716 Restrict,
717 Cascade,
718 SetNull,
719 NoAction,
720 SetDefault,
721}
722
723impl fmt::Display for ReferentialAction {
724 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
725 f.write_str(match self {
726 ReferentialAction::Restrict => "RESTRICT",
727 ReferentialAction::Cascade => "CASCADE",
728 ReferentialAction::SetNull => "SET NULL",
729 ReferentialAction::NoAction => "NO ACTION",
730 ReferentialAction::SetDefault => "SET DEFAULT",
731 })
732 }
733}
734
735#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
739pub enum UserDefinedTypeRepresentation {
740 Composite {
741 attributes: Vec<UserDefinedTypeCompositeAttributeDef>,
742 },
743}
744
745impl fmt::Display for UserDefinedTypeRepresentation {
746 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
747 match self {
748 UserDefinedTypeRepresentation::Composite { attributes } => {
749 write!(f, "({})", display_comma_separated(attributes))
750 }
751 }
752 }
753}
754
755#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
757#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
758#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
759pub struct UserDefinedTypeCompositeAttributeDef {
760 pub name: Ident,
761 pub data_type: DataType,
762 pub collation: Option<ObjectName>,
763}
764
765impl fmt::Display for UserDefinedTypeCompositeAttributeDef {
766 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
767 write!(f, "{} {}", self.name, self.data_type)?;
768 if let Some(collation) = &self.collation {
769 write!(f, " COLLATE {collation}")?;
770 }
771 Ok(())
772 }
773}
774
775#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
777#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
778#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
779pub struct Partition {
780 pub partitions: Vec<Expr>,
781}
782
783impl fmt::Display for Partition {
784 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
785 write!(
786 f,
787 "PARTITION ({})",
788 display_comma_separated(&self.partitions)
789 )
790 }
791}