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 SqlOption,
30};
31use crate::tokenizer::Token;
32
33#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
37pub enum AlterTableOperation {
38 AddConstraint(TableConstraint),
40 AddColumn {
42 column_keyword: bool,
44 if_not_exists: bool,
46 column_def: ColumnDef,
48 },
49 DisableRowLevelSecurity,
53 DisableRule { name: Ident },
57 DisableTrigger { name: Ident },
61 DropConstraint {
63 if_exists: bool,
64 name: Ident,
65 cascade: bool,
66 },
67 DropColumn {
69 column_name: Ident,
70 if_exists: bool,
71 cascade: bool,
72 },
73 DropPrimaryKey,
77 EnableAlwaysRule { name: Ident },
81 EnableAlwaysTrigger { name: Ident },
85 EnableReplicaRule { name: Ident },
89 EnableReplicaTrigger { name: Ident },
93 EnableRowLevelSecurity,
97 EnableRule { name: Ident },
101 EnableTrigger { name: Ident },
105 RenamePartitions {
107 old_partitions: Vec<Expr>,
108 new_partitions: Vec<Expr>,
109 },
110 AddPartitions {
112 if_not_exists: bool,
113 new_partitions: Vec<Partition>,
114 },
115 DropPartitions {
116 partitions: Vec<Expr>,
117 if_exists: bool,
118 },
119 RenameColumn {
121 old_column_name: Ident,
122 new_column_name: Ident,
123 },
124 RenameTable { table_name: ObjectName },
126 ChangeColumn {
128 old_name: Ident,
129 new_name: Ident,
130 data_type: DataType,
131 options: Vec<ColumnOption>,
132 },
133 RenameConstraint { old_name: Ident, new_name: Ident },
137 AlterColumn {
139 column_name: Ident,
140 op: AlterColumnOperation,
141 },
142 SwapWith { table_name: ObjectName },
146}
147
148#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
149#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
150#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
151pub enum AlterIndexOperation {
152 RenameIndex { index_name: ObjectName },
153}
154
155impl fmt::Display for AlterTableOperation {
156 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157 match self {
158 AlterTableOperation::AddPartitions {
159 if_not_exists,
160 new_partitions,
161 } => write!(
162 f,
163 "ADD{ine} {}",
164 display_separated(new_partitions, " "),
165 ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
166 ),
167 AlterTableOperation::AddConstraint(c) => write!(f, "ADD {c}"),
168 AlterTableOperation::AddColumn {
169 column_keyword,
170 if_not_exists,
171 column_def,
172 } => {
173 write!(f, "ADD")?;
174 if *column_keyword {
175 write!(f, " COLUMN")?;
176 }
177 if *if_not_exists {
178 write!(f, " IF NOT EXISTS")?;
179 }
180 write!(f, " {column_def}")?;
181
182 Ok(())
183 }
184 AlterTableOperation::AlterColumn { column_name, op } => {
185 write!(f, "ALTER COLUMN {column_name} {op}")
186 }
187 AlterTableOperation::DisableRowLevelSecurity => {
188 write!(f, "DISABLE ROW LEVEL SECURITY")
189 }
190 AlterTableOperation::DisableRule { name } => {
191 write!(f, "DISABLE RULE {name}")
192 }
193 AlterTableOperation::DisableTrigger { name } => {
194 write!(f, "DISABLE TRIGGER {name}")
195 }
196 AlterTableOperation::DropPartitions {
197 partitions,
198 if_exists,
199 } => write!(
200 f,
201 "DROP{ie} PARTITION ({})",
202 display_comma_separated(partitions),
203 ie = if *if_exists { " IF EXISTS" } else { "" }
204 ),
205 AlterTableOperation::DropConstraint {
206 if_exists,
207 name,
208 cascade,
209 } => {
210 write!(
211 f,
212 "DROP CONSTRAINT {}{}{}",
213 if *if_exists { "IF EXISTS " } else { "" },
214 name,
215 if *cascade { " CASCADE" } else { "" },
216 )
217 }
218 AlterTableOperation::DropPrimaryKey => write!(f, "DROP PRIMARY KEY"),
219 AlterTableOperation::DropColumn {
220 column_name,
221 if_exists,
222 cascade,
223 } => write!(
224 f,
225 "DROP COLUMN {}{}{}",
226 if *if_exists { "IF EXISTS " } else { "" },
227 column_name,
228 if *cascade { " CASCADE" } else { "" }
229 ),
230 AlterTableOperation::EnableAlwaysRule { name } => {
231 write!(f, "ENABLE ALWAYS RULE {name}")
232 }
233 AlterTableOperation::EnableAlwaysTrigger { name } => {
234 write!(f, "ENABLE ALWAYS TRIGGER {name}")
235 }
236 AlterTableOperation::EnableReplicaRule { name } => {
237 write!(f, "ENABLE REPLICA RULE {name}")
238 }
239 AlterTableOperation::EnableReplicaTrigger { name } => {
240 write!(f, "ENABLE REPLICA TRIGGER {name}")
241 }
242 AlterTableOperation::EnableRowLevelSecurity => {
243 write!(f, "ENABLE ROW LEVEL SECURITY")
244 }
245 AlterTableOperation::EnableRule { name } => {
246 write!(f, "ENABLE RULE {name}")
247 }
248 AlterTableOperation::EnableTrigger { name } => {
249 write!(f, "ENABLE TRIGGER {name}")
250 }
251 AlterTableOperation::RenamePartitions {
252 old_partitions,
253 new_partitions,
254 } => write!(
255 f,
256 "PARTITION ({}) RENAME TO PARTITION ({})",
257 display_comma_separated(old_partitions),
258 display_comma_separated(new_partitions)
259 ),
260 AlterTableOperation::RenameColumn {
261 old_column_name,
262 new_column_name,
263 } => write!(f, "RENAME COLUMN {old_column_name} TO {new_column_name}"),
264 AlterTableOperation::RenameTable { table_name } => {
265 write!(f, "RENAME TO {table_name}")
266 }
267 AlterTableOperation::ChangeColumn {
268 old_name,
269 new_name,
270 data_type,
271 options,
272 } => {
273 write!(f, "CHANGE COLUMN {old_name} {new_name} {data_type}")?;
274 if options.is_empty() {
275 Ok(())
276 } else {
277 write!(f, " {}", display_separated(options, " "))
278 }
279 }
280 AlterTableOperation::RenameConstraint { old_name, new_name } => {
281 write!(f, "RENAME CONSTRAINT {old_name} TO {new_name}")
282 }
283 AlterTableOperation::SwapWith { table_name } => {
284 write!(f, "SWAP WITH {table_name}")
285 }
286 }
287 }
288}
289
290impl fmt::Display for AlterIndexOperation {
291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292 match self {
293 AlterIndexOperation::RenameIndex { index_name } => {
294 write!(f, "RENAME TO {index_name}")
295 }
296 }
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
304pub enum AlterColumnOperation {
305 SetNotNull,
307 DropNotNull,
309 SetDefault { value: Expr },
311 DropDefault,
313 SetDataType {
315 data_type: DataType,
316 using: Option<Expr>,
318 },
319 AddGenerated {
323 generated_as: Option<GeneratedAs>,
324 sequence_options: Option<Vec<SequenceOptions>>,
325 },
326}
327
328impl fmt::Display for AlterColumnOperation {
329 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
330 match self {
331 AlterColumnOperation::SetNotNull => write!(f, "SET NOT NULL",),
332 AlterColumnOperation::DropNotNull => write!(f, "DROP NOT NULL",),
333 AlterColumnOperation::SetDefault { value } => {
334 write!(f, "SET DEFAULT {value}")
335 }
336 AlterColumnOperation::DropDefault {} => {
337 write!(f, "DROP DEFAULT")
338 }
339 AlterColumnOperation::SetDataType { data_type, using } => {
340 if let Some(expr) = using {
341 write!(f, "SET DATA TYPE {data_type} USING {expr}")
342 } else {
343 write!(f, "SET DATA TYPE {data_type}")
344 }
345 }
346 AlterColumnOperation::AddGenerated {
347 generated_as,
348 sequence_options,
349 } => {
350 let generated_as = match generated_as {
351 Some(GeneratedAs::Always) => " ALWAYS",
352 Some(GeneratedAs::ByDefault) => " BY DEFAULT",
353 _ => "",
354 };
355
356 write!(f, "ADD GENERATED{generated_as} AS IDENTITY",)?;
357 if let Some(options) = sequence_options {
358 write!(f, " (")?;
359
360 for sequence_option in options {
361 write!(f, "{sequence_option}")?;
362 }
363
364 write!(f, " )")?;
365 }
366 Ok(())
367 }
368 }
369 }
370}
371
372#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
377pub enum TableConstraint {
378 Unique {
380 name: Option<Ident>,
381 columns: Vec<Ident>,
382 is_primary: bool,
384 characteristics: Option<ConstraintCharacteristics>,
385 },
386 ForeignKey {
392 name: Option<Ident>,
393 columns: Vec<Ident>,
394 foreign_table: ObjectName,
395 referred_columns: Vec<Ident>,
396 on_delete: Option<ReferentialAction>,
397 on_update: Option<ReferentialAction>,
398 characteristics: Option<ConstraintCharacteristics>,
399 },
400 Check {
402 name: Option<Ident>,
403 expr: Box<Expr>,
404 },
405 Index {
412 display_as_key: bool,
414 name: Option<Ident>,
416 index_type: Option<IndexType>,
420 columns: Vec<Ident>,
422 },
423 FulltextOrSpatial {
437 fulltext: bool,
439 index_type_display: KeyOrIndexDisplay,
441 opt_index_name: Option<Ident>,
443 columns: Vec<Ident>,
445 },
446}
447
448impl fmt::Display for TableConstraint {
449 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
450 match self {
451 TableConstraint::Unique {
452 name,
453 columns,
454 is_primary,
455 characteristics,
456 } => {
457 write!(
458 f,
459 "{}{} ({})",
460 display_constraint_name(name),
461 if *is_primary { "PRIMARY KEY" } else { "UNIQUE" },
462 display_comma_separated(columns)
463 )?;
464
465 if let Some(characteristics) = characteristics {
466 write!(f, " {}", characteristics)?;
467 }
468
469 Ok(())
470 }
471 TableConstraint::ForeignKey {
472 name,
473 columns,
474 foreign_table,
475 referred_columns,
476 on_delete,
477 on_update,
478 characteristics,
479 } => {
480 write!(
481 f,
482 "{}FOREIGN KEY ({}) REFERENCES {}({})",
483 display_constraint_name(name),
484 display_comma_separated(columns),
485 foreign_table,
486 display_comma_separated(referred_columns),
487 )?;
488 if let Some(action) = on_delete {
489 write!(f, " ON DELETE {action}")?;
490 }
491 if let Some(action) = on_update {
492 write!(f, " ON UPDATE {action}")?;
493 }
494 if let Some(characteristics) = characteristics {
495 write!(f, " {}", characteristics)?;
496 }
497 Ok(())
498 }
499 TableConstraint::Check { name, expr } => {
500 write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
501 }
502 TableConstraint::Index {
503 display_as_key,
504 name,
505 index_type,
506 columns,
507 } => {
508 write!(f, "{}", if *display_as_key { "KEY" } else { "INDEX" })?;
509 if let Some(name) = name {
510 write!(f, " {name}")?;
511 }
512 if let Some(index_type) = index_type {
513 write!(f, " USING {index_type}")?;
514 }
515 write!(f, " ({})", display_comma_separated(columns))?;
516
517 Ok(())
518 }
519 Self::FulltextOrSpatial {
520 fulltext,
521 index_type_display,
522 opt_index_name,
523 columns,
524 } => {
525 if *fulltext {
526 write!(f, "FULLTEXT")?;
527 } else {
528 write!(f, "SPATIAL")?;
529 }
530
531 if !matches!(index_type_display, KeyOrIndexDisplay::None) {
532 write!(f, " {index_type_display}")?;
533 }
534
535 if let Some(name) = opt_index_name {
536 write!(f, " {name}")?;
537 }
538
539 write!(f, " ({})", display_comma_separated(columns))?;
540
541 Ok(())
542 }
543 }
544 }
545}
546
547#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
555#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
556#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
557pub enum KeyOrIndexDisplay {
558 None,
560 Key,
562 Index,
564}
565
566impl fmt::Display for KeyOrIndexDisplay {
567 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568 match self {
569 KeyOrIndexDisplay::None => {
570 write!(f, "")
571 }
572 KeyOrIndexDisplay::Key => {
573 write!(f, "KEY")
574 }
575 KeyOrIndexDisplay::Index => {
576 write!(f, "INDEX")
577 }
578 }
579 }
580}
581
582#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
591#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
592#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
593pub enum IndexType {
594 BTree,
595 Hash,
596 }
598
599impl fmt::Display for IndexType {
600 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
601 match self {
602 Self::BTree => write!(f, "BTREE"),
603 Self::Hash => write!(f, "HASH"),
604 }
605 }
606}
607#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
608#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
609#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
610pub struct ProcedureParam {
611 pub name: Ident,
612 pub data_type: DataType,
613}
614
615impl fmt::Display for ProcedureParam {
616 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
617 write!(f, "{} {}", self.name, self.data_type)
618 }
619}
620
621#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
624#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
625pub struct ColumnDef {
626 pub name: Ident,
627 pub data_type: DataType,
628 pub collation: Option<ObjectName>,
629 pub options: Vec<ColumnOptionDef>,
630}
631
632impl fmt::Display for ColumnDef {
633 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
634 if self.data_type == DataType::Unspecified {
635 write!(f, "{}", self.name)?;
636 } else {
637 write!(f, "{} {}", self.name, self.data_type)?;
638 }
639 if let Some(collation) = &self.collation {
640 write!(f, " COLLATE {collation}")?;
641 }
642 for option in &self.options {
643 write!(f, " {option}")?;
644 }
645 Ok(())
646 }
647}
648
649#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
665#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
666pub struct ViewColumnDef {
667 pub name: Ident,
668 pub options: Option<Vec<SqlOption>>,
669}
670
671impl fmt::Display for ViewColumnDef {
672 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
673 write!(f, "{}", self.name)?;
674 if let Some(options) = self.options.as_ref() {
675 write!(
676 f,
677 " OPTIONS({})",
678 display_comma_separated(options.as_slice())
679 )?;
680 }
681 Ok(())
682 }
683}
684
685#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
704pub struct ColumnOptionDef {
705 pub name: Option<Ident>,
706 pub option: ColumnOption,
707}
708
709impl fmt::Display for ColumnOptionDef {
710 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
711 write!(f, "{}{}", display_constraint_name(&self.name), self.option)
712 }
713}
714
715#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
718#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
719#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
720pub enum ColumnOption {
721 Null,
723 NotNull,
725 Default(Expr),
727 Unique {
729 is_primary: bool,
730 characteristics: Option<ConstraintCharacteristics>,
731 },
732 ForeignKey {
740 foreign_table: ObjectName,
741 referred_columns: Vec<Ident>,
742 on_delete: Option<ReferentialAction>,
743 on_update: Option<ReferentialAction>,
744 characteristics: Option<ConstraintCharacteristics>,
745 },
746 Check(Expr),
748 DialectSpecific(Vec<Token>),
752 CharacterSet(ObjectName),
753 Comment(String),
754 OnUpdate(Expr),
755 Generated {
758 generated_as: GeneratedAs,
759 sequence_options: Option<Vec<SequenceOptions>>,
760 generation_expr: Option<Expr>,
761 generation_expr_mode: Option<GeneratedExpressionMode>,
762 generated_keyword: bool,
764 },
765 Options(Vec<SqlOption>),
773}
774
775impl fmt::Display for ColumnOption {
776 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
777 use ColumnOption::*;
778 match self {
779 Null => write!(f, "NULL"),
780 NotNull => write!(f, "NOT NULL"),
781 Default(expr) => write!(f, "DEFAULT {expr}"),
782 Unique {
783 is_primary,
784 characteristics,
785 } => {
786 write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })?;
787 if let Some(characteristics) = characteristics {
788 write!(f, " {}", characteristics)?;
789 }
790 Ok(())
791 }
792 ForeignKey {
793 foreign_table,
794 referred_columns,
795 on_delete,
796 on_update,
797 characteristics,
798 } => {
799 write!(f, "REFERENCES {foreign_table}")?;
800 if !referred_columns.is_empty() {
801 write!(f, " ({})", display_comma_separated(referred_columns))?;
802 }
803 if let Some(action) = on_delete {
804 write!(f, " ON DELETE {action}")?;
805 }
806 if let Some(action) = on_update {
807 write!(f, " ON UPDATE {action}")?;
808 }
809 if let Some(characteristics) = characteristics {
810 write!(f, " {}", characteristics)?;
811 }
812 Ok(())
813 }
814 Check(expr) => write!(f, "CHECK ({expr})"),
815 DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
816 CharacterSet(n) => write!(f, "CHARACTER SET {n}"),
817 Comment(v) => write!(f, "COMMENT '{}'", escape_single_quote_string(v)),
818 OnUpdate(expr) => write!(f, "ON UPDATE {expr}"),
819 Generated {
820 generated_as,
821 sequence_options,
822 generation_expr,
823 generation_expr_mode,
824 generated_keyword,
825 } => {
826 if let Some(expr) = generation_expr {
827 let modifier = match generation_expr_mode {
828 None => "",
829 Some(GeneratedExpressionMode::Virtual) => " VIRTUAL",
830 Some(GeneratedExpressionMode::Stored) => " STORED",
831 };
832 if *generated_keyword {
833 write!(f, "GENERATED ALWAYS AS ({expr}){modifier}")?;
834 } else {
835 write!(f, "AS ({expr}){modifier}")?;
836 }
837 Ok(())
838 } else {
839 let when = match generated_as {
841 GeneratedAs::Always => "ALWAYS",
842 GeneratedAs::ByDefault => "BY DEFAULT",
843 GeneratedAs::ExpStored => unreachable!(),
845 };
846 write!(f, "GENERATED {when} AS IDENTITY")?;
847 if sequence_options.is_some() {
848 let so = sequence_options.as_ref().unwrap();
849 if !so.is_empty() {
850 write!(f, " (")?;
851 }
852 for sequence_option in so {
853 write!(f, "{sequence_option}")?;
854 }
855 if !so.is_empty() {
856 write!(f, " )")?;
857 }
858 }
859 Ok(())
860 }
861 }
862 Options(options) => {
863 write!(f, "OPTIONS({})", display_comma_separated(options))
864 }
865 }
866 }
867}
868
869#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
872#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
873#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
874pub enum GeneratedAs {
875 Always,
876 ByDefault,
877 ExpStored,
878}
879
880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
883#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
884#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
885pub enum GeneratedExpressionMode {
886 Virtual,
887 Stored,
888}
889
890fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
891 struct ConstraintName<'a>(&'a Option<Ident>);
892 impl<'a> fmt::Display for ConstraintName<'a> {
893 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
894 if let Some(name) = self.0 {
895 write!(f, "CONSTRAINT {name} ")?;
896 }
897 Ok(())
898 }
899 }
900 ConstraintName(name)
901}
902
903#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
907#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
908#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
909pub struct ConstraintCharacteristics {
910 pub deferrable: Option<bool>,
912 pub initially: Option<DeferrableInitial>,
914 pub enforced: Option<bool>,
916}
917
918#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
919#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
920#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
921pub enum DeferrableInitial {
922 Immediate,
924 Deferred,
926}
927
928impl ConstraintCharacteristics {
929 fn deferrable_text(&self) -> Option<&'static str> {
930 self.deferrable.map(|deferrable| {
931 if deferrable {
932 "DEFERRABLE"
933 } else {
934 "NOT DEFERRABLE"
935 }
936 })
937 }
938
939 fn initially_immediate_text(&self) -> Option<&'static str> {
940 self.initially
941 .map(|initially_immediate| match initially_immediate {
942 DeferrableInitial::Immediate => "INITIALLY IMMEDIATE",
943 DeferrableInitial::Deferred => "INITIALLY DEFERRED",
944 })
945 }
946
947 fn enforced_text(&self) -> Option<&'static str> {
948 self.enforced.map(
949 |enforced| {
950 if enforced {
951 "ENFORCED"
952 } else {
953 "NOT ENFORCED"
954 }
955 },
956 )
957 }
958}
959
960impl fmt::Display for ConstraintCharacteristics {
961 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
962 let deferrable = self.deferrable_text();
963 let initially_immediate = self.initially_immediate_text();
964 let enforced = self.enforced_text();
965
966 match (deferrable, initially_immediate, enforced) {
967 (None, None, None) => Ok(()),
968 (None, None, Some(enforced)) => write!(f, "{enforced}"),
969 (None, Some(initial), None) => write!(f, "{initial}"),
970 (None, Some(initial), Some(enforced)) => write!(f, "{initial} {enforced}"),
971 (Some(deferrable), None, None) => write!(f, "{deferrable}"),
972 (Some(deferrable), None, Some(enforced)) => write!(f, "{deferrable} {enforced}"),
973 (Some(deferrable), Some(initial), None) => write!(f, "{deferrable} {initial}"),
974 (Some(deferrable), Some(initial), Some(enforced)) => {
975 write!(f, "{deferrable} {initial} {enforced}")
976 }
977 }
978 }
979}
980
981#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
986#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
987#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
988pub enum ReferentialAction {
989 Restrict,
990 Cascade,
991 SetNull,
992 NoAction,
993 SetDefault,
994}
995
996impl fmt::Display for ReferentialAction {
997 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
998 f.write_str(match self {
999 ReferentialAction::Restrict => "RESTRICT",
1000 ReferentialAction::Cascade => "CASCADE",
1001 ReferentialAction::SetNull => "SET NULL",
1002 ReferentialAction::NoAction => "NO ACTION",
1003 ReferentialAction::SetDefault => "SET DEFAULT",
1004 })
1005 }
1006}
1007
1008#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1010#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1011#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1012pub enum UserDefinedTypeRepresentation {
1013 Composite {
1014 attributes: Vec<UserDefinedTypeCompositeAttributeDef>,
1015 },
1016}
1017
1018impl fmt::Display for UserDefinedTypeRepresentation {
1019 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1020 match self {
1021 UserDefinedTypeRepresentation::Composite { attributes } => {
1022 write!(f, "({})", display_comma_separated(attributes))
1023 }
1024 }
1025 }
1026}
1027
1028#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1030#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1031#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1032pub struct UserDefinedTypeCompositeAttributeDef {
1033 pub name: Ident,
1034 pub data_type: DataType,
1035 pub collation: Option<ObjectName>,
1036}
1037
1038impl fmt::Display for UserDefinedTypeCompositeAttributeDef {
1039 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1040 write!(f, "{} {}", self.name, self.data_type)?;
1041 if let Some(collation) = &self.collation {
1042 write!(f, " COLLATE {collation}")?;
1043 }
1044 Ok(())
1045 }
1046}
1047
1048#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1050#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1051#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1052pub struct Partition {
1053 pub partitions: Vec<Expr>,
1054}
1055
1056impl fmt::Display for Partition {
1057 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1058 write!(
1059 f,
1060 "PARTITION ({})",
1061 display_comma_separated(&self.partitions)
1062 )
1063 }
1064}