1#[cfg(not(feature = "std"))]
22use alloc::{boxed::Box, string::String, vec::Vec};
23use core::fmt::{self, Write};
24
25#[cfg(feature = "serde")]
26use serde::{Deserialize, Serialize};
27
28#[cfg(feature = "visitor")]
29use sqltk_parser_derive::{Visit, VisitMut};
30
31use crate::ast::value::escape_single_quote_string;
32use crate::ast::{
33 display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition,
34 ObjectName, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag, Value,
35};
36use crate::keywords::Keyword;
37use crate::tokenizer::Token;
38
39#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
43pub enum AlterTableOperation {
44 AddConstraint(TableConstraint),
46 AddColumn {
48 column_keyword: bool,
50 if_not_exists: bool,
52 column_def: ColumnDef,
54 column_position: Option<MySQLColumnPosition>,
56 },
57 AddProjection {
62 if_not_exists: bool,
63 name: Ident,
64 select: ProjectionSelect,
65 },
66
67 DropProjection { if_exists: bool, name: Ident },
72
73 MaterializeProjection {
78 if_exists: bool,
79 name: Ident,
80 partition: Option<Ident>,
81 },
82
83 ClearProjection {
88 if_exists: bool,
89 name: Ident,
90 partition: Option<Ident>,
91 },
92
93 DisableRowLevelSecurity,
97 DisableRule { name: Ident },
101 DisableTrigger { name: Ident },
105 DropConstraint {
107 if_exists: bool,
108 name: Ident,
109 cascade: bool,
110 },
111 DropColumn {
113 column_name: Ident,
114 if_exists: bool,
115 cascade: bool,
116 },
117 AttachPartition {
121 partition: Partition,
124 },
125 DetachPartition {
129 partition: Partition,
131 },
132 FreezePartition {
136 partition: Partition,
137 with_name: Option<Ident>,
138 },
139 UnfreezePartition {
143 partition: Partition,
144 with_name: Option<Ident>,
145 },
146 DropPrimaryKey,
150 EnableAlwaysRule { name: Ident },
154 EnableAlwaysTrigger { name: Ident },
158 EnableReplicaRule { name: Ident },
162 EnableReplicaTrigger { name: Ident },
166 EnableRowLevelSecurity,
170 EnableRule { name: Ident },
174 EnableTrigger { name: Ident },
178 RenamePartitions {
180 old_partitions: Vec<Expr>,
181 new_partitions: Vec<Expr>,
182 },
183 AddPartitions {
185 if_not_exists: bool,
186 new_partitions: Vec<Partition>,
187 },
188 DropPartitions {
189 partitions: Vec<Expr>,
190 if_exists: bool,
191 },
192 RenameColumn {
194 old_column_name: Ident,
195 new_column_name: Ident,
196 },
197 RenameTable { table_name: ObjectName },
199 ChangeColumn {
201 old_name: Ident,
202 new_name: Ident,
203 data_type: DataType,
204 options: Vec<ColumnOption>,
205 column_position: Option<MySQLColumnPosition>,
207 },
208 ModifyColumn {
210 col_name: Ident,
211 data_type: DataType,
212 options: Vec<ColumnOption>,
213 column_position: Option<MySQLColumnPosition>,
215 },
216 RenameConstraint { old_name: Ident, new_name: Ident },
220 AlterColumn {
222 column_name: Ident,
223 op: AlterColumnOperation,
224 },
225 SwapWith { table_name: ObjectName },
229 SetTblProperties { table_properties: Vec<SqlOption> },
231
232 OwnerTo { new_owner: Owner },
236}
237
238#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
243#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
244pub enum AlterPolicyOperation {
245 Rename {
246 new_name: Ident,
247 },
248 Apply {
249 to: Option<Vec<Owner>>,
250 using: Option<Expr>,
251 with_check: Option<Expr>,
252 },
253}
254
255impl fmt::Display for AlterPolicyOperation {
256 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
257 match self {
258 AlterPolicyOperation::Rename { new_name } => {
259 write!(f, " RENAME TO {new_name}")
260 }
261 AlterPolicyOperation::Apply {
262 to,
263 using,
264 with_check,
265 } => {
266 if let Some(to) = to {
267 write!(f, " TO {}", display_comma_separated(to))?;
268 }
269 if let Some(using) = using {
270 write!(f, " USING ({using})")?;
271 }
272 if let Some(with_check) = with_check {
273 write!(f, " WITH CHECK ({with_check})")?;
274 }
275 Ok(())
276 }
277 }
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
282#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
283#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
284pub enum Owner {
285 Ident(Ident),
286 CurrentRole,
287 CurrentUser,
288 SessionUser,
289}
290
291impl fmt::Display for Owner {
292 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293 match self {
294 Owner::Ident(ident) => write!(f, "{}", ident),
295 Owner::CurrentRole => write!(f, "CURRENT_ROLE"),
296 Owner::CurrentUser => write!(f, "CURRENT_USER"),
297 Owner::SessionUser => write!(f, "SESSION_USER"),
298 }
299 }
300}
301
302#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
305pub enum AlterIndexOperation {
306 RenameIndex { index_name: ObjectName },
307}
308
309impl fmt::Display for AlterTableOperation {
310 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311 match self {
312 AlterTableOperation::AddPartitions {
313 if_not_exists,
314 new_partitions,
315 } => write!(
316 f,
317 "ADD{ine} {}",
318 display_separated(new_partitions, " "),
319 ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
320 ),
321 AlterTableOperation::AddConstraint(c) => write!(f, "ADD {c}"),
322 AlterTableOperation::AddColumn {
323 column_keyword,
324 if_not_exists,
325 column_def,
326 column_position,
327 } => {
328 write!(f, "ADD")?;
329 if *column_keyword {
330 write!(f, " COLUMN")?;
331 }
332 if *if_not_exists {
333 write!(f, " IF NOT EXISTS")?;
334 }
335 write!(f, " {column_def}")?;
336
337 if let Some(position) = column_position {
338 write!(f, " {position}")?;
339 }
340
341 Ok(())
342 }
343 AlterTableOperation::AddProjection {
344 if_not_exists,
345 name,
346 select: query,
347 } => {
348 write!(f, "ADD PROJECTION")?;
349 if *if_not_exists {
350 write!(f, " IF NOT EXISTS")?;
351 }
352 write!(f, " {} ({})", name, query)
353 }
354 AlterTableOperation::DropProjection { if_exists, name } => {
355 write!(f, "DROP PROJECTION")?;
356 if *if_exists {
357 write!(f, " IF EXISTS")?;
358 }
359 write!(f, " {}", name)
360 }
361 AlterTableOperation::MaterializeProjection {
362 if_exists,
363 name,
364 partition,
365 } => {
366 write!(f, "MATERIALIZE PROJECTION")?;
367 if *if_exists {
368 write!(f, " IF EXISTS")?;
369 }
370 write!(f, " {}", name)?;
371 if let Some(partition) = partition {
372 write!(f, " IN PARTITION {}", partition)?;
373 }
374 Ok(())
375 }
376 AlterTableOperation::ClearProjection {
377 if_exists,
378 name,
379 partition,
380 } => {
381 write!(f, "CLEAR PROJECTION")?;
382 if *if_exists {
383 write!(f, " IF EXISTS")?;
384 }
385 write!(f, " {}", name)?;
386 if let Some(partition) = partition {
387 write!(f, " IN PARTITION {}", partition)?;
388 }
389 Ok(())
390 }
391 AlterTableOperation::AlterColumn { column_name, op } => {
392 write!(f, "ALTER COLUMN {column_name} {op}")
393 }
394 AlterTableOperation::DisableRowLevelSecurity => {
395 write!(f, "DISABLE ROW LEVEL SECURITY")
396 }
397 AlterTableOperation::DisableRule { name } => {
398 write!(f, "DISABLE RULE {name}")
399 }
400 AlterTableOperation::DisableTrigger { name } => {
401 write!(f, "DISABLE TRIGGER {name}")
402 }
403 AlterTableOperation::DropPartitions {
404 partitions,
405 if_exists,
406 } => write!(
407 f,
408 "DROP{ie} PARTITION ({})",
409 display_comma_separated(partitions),
410 ie = if *if_exists { " IF EXISTS" } else { "" }
411 ),
412 AlterTableOperation::DropConstraint {
413 if_exists,
414 name,
415 cascade,
416 } => {
417 write!(
418 f,
419 "DROP CONSTRAINT {}{}{}",
420 if *if_exists { "IF EXISTS " } else { "" },
421 name,
422 if *cascade { " CASCADE" } else { "" },
423 )
424 }
425 AlterTableOperation::DropPrimaryKey => write!(f, "DROP PRIMARY KEY"),
426 AlterTableOperation::DropColumn {
427 column_name,
428 if_exists,
429 cascade,
430 } => write!(
431 f,
432 "DROP COLUMN {}{}{}",
433 if *if_exists { "IF EXISTS " } else { "" },
434 column_name,
435 if *cascade { " CASCADE" } else { "" }
436 ),
437 AlterTableOperation::AttachPartition { partition } => {
438 write!(f, "ATTACH {partition}")
439 }
440 AlterTableOperation::DetachPartition { partition } => {
441 write!(f, "DETACH {partition}")
442 }
443 AlterTableOperation::EnableAlwaysRule { name } => {
444 write!(f, "ENABLE ALWAYS RULE {name}")
445 }
446 AlterTableOperation::EnableAlwaysTrigger { name } => {
447 write!(f, "ENABLE ALWAYS TRIGGER {name}")
448 }
449 AlterTableOperation::EnableReplicaRule { name } => {
450 write!(f, "ENABLE REPLICA RULE {name}")
451 }
452 AlterTableOperation::EnableReplicaTrigger { name } => {
453 write!(f, "ENABLE REPLICA TRIGGER {name}")
454 }
455 AlterTableOperation::EnableRowLevelSecurity => {
456 write!(f, "ENABLE ROW LEVEL SECURITY")
457 }
458 AlterTableOperation::EnableRule { name } => {
459 write!(f, "ENABLE RULE {name}")
460 }
461 AlterTableOperation::EnableTrigger { name } => {
462 write!(f, "ENABLE TRIGGER {name}")
463 }
464 AlterTableOperation::RenamePartitions {
465 old_partitions,
466 new_partitions,
467 } => write!(
468 f,
469 "PARTITION ({}) RENAME TO PARTITION ({})",
470 display_comma_separated(old_partitions),
471 display_comma_separated(new_partitions)
472 ),
473 AlterTableOperation::RenameColumn {
474 old_column_name,
475 new_column_name,
476 } => write!(f, "RENAME COLUMN {old_column_name} TO {new_column_name}"),
477 AlterTableOperation::RenameTable { table_name } => {
478 write!(f, "RENAME TO {table_name}")
479 }
480 AlterTableOperation::ChangeColumn {
481 old_name,
482 new_name,
483 data_type,
484 options,
485 column_position,
486 } => {
487 write!(f, "CHANGE COLUMN {old_name} {new_name} {data_type}")?;
488 if !options.is_empty() {
489 write!(f, " {}", display_separated(options, " "))?;
490 }
491 if let Some(position) = column_position {
492 write!(f, " {position}")?;
493 }
494
495 Ok(())
496 }
497 AlterTableOperation::ModifyColumn {
498 col_name,
499 data_type,
500 options,
501 column_position,
502 } => {
503 write!(f, "MODIFY COLUMN {col_name} {data_type}")?;
504 if !options.is_empty() {
505 write!(f, " {}", display_separated(options, " "))?;
506 }
507 if let Some(position) = column_position {
508 write!(f, " {position}")?;
509 }
510
511 Ok(())
512 }
513 AlterTableOperation::RenameConstraint { old_name, new_name } => {
514 write!(f, "RENAME CONSTRAINT {old_name} TO {new_name}")
515 }
516 AlterTableOperation::SwapWith { table_name } => {
517 write!(f, "SWAP WITH {table_name}")
518 }
519 AlterTableOperation::OwnerTo { new_owner } => {
520 write!(f, "OWNER TO {new_owner}")
521 }
522 AlterTableOperation::SetTblProperties { table_properties } => {
523 write!(
524 f,
525 "SET TBLPROPERTIES({})",
526 display_comma_separated(table_properties)
527 )
528 }
529 AlterTableOperation::FreezePartition {
530 partition,
531 with_name,
532 } => {
533 write!(f, "FREEZE {partition}")?;
534 if let Some(name) = with_name {
535 write!(f, " WITH NAME {name}")?;
536 }
537 Ok(())
538 }
539 AlterTableOperation::UnfreezePartition {
540 partition,
541 with_name,
542 } => {
543 write!(f, "UNFREEZE {partition}")?;
544 if let Some(name) = with_name {
545 write!(f, " WITH NAME {name}")?;
546 }
547 Ok(())
548 }
549 }
550 }
551}
552
553impl fmt::Display for AlterIndexOperation {
554 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
555 match self {
556 AlterIndexOperation::RenameIndex { index_name } => {
557 write!(f, "RENAME TO {index_name}")
558 }
559 }
560 }
561}
562
563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
566#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
567pub enum AlterColumnOperation {
568 SetNotNull,
570 DropNotNull,
572 SetDefault { value: Expr },
574 DropDefault,
576 SetDataType {
578 data_type: DataType,
579 using: Option<Expr>,
581 },
582 AddGenerated {
586 generated_as: Option<GeneratedAs>,
587 sequence_options: Option<Vec<SequenceOptions>>,
588 },
589}
590
591impl fmt::Display for AlterColumnOperation {
592 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
593 match self {
594 AlterColumnOperation::SetNotNull => write!(f, "SET NOT NULL",),
595 AlterColumnOperation::DropNotNull => write!(f, "DROP NOT NULL",),
596 AlterColumnOperation::SetDefault { value } => {
597 write!(f, "SET DEFAULT {value}")
598 }
599 AlterColumnOperation::DropDefault {} => {
600 write!(f, "DROP DEFAULT")
601 }
602 AlterColumnOperation::SetDataType { data_type, using } => {
603 if let Some(expr) = using {
604 write!(f, "SET DATA TYPE {data_type} USING {expr}")
605 } else {
606 write!(f, "SET DATA TYPE {data_type}")
607 }
608 }
609 AlterColumnOperation::AddGenerated {
610 generated_as,
611 sequence_options,
612 } => {
613 let generated_as = match generated_as {
614 Some(GeneratedAs::Always) => " ALWAYS",
615 Some(GeneratedAs::ByDefault) => " BY DEFAULT",
616 _ => "",
617 };
618
619 write!(f, "ADD GENERATED{generated_as} AS IDENTITY",)?;
620 if let Some(options) = sequence_options {
621 write!(f, " (")?;
622
623 for sequence_option in options {
624 write!(f, "{sequence_option}")?;
625 }
626
627 write!(f, " )")?;
628 }
629 Ok(())
630 }
631 }
632 }
633}
634
635#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
638#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
639#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
640pub enum TableConstraint {
641 Unique {
654 name: Option<Ident>,
658 index_name: Option<Ident>,
660 index_type_display: KeyOrIndexDisplay,
662 index_type: Option<IndexType>,
666 columns: Vec<Ident>,
668 index_options: Vec<IndexOption>,
669 characteristics: Option<ConstraintCharacteristics>,
670 },
671 PrimaryKey {
690 name: Option<Ident>,
694 index_name: Option<Ident>,
696 index_type: Option<IndexType>,
700 columns: Vec<Ident>,
702 index_options: Vec<IndexOption>,
703 characteristics: Option<ConstraintCharacteristics>,
704 },
705 ForeignKey {
711 name: Option<Ident>,
712 columns: Vec<Ident>,
713 foreign_table: ObjectName,
714 referred_columns: Vec<Ident>,
715 on_delete: Option<ReferentialAction>,
716 on_update: Option<ReferentialAction>,
717 characteristics: Option<ConstraintCharacteristics>,
718 },
719 Check {
721 name: Option<Ident>,
722 expr: Box<Expr>,
723 },
724 Index {
731 display_as_key: bool,
733 name: Option<Ident>,
735 index_type: Option<IndexType>,
739 columns: Vec<Ident>,
741 },
742 FulltextOrSpatial {
756 fulltext: bool,
758 index_type_display: KeyOrIndexDisplay,
760 opt_index_name: Option<Ident>,
762 columns: Vec<Ident>,
764 },
765}
766
767impl fmt::Display for TableConstraint {
768 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
769 match self {
770 TableConstraint::Unique {
771 name,
772 index_name,
773 index_type_display,
774 index_type,
775 columns,
776 index_options,
777 characteristics,
778 } => {
779 write!(
780 f,
781 "{}UNIQUE{index_type_display:>}{}{} ({})",
782 display_constraint_name(name),
783 display_option_spaced(index_name),
784 display_option(" USING ", "", index_type),
785 display_comma_separated(columns),
786 )?;
787
788 if !index_options.is_empty() {
789 write!(f, " {}", display_separated(index_options, " "))?;
790 }
791
792 write!(f, "{}", display_option_spaced(characteristics))?;
793 Ok(())
794 }
795 TableConstraint::PrimaryKey {
796 name,
797 index_name,
798 index_type,
799 columns,
800 index_options,
801 characteristics,
802 } => {
803 write!(
804 f,
805 "{}PRIMARY KEY{}{} ({})",
806 display_constraint_name(name),
807 display_option_spaced(index_name),
808 display_option(" USING ", "", index_type),
809 display_comma_separated(columns),
810 )?;
811
812 if !index_options.is_empty() {
813 write!(f, " {}", display_separated(index_options, " "))?;
814 }
815
816 write!(f, "{}", display_option_spaced(characteristics))?;
817 Ok(())
818 }
819 TableConstraint::ForeignKey {
820 name,
821 columns,
822 foreign_table,
823 referred_columns,
824 on_delete,
825 on_update,
826 characteristics,
827 } => {
828 write!(
829 f,
830 "{}FOREIGN KEY ({}) REFERENCES {}({})",
831 display_constraint_name(name),
832 display_comma_separated(columns),
833 foreign_table,
834 display_comma_separated(referred_columns),
835 )?;
836 if let Some(action) = on_delete {
837 write!(f, " ON DELETE {action}")?;
838 }
839 if let Some(action) = on_update {
840 write!(f, " ON UPDATE {action}")?;
841 }
842 if let Some(characteristics) = characteristics {
843 write!(f, " {}", characteristics)?;
844 }
845 Ok(())
846 }
847 TableConstraint::Check { name, expr } => {
848 write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
849 }
850 TableConstraint::Index {
851 display_as_key,
852 name,
853 index_type,
854 columns,
855 } => {
856 write!(f, "{}", if *display_as_key { "KEY" } else { "INDEX" })?;
857 if let Some(name) = name {
858 write!(f, " {name}")?;
859 }
860 if let Some(index_type) = index_type {
861 write!(f, " USING {index_type}")?;
862 }
863 write!(f, " ({})", display_comma_separated(columns))?;
864
865 Ok(())
866 }
867 Self::FulltextOrSpatial {
868 fulltext,
869 index_type_display,
870 opt_index_name,
871 columns,
872 } => {
873 if *fulltext {
874 write!(f, "FULLTEXT")?;
875 } else {
876 write!(f, "SPATIAL")?;
877 }
878
879 write!(f, "{index_type_display:>}")?;
880
881 if let Some(name) = opt_index_name {
882 write!(f, " {name}")?;
883 }
884
885 write!(f, " ({})", display_comma_separated(columns))?;
886
887 Ok(())
888 }
889 }
890 }
891}
892
893#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
901#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
902#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
903pub enum KeyOrIndexDisplay {
904 None,
906 Key,
908 Index,
910}
911
912impl KeyOrIndexDisplay {
913 pub fn is_none(self) -> bool {
914 matches!(self, Self::None)
915 }
916}
917
918impl fmt::Display for KeyOrIndexDisplay {
919 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
920 let left_space = matches!(f.align(), Some(fmt::Alignment::Right));
921
922 if left_space && !self.is_none() {
923 f.write_char(' ')?
924 }
925
926 match self {
927 KeyOrIndexDisplay::None => {
928 write!(f, "")
929 }
930 KeyOrIndexDisplay::Key => {
931 write!(f, "KEY")
932 }
933 KeyOrIndexDisplay::Index => {
934 write!(f, "INDEX")
935 }
936 }
937 }
938}
939
940#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
949#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
950#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
951pub enum IndexType {
952 BTree,
953 Hash,
954 }
956
957impl fmt::Display for IndexType {
958 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
959 match self {
960 Self::BTree => write!(f, "BTREE"),
961 Self::Hash => write!(f, "HASH"),
962 }
963 }
964}
965
966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
973#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
974#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
975pub enum IndexOption {
976 Using(IndexType),
977 Comment(String),
978}
979
980impl fmt::Display for IndexOption {
981 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
982 match self {
983 Self::Using(index_type) => write!(f, "USING {index_type}"),
984 Self::Comment(s) => write!(f, "COMMENT '{s}'"),
985 }
986 }
987}
988
989#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
990#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
991#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
992pub struct ProcedureParam {
993 pub name: Ident,
994 pub data_type: DataType,
995}
996
997impl fmt::Display for ProcedureParam {
998 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
999 write!(f, "{} {}", self.name, self.data_type)
1000 }
1001}
1002
1003#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1005#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1006#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1007pub struct ColumnDef {
1008 pub name: Ident,
1009 pub data_type: DataType,
1010 pub collation: Option<ObjectName>,
1011 pub options: Vec<ColumnOptionDef>,
1012}
1013
1014impl fmt::Display for ColumnDef {
1015 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1016 if self.data_type == DataType::Unspecified {
1017 write!(f, "{}", self.name)?;
1018 } else {
1019 write!(f, "{} {}", self.name, self.data_type)?;
1020 }
1021 if let Some(collation) = &self.collation {
1022 write!(f, " COLLATE {collation}")?;
1023 }
1024 for option in &self.options {
1025 write!(f, " {option}")?;
1026 }
1027 Ok(())
1028 }
1029}
1030
1031#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1048#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1049#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1050pub struct ViewColumnDef {
1051 pub name: Ident,
1052 pub data_type: Option<DataType>,
1053 pub options: Option<Vec<ColumnOption>>,
1054}
1055
1056impl fmt::Display for ViewColumnDef {
1057 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1058 write!(f, "{}", self.name)?;
1059 if let Some(data_type) = self.data_type.as_ref() {
1060 write!(f, " {}", data_type)?;
1061 }
1062 if let Some(options) = self.options.as_ref() {
1063 write!(f, " {}", display_comma_separated(options.as_slice()))?;
1064 }
1065 Ok(())
1066 }
1067}
1068
1069#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1086#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1087#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1088pub struct ColumnOptionDef {
1089 pub name: Option<Ident>,
1090 pub option: ColumnOption,
1091}
1092
1093impl fmt::Display for ColumnOptionDef {
1094 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1095 write!(f, "{}{}", display_constraint_name(&self.name), self.option)
1096 }
1097}
1098
1099#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1107#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1108#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1109pub enum IdentityPropertyKind {
1110 Autoincrement(IdentityProperty),
1118 Identity(IdentityProperty),
1131}
1132
1133impl fmt::Display for IdentityPropertyKind {
1134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1135 let (command, property) = match self {
1136 IdentityPropertyKind::Identity(property) => ("IDENTITY", property),
1137 IdentityPropertyKind::Autoincrement(property) => ("AUTOINCREMENT", property),
1138 };
1139 write!(f, "{command}")?;
1140 if let Some(parameters) = &property.parameters {
1141 write!(f, "{parameters}")?;
1142 }
1143 if let Some(order) = &property.order {
1144 write!(f, "{order}")?;
1145 }
1146 Ok(())
1147 }
1148}
1149
1150#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1152#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1153pub struct IdentityProperty {
1154 pub parameters: Option<IdentityPropertyFormatKind>,
1155 pub order: Option<IdentityPropertyOrder>,
1156}
1157
1158#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1174#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1175pub enum IdentityPropertyFormatKind {
1176 FunctionCall(IdentityParameters),
1184 StartAndIncrement(IdentityParameters),
1191}
1192
1193impl fmt::Display for IdentityPropertyFormatKind {
1194 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1195 match self {
1196 IdentityPropertyFormatKind::FunctionCall(parameters) => {
1197 write!(f, "({}, {})", parameters.seed, parameters.increment)
1198 }
1199 IdentityPropertyFormatKind::StartAndIncrement(parameters) => {
1200 write!(
1201 f,
1202 " START {} INCREMENT {}",
1203 parameters.seed, parameters.increment
1204 )
1205 }
1206 }
1207 }
1208}
1209#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1211#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1212pub struct IdentityParameters {
1213 pub seed: Expr,
1214 pub increment: Expr,
1215}
1216
1217#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1224#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1225#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1226pub enum IdentityPropertyOrder {
1227 Order,
1228 NoOrder,
1229}
1230
1231impl fmt::Display for IdentityPropertyOrder {
1232 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1233 match self {
1234 IdentityPropertyOrder::Order => write!(f, " ORDER"),
1235 IdentityPropertyOrder::NoOrder => write!(f, " NOORDER"),
1236 }
1237 }
1238}
1239
1240#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1248#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1249#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1250pub enum ColumnPolicy {
1251 MaskingPolicy(ColumnPolicyProperty),
1252 ProjectionPolicy(ColumnPolicyProperty),
1253}
1254
1255impl fmt::Display for ColumnPolicy {
1256 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1257 let (command, property) = match self {
1258 ColumnPolicy::MaskingPolicy(property) => ("MASKING POLICY", property),
1259 ColumnPolicy::ProjectionPolicy(property) => ("PROJECTION POLICY", property),
1260 };
1261 if property.with {
1262 write!(f, "WITH ")?;
1263 }
1264 write!(f, "{command} {}", property.policy_name)?;
1265 if let Some(using_columns) = &property.using_columns {
1266 write!(f, " USING ({})", display_comma_separated(using_columns))?;
1267 }
1268 Ok(())
1269 }
1270}
1271
1272#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1273#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1274#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1275pub struct ColumnPolicyProperty {
1276 pub with: bool,
1283 pub policy_name: Ident,
1284 pub using_columns: Option<Vec<Ident>>,
1285}
1286
1287#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1294#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1295#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1296pub struct TagsColumnOption {
1297 pub with: bool,
1304 pub tags: Vec<Tag>,
1305}
1306
1307impl fmt::Display for TagsColumnOption {
1308 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1309 if self.with {
1310 write!(f, "WITH ")?;
1311 }
1312 write!(f, "TAG ({})", display_comma_separated(&self.tags))?;
1313 Ok(())
1314 }
1315}
1316
1317#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1320#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1321#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1322pub enum ColumnOption {
1323 Null,
1325 NotNull,
1327 Default(Expr),
1329
1330 Materialized(Expr),
1336 Ephemeral(Option<Expr>),
1338 Alias(Expr),
1340
1341 Unique {
1343 is_primary: bool,
1344 characteristics: Option<ConstraintCharacteristics>,
1345 },
1346 ForeignKey {
1354 foreign_table: ObjectName,
1355 referred_columns: Vec<Ident>,
1356 on_delete: Option<ReferentialAction>,
1357 on_update: Option<ReferentialAction>,
1358 characteristics: Option<ConstraintCharacteristics>,
1359 },
1360 Check(Expr),
1362 DialectSpecific(Vec<Token>),
1366 CharacterSet(ObjectName),
1367 Comment(String),
1368 OnUpdate(Expr),
1369 Generated {
1372 generated_as: GeneratedAs,
1373 sequence_options: Option<Vec<SequenceOptions>>,
1374 generation_expr: Option<Expr>,
1375 generation_expr_mode: Option<GeneratedExpressionMode>,
1376 generated_keyword: bool,
1378 },
1379 Options(Vec<SqlOption>),
1387 Identity(IdentityPropertyKind),
1395 OnConflict(Keyword),
1398 Policy(ColumnPolicy),
1406 Tags(TagsColumnOption),
1413}
1414
1415impl fmt::Display for ColumnOption {
1416 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1417 use ColumnOption::*;
1418 match self {
1419 Null => write!(f, "NULL"),
1420 NotNull => write!(f, "NOT NULL"),
1421 Default(expr) => write!(f, "DEFAULT {expr}"),
1422 Materialized(expr) => write!(f, "MATERIALIZED {expr}"),
1423 Ephemeral(expr) => {
1424 if let Some(e) = expr {
1425 write!(f, "EPHEMERAL {e}")
1426 } else {
1427 write!(f, "EPHEMERAL")
1428 }
1429 }
1430 Alias(expr) => write!(f, "ALIAS {expr}"),
1431 Unique {
1432 is_primary,
1433 characteristics,
1434 } => {
1435 write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })?;
1436 if let Some(characteristics) = characteristics {
1437 write!(f, " {}", characteristics)?;
1438 }
1439 Ok(())
1440 }
1441 ForeignKey {
1442 foreign_table,
1443 referred_columns,
1444 on_delete,
1445 on_update,
1446 characteristics,
1447 } => {
1448 write!(f, "REFERENCES {foreign_table}")?;
1449 if !referred_columns.is_empty() {
1450 write!(f, " ({})", display_comma_separated(referred_columns))?;
1451 }
1452 if let Some(action) = on_delete {
1453 write!(f, " ON DELETE {action}")?;
1454 }
1455 if let Some(action) = on_update {
1456 write!(f, " ON UPDATE {action}")?;
1457 }
1458 if let Some(characteristics) = characteristics {
1459 write!(f, " {}", characteristics)?;
1460 }
1461 Ok(())
1462 }
1463 Check(expr) => write!(f, "CHECK ({expr})"),
1464 DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
1465 CharacterSet(n) => write!(f, "CHARACTER SET {n}"),
1466 Comment(v) => write!(f, "COMMENT '{}'", escape_single_quote_string(v)),
1467 OnUpdate(expr) => write!(f, "ON UPDATE {expr}"),
1468 Generated {
1469 generated_as,
1470 sequence_options,
1471 generation_expr,
1472 generation_expr_mode,
1473 generated_keyword,
1474 } => {
1475 if let Some(expr) = generation_expr {
1476 let modifier = match generation_expr_mode {
1477 None => "",
1478 Some(GeneratedExpressionMode::Virtual) => " VIRTUAL",
1479 Some(GeneratedExpressionMode::Stored) => " STORED",
1480 };
1481 if *generated_keyword {
1482 write!(f, "GENERATED ALWAYS AS ({expr}){modifier}")?;
1483 } else {
1484 write!(f, "AS ({expr}){modifier}")?;
1485 }
1486 Ok(())
1487 } else {
1488 let when = match generated_as {
1490 GeneratedAs::Always => "ALWAYS",
1491 GeneratedAs::ByDefault => "BY DEFAULT",
1492 GeneratedAs::ExpStored => unreachable!(),
1494 };
1495 write!(f, "GENERATED {when} AS IDENTITY")?;
1496 if sequence_options.is_some() {
1497 let so = sequence_options.as_ref().unwrap();
1498 if !so.is_empty() {
1499 write!(f, " (")?;
1500 }
1501 for sequence_option in so {
1502 write!(f, "{sequence_option}")?;
1503 }
1504 if !so.is_empty() {
1505 write!(f, " )")?;
1506 }
1507 }
1508 Ok(())
1509 }
1510 }
1511 Options(options) => {
1512 write!(f, "OPTIONS({})", display_comma_separated(options))
1513 }
1514 Identity(parameters) => {
1515 write!(f, "{parameters}")
1516 }
1517 OnConflict(keyword) => {
1518 write!(f, "ON CONFLICT {:?}", keyword)?;
1519 Ok(())
1520 }
1521 Policy(parameters) => {
1522 write!(f, "{parameters}")
1523 }
1524 Tags(tags) => {
1525 write!(f, "{tags}")
1526 }
1527 }
1528 }
1529}
1530
1531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1534#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1535#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1536pub enum GeneratedAs {
1537 Always,
1538 ByDefault,
1539 ExpStored,
1540}
1541
1542#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1547pub enum GeneratedExpressionMode {
1548 Virtual,
1549 Stored,
1550}
1551
1552#[must_use]
1553fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
1554 struct ConstraintName<'a>(&'a Option<Ident>);
1555 impl<'a> fmt::Display for ConstraintName<'a> {
1556 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1557 if let Some(name) = self.0 {
1558 write!(f, "CONSTRAINT {name} ")?;
1559 }
1560 Ok(())
1561 }
1562 }
1563 ConstraintName(name)
1564}
1565
1566#[must_use]
1570fn display_option<'a, T: fmt::Display>(
1571 prefix: &'a str,
1572 postfix: &'a str,
1573 option: &'a Option<T>,
1574) -> impl fmt::Display + 'a {
1575 struct OptionDisplay<'a, T>(&'a str, &'a str, &'a Option<T>);
1576 impl<'a, T: fmt::Display> fmt::Display for OptionDisplay<'a, T> {
1577 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1578 if let Some(inner) = self.2 {
1579 let (prefix, postfix) = (self.0, self.1);
1580 write!(f, "{prefix}{inner}{postfix}")?;
1581 }
1582 Ok(())
1583 }
1584 }
1585 OptionDisplay(prefix, postfix, option)
1586}
1587
1588#[must_use]
1592fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Display + '_ {
1593 display_option(" ", "", option)
1594}
1595
1596#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Default, Eq, Ord, Hash)]
1600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1602pub struct ConstraintCharacteristics {
1603 pub deferrable: Option<bool>,
1605 pub initially: Option<DeferrableInitial>,
1607 pub enforced: Option<bool>,
1609}
1610
1611#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1612#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1613#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1614pub enum DeferrableInitial {
1615 Immediate,
1617 Deferred,
1619}
1620
1621impl ConstraintCharacteristics {
1622 fn deferrable_text(&self) -> Option<&'static str> {
1623 self.deferrable.map(|deferrable| {
1624 if deferrable {
1625 "DEFERRABLE"
1626 } else {
1627 "NOT DEFERRABLE"
1628 }
1629 })
1630 }
1631
1632 fn initially_immediate_text(&self) -> Option<&'static str> {
1633 self.initially
1634 .map(|initially_immediate| match initially_immediate {
1635 DeferrableInitial::Immediate => "INITIALLY IMMEDIATE",
1636 DeferrableInitial::Deferred => "INITIALLY DEFERRED",
1637 })
1638 }
1639
1640 fn enforced_text(&self) -> Option<&'static str> {
1641 self.enforced.map(
1642 |enforced| {
1643 if enforced {
1644 "ENFORCED"
1645 } else {
1646 "NOT ENFORCED"
1647 }
1648 },
1649 )
1650 }
1651}
1652
1653impl fmt::Display for ConstraintCharacteristics {
1654 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1655 let deferrable = self.deferrable_text();
1656 let initially_immediate = self.initially_immediate_text();
1657 let enforced = self.enforced_text();
1658
1659 match (deferrable, initially_immediate, enforced) {
1660 (None, None, None) => Ok(()),
1661 (None, None, Some(enforced)) => write!(f, "{enforced}"),
1662 (None, Some(initial), None) => write!(f, "{initial}"),
1663 (None, Some(initial), Some(enforced)) => write!(f, "{initial} {enforced}"),
1664 (Some(deferrable), None, None) => write!(f, "{deferrable}"),
1665 (Some(deferrable), None, Some(enforced)) => write!(f, "{deferrable} {enforced}"),
1666 (Some(deferrable), Some(initial), None) => write!(f, "{deferrable} {initial}"),
1667 (Some(deferrable), Some(initial), Some(enforced)) => {
1668 write!(f, "{deferrable} {initial} {enforced}")
1669 }
1670 }
1671 }
1672}
1673
1674#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1679#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1680#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1681pub enum ReferentialAction {
1682 Restrict,
1683 Cascade,
1684 SetNull,
1685 NoAction,
1686 SetDefault,
1687}
1688
1689impl fmt::Display for ReferentialAction {
1690 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1691 f.write_str(match self {
1692 ReferentialAction::Restrict => "RESTRICT",
1693 ReferentialAction::Cascade => "CASCADE",
1694 ReferentialAction::SetNull => "SET NULL",
1695 ReferentialAction::NoAction => "NO ACTION",
1696 ReferentialAction::SetDefault => "SET DEFAULT",
1697 })
1698 }
1699}
1700
1701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1703#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1704#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1705pub enum UserDefinedTypeRepresentation {
1706 Composite {
1707 attributes: Vec<UserDefinedTypeCompositeAttributeDef>,
1708 },
1709 Enum { labels: Vec<Ident> },
1711}
1712
1713impl fmt::Display for UserDefinedTypeRepresentation {
1714 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1715 match self {
1716 UserDefinedTypeRepresentation::Composite { attributes } => {
1717 write!(f, "({})", display_comma_separated(attributes))
1718 }
1719 UserDefinedTypeRepresentation::Enum { labels } => {
1720 write!(f, "ENUM ({})", display_comma_separated(labels))
1721 }
1722 }
1723 }
1724}
1725
1726#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1728#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1729#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1730pub struct UserDefinedTypeCompositeAttributeDef {
1731 pub name: Ident,
1732 pub data_type: DataType,
1733 pub collation: Option<ObjectName>,
1734}
1735
1736impl fmt::Display for UserDefinedTypeCompositeAttributeDef {
1737 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1738 write!(f, "{} {}", self.name, self.data_type)?;
1739 if let Some(collation) = &self.collation {
1740 write!(f, " COLLATE {collation}")?;
1741 }
1742 Ok(())
1743 }
1744}
1745
1746#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1751#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1752pub enum Partition {
1753 Identifier(Ident),
1754 Expr(Expr),
1755 Part(Expr),
1758 Partitions(Vec<Expr>),
1759}
1760
1761impl fmt::Display for Partition {
1762 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1763 match self {
1764 Partition::Identifier(id) => write!(f, "PARTITION ID {id}"),
1765 Partition::Expr(expr) => write!(f, "PARTITION {expr}"),
1766 Partition::Part(expr) => write!(f, "PART {expr}"),
1767 Partition::Partitions(partitions) => {
1768 write!(f, "PARTITION ({})", display_comma_separated(partitions))
1769 }
1770 }
1771 }
1772}
1773
1774#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1777#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1778#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1779pub enum Deduplicate {
1780 All,
1781 ByExpression(Expr),
1782}
1783
1784impl fmt::Display for Deduplicate {
1785 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1786 match self {
1787 Deduplicate::All => write!(f, "DEDUPLICATE"),
1788 Deduplicate::ByExpression(expr) => write!(f, "DEDUPLICATE BY {expr}"),
1789 }
1790 }
1791}
1792
1793#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1800pub struct ClusteredBy {
1801 pub columns: Vec<Ident>,
1802 pub sorted_by: Option<Vec<OrderByExpr>>,
1803 pub num_buckets: Value,
1804}
1805
1806impl fmt::Display for ClusteredBy {
1807 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1808 write!(
1809 f,
1810 "CLUSTERED BY ({})",
1811 display_comma_separated(&self.columns)
1812 )?;
1813 if let Some(ref sorted_by) = self.sorted_by {
1814 write!(f, " SORTED BY ({})", display_comma_separated(sorted_by))?;
1815 }
1816 write!(f, " INTO {} BUCKETS", self.num_buckets)
1817 }
1818}