1use std::collections::BTreeMap;
16use std::fmt::Display;
17use std::fmt::Formatter;
18use std::time::Duration;
19
20use derive_visitor::Drive;
21use derive_visitor::DriveMut;
22
23use crate::ast::quote::QuotedString;
24use crate::ast::statements::show::ShowLimit;
25use crate::ast::write_comma_separated_list;
26use crate::ast::write_comma_separated_string_map;
27use crate::ast::write_dot_separated_list;
28use crate::ast::write_space_separated_string_map;
29use crate::ast::CreateOption;
30use crate::ast::Expr;
31use crate::ast::Identifier;
32use crate::ast::Query;
33use crate::ast::TableIndexType;
34use crate::ast::TableReference;
35use crate::ast::TimeTravelPoint;
36use crate::ast::TypeName;
37use crate::ast::UriLocation;
38
39#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
40pub struct ShowTablesStmt {
41 pub catalog: Option<Identifier>,
42 pub database: Option<Identifier>,
43 pub full: bool,
44 pub limit: Option<ShowLimit>,
45 pub with_history: bool,
46}
47
48impl Display for ShowTablesStmt {
49 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
50 write!(f, "SHOW")?;
51 if self.full {
52 write!(f, " FULL")?;
53 }
54 write!(f, " TABLES")?;
55 if self.with_history {
56 write!(f, " HISTORY")?;
57 }
58 if let Some(database) = &self.database {
59 write!(f, " FROM ")?;
60 if let Some(catalog) = &self.catalog {
61 write!(f, "{catalog}.",)?;
62 }
63 write!(f, "{database}")?;
64 }
65 if let Some(limit) = &self.limit {
66 write!(f, " {limit}")?;
67 }
68
69 Ok(())
70 }
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
74pub struct ShowCreateTableStmt {
75 pub catalog: Option<Identifier>,
76 pub database: Option<Identifier>,
77 pub table: Identifier,
78 pub with_quoted_ident: bool,
79}
80
81impl Display for ShowCreateTableStmt {
82 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
83 write!(f, "SHOW CREATE TABLE ")?;
84 write_dot_separated_list(
85 f,
86 self.catalog
87 .iter()
88 .chain(&self.database)
89 .chain(Some(&self.table)),
90 )?;
91 if self.with_quoted_ident {
92 write!(f, " WITH QUOTED_IDENTIFIERS")?
93 }
94 Ok(())
95 }
96}
97
98#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
99pub struct ShowTablesStatusStmt {
100 pub database: Option<Identifier>,
101 pub limit: Option<ShowLimit>,
102}
103
104impl Display for ShowTablesStatusStmt {
105 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
106 write!(f, "SHOW TABLE STATUS")?;
107 if let Some(database) = &self.database {
108 write!(f, " FROM {database}")?;
109 }
110 if let Some(limit) = &self.limit {
111 write!(f, " {limit}")?;
112 }
113
114 Ok(())
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
119pub struct ShowDropTablesStmt {
120 pub database: Option<Identifier>,
121 pub limit: Option<ShowLimit>,
122}
123
124impl Display for ShowDropTablesStmt {
125 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
126 write!(f, "SHOW DROP TABLES")?;
127 if let Some(database) = &self.database {
128 write!(f, " FROM {database}")?;
129 }
130 if let Some(limit) = &self.limit {
131 write!(f, " {limit}")?;
132 }
133
134 Ok(())
135 }
136}
137
138#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
139pub enum ClusterType {
140 Linear,
141 Hilbert,
142}
143
144impl Display for ClusterType {
145 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
146 match self {
147 ClusterType::Linear => write!(f, "LINEAR"),
148 ClusterType::Hilbert => write!(f, "HILBERT"),
149 }
150 }
151}
152
153impl std::str::FromStr for ClusterType {
154 type Err = ();
155 fn from_str(s: &str) -> Result<Self, Self::Err> {
156 match s.to_lowercase().as_str() {
157 "linear" => Ok(ClusterType::Linear),
158 "hilbert" => Ok(ClusterType::Hilbert),
159 _ => Err(()),
160 }
161 }
162}
163
164#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
165pub struct ClusterOption {
166 pub cluster_type: ClusterType,
167 pub cluster_exprs: Vec<Expr>,
168}
169
170impl Display for ClusterOption {
171 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
172 write!(f, "CLUSTER BY {}(", self.cluster_type)?;
173 write_comma_separated_list(f, &self.cluster_exprs)?;
174 write!(f, ")")
175 }
176}
177
178#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
179pub struct CreateTableStmt {
180 pub create_option: CreateOption,
181 pub catalog: Option<Identifier>,
182 pub database: Option<Identifier>,
183 pub table: Identifier,
184 pub source: Option<CreateTableSource>,
185 pub engine: Option<Engine>,
186 pub uri_location: Option<UriLocation>,
187 pub cluster_by: Option<ClusterOption>,
188 pub table_options: BTreeMap<String, String>,
189 pub iceberg_table_partition: Option<Vec<Identifier>>,
190 pub table_properties: Option<BTreeMap<String, String>>,
191 pub as_query: Option<Box<Query>>,
192 pub table_type: TableType,
193}
194
195#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
196pub enum TableType {
197 Normal,
198 Transient,
199 Temporary,
200}
201
202impl Display for CreateTableStmt {
203 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
204 write!(f, "CREATE")?;
205 if let CreateOption::CreateOrReplace = self.create_option {
206 write!(f, " OR REPLACE")?;
207 }
208 match self.table_type {
209 TableType::Normal => {}
210 TableType::Transient => write!(f, " TRANSIENT")?,
211 TableType::Temporary => write!(f, " TEMPORARY")?,
212 };
213 write!(f, " TABLE")?;
214 if let CreateOption::CreateIfNotExists = self.create_option {
215 write!(f, " IF NOT EXISTS")?;
216 }
217 write!(f, " ")?;
218 write_dot_separated_list(
219 f,
220 self.catalog
221 .iter()
222 .chain(&self.database)
223 .chain(Some(&self.table)),
224 )?;
225
226 if let Some(source) = &self.source {
227 write!(f, " {source}")?;
228 }
229
230 if let Some(engine) = &self.engine {
231 write!(f, " ENGINE = {engine}")?;
232 }
233
234 if let Some(uri_location) = &self.uri_location {
235 write!(f, " {uri_location}")?;
236 }
237
238 if let Some(cluster_by) = &self.cluster_by {
239 write!(f, " {cluster_by}")?;
240 }
241
242 if !self.table_options.is_empty() {
244 write!(f, " ")?;
245 write_space_separated_string_map(f, &self.table_options)?;
246 }
247
248 if let Some(iceberg_table_partition) = &self.iceberg_table_partition {
249 write!(f, " PARTITION BY(")?;
250 write_comma_separated_list(f, iceberg_table_partition)?;
251 write!(f, ")")?;
252 }
253
254 if let Some(table_properties) = &self.table_properties {
255 write!(f, " PROPERTIES(")?;
256 write_space_separated_string_map(f, table_properties)?;
257 write!(f, ")")?;
258 }
259
260 if let Some(as_query) = &self.as_query {
261 write!(f, " AS {as_query}")?;
262 }
263
264 Ok(())
265 }
266}
267
268#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
269pub struct AttachTableStmt {
270 pub catalog: Option<Identifier>,
271 pub database: Option<Identifier>,
272 pub table: Identifier,
273 pub columns_opt: Option<Vec<Identifier>>,
274 pub uri_location: UriLocation,
275}
276
277impl Display for AttachTableStmt {
278 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
279 write!(f, "ATTACH TABLE ")?;
280 write_dot_separated_list(
281 f,
282 self.catalog
283 .iter()
284 .chain(&self.database)
285 .chain(Some(&self.table)),
286 )?;
287
288 if let Some(cols) = &self.columns_opt {
289 write!(f, " (")?;
290 write_comma_separated_list(f, cols.iter())?;
291 write!(f, ")")?;
292 }
293
294 write!(f, " {}", self.uri_location)?;
295
296 Ok(())
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
301pub enum CreateTableSource {
302 Columns(Vec<ColumnDefinition>, Option<Vec<TableIndexDefinition>>),
303 Like {
304 catalog: Option<Identifier>,
305 database: Option<Identifier>,
306 table: Identifier,
307 },
308}
309
310impl Display for CreateTableSource {
311 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
312 match self {
313 CreateTableSource::Columns(columns, table_indexes) => {
314 write!(f, "(")?;
315 write_comma_separated_list(f, columns)?;
316 if let Some(table_indexes) = table_indexes {
317 write!(f, ", ")?;
318 write_comma_separated_list(f, table_indexes)?;
319 }
320 write!(f, ")")
321 }
322 CreateTableSource::Like {
323 catalog,
324 database,
325 table,
326 } => {
327 write!(f, "LIKE ")?;
328 write_dot_separated_list(f, catalog.iter().chain(database).chain(Some(table)))
329 }
330 }
331 }
332}
333
334#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
335pub struct DescribeTableStmt {
336 pub catalog: Option<Identifier>,
337 pub database: Option<Identifier>,
338 pub table: Identifier,
339}
340
341impl Display for DescribeTableStmt {
342 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
343 write!(f, "DESCRIBE ")?;
344 write_dot_separated_list(
345 f,
346 self.catalog
347 .iter()
348 .chain(self.database.iter().chain(Some(&self.table))),
349 )
350 }
351}
352
353#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
354pub struct DropTableStmt {
355 pub if_exists: bool,
356 pub catalog: Option<Identifier>,
357 pub database: Option<Identifier>,
358 pub table: Identifier,
359 pub all: bool,
360}
361
362impl Display for DropTableStmt {
363 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
364 write!(f, "DROP TABLE ")?;
365 if self.if_exists {
366 write!(f, "IF EXISTS ")?;
367 }
368 write_dot_separated_list(
369 f,
370 self.catalog
371 .iter()
372 .chain(&self.database)
373 .chain(Some(&self.table)),
374 )?;
375 if self.all {
376 write!(f, " ALL")?;
377 }
378
379 Ok(())
380 }
381}
382
383#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
384pub struct UndropTableStmt {
385 pub catalog: Option<Identifier>,
386 pub database: Option<Identifier>,
387 pub table: Identifier,
388}
389
390impl Display for UndropTableStmt {
391 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
392 write!(f, "UNDROP TABLE ")?;
393 write_dot_separated_list(
394 f,
395 self.catalog
396 .iter()
397 .chain(&self.database)
398 .chain(Some(&self.table)),
399 )
400 }
401}
402
403#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
404pub struct AlterTableStmt {
405 pub if_exists: bool,
406 pub table_reference: TableReference,
407 pub action: AlterTableAction,
408}
409
410impl Display for AlterTableStmt {
411 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
412 write!(f, "ALTER TABLE")?;
413 if self.if_exists {
414 write!(f, " IF EXISTS")?;
415 }
416 write!(f, " {}", self.table_reference)?;
417 write!(f, " {}", self.action)
418 }
419}
420
421#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
422pub enum AlterTableAction {
423 RenameTable {
424 new_table: Identifier,
425 },
426 AddColumn {
427 column: ColumnDefinition,
428 option: AddColumnOption,
429 },
430 RenameColumn {
431 old_column: Identifier,
432 new_column: Identifier,
433 },
434 ModifyTableComment {
435 new_comment: String,
436 },
437 ModifyColumn {
438 action: ModifyColumnAction,
439 },
440 DropColumn {
441 column: Identifier,
442 },
443 AlterTableClusterKey {
444 cluster_by: ClusterOption,
445 },
446 DropTableClusterKey,
447 ReclusterTable {
448 is_final: bool,
449 selection: Option<Expr>,
450 limit: Option<u64>,
451 },
452 FlashbackTo {
453 point: TimeTravelPoint,
454 },
455 SetOptions {
456 set_options: BTreeMap<String, String>,
457 },
458 UnsetOptions {
459 targets: Vec<Identifier>,
460 },
461 RefreshTableCache,
462 ModifyConnection {
463 new_connection: BTreeMap<String, String>,
464 },
465}
466
467impl Display for AlterTableAction {
468 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
469 match self {
470 AlterTableAction::SetOptions { set_options } => {
471 write!(f, "SET OPTIONS (")?;
472 write_comma_separated_string_map(f, set_options)?;
473 write!(f, ")")?;
474 }
475
476 AlterTableAction::RenameTable { new_table } => {
477 write!(f, "RENAME TO {new_table}")?;
478 }
479 AlterTableAction::ModifyTableComment { new_comment } => {
480 write!(f, "COMMENT={}", QuotedString(new_comment, '\''))?;
481 }
482 AlterTableAction::RenameColumn {
483 old_column,
484 new_column,
485 } => {
486 write!(f, "RENAME COLUMN {old_column} TO {new_column}")?;
487 }
488 AlterTableAction::AddColumn { column, option } => {
489 write!(f, "ADD COLUMN {column}{option}")?;
490 }
491 AlterTableAction::ModifyColumn { action } => {
492 write!(f, "MODIFY COLUMN {action}")?;
493 }
494 AlterTableAction::DropColumn { column } => {
495 write!(f, "DROP COLUMN {column}")?;
496 }
497 AlterTableAction::AlterTableClusterKey { cluster_by } => {
498 write!(f, "{cluster_by}")?;
499 }
500 AlterTableAction::DropTableClusterKey => {
501 write!(f, "DROP CLUSTER KEY")?;
502 }
503 AlterTableAction::ReclusterTable {
504 is_final,
505 selection,
506 limit,
507 } => {
508 write!(f, "RECLUSTER")?;
509 if *is_final {
510 write!(f, " FINAL")?;
511 }
512 if let Some(conditions) = selection {
513 write!(f, " WHERE {conditions}")?;
514 }
515 if let Some(limit) = limit {
516 write!(f, " LIMIT {limit}")?;
517 }
518 }
519 AlterTableAction::FlashbackTo { point } => {
520 write!(f, "FLASHBACK TO {}", point)?;
521 }
522 AlterTableAction::UnsetOptions {
523 targets: unset_targets,
524 } => {
525 write!(f, "UNSET OPTIONS ")?;
526 if unset_targets.len() == 1 {
527 write!(f, "{}", unset_targets[0])?;
528 } else {
529 write!(f, "(")?;
530 write_comma_separated_list(f, unset_targets)?;
531 write!(f, ")")?;
532 }
533 }
534 AlterTableAction::RefreshTableCache => {
535 write!(f, "REFRESH CACHE")?;
536 }
537 AlterTableAction::ModifyConnection { new_connection } => {
538 write!(f, "CONNECTION=(")?;
539 write_space_separated_string_map(f, new_connection)?;
540 write!(f, ")")?;
541 }
542 };
543 Ok(())
544 }
545}
546
547#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
548pub enum AddColumnOption {
549 End,
550 First,
551 After(Identifier),
552}
553
554impl Display for AddColumnOption {
555 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
556 match self {
557 AddColumnOption::First => write!(f, " FIRST"),
558 AddColumnOption::After(ident) => write!(f, " AFTER {ident}"),
559 AddColumnOption::End => Ok(()),
560 }
561 }
562}
563
564#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
565pub struct RenameTableStmt {
566 pub if_exists: bool,
567 pub catalog: Option<Identifier>,
568 pub database: Option<Identifier>,
569 pub table: Identifier,
570 pub new_catalog: Option<Identifier>,
571 pub new_database: Option<Identifier>,
572 pub new_table: Identifier,
573}
574
575impl Display for RenameTableStmt {
576 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
577 write!(f, "RENAME TABLE ")?;
578 if self.if_exists {
579 write!(f, "IF EXISTS ")?;
580 }
581 write_dot_separated_list(
582 f,
583 self.catalog
584 .iter()
585 .chain(&self.database)
586 .chain(Some(&self.table)),
587 )?;
588 write!(f, " TO ")?;
589 write_dot_separated_list(
590 f,
591 self.new_catalog
592 .iter()
593 .chain(&self.new_database)
594 .chain(Some(&self.new_table)),
595 )
596 }
597}
598
599#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
600pub struct TruncateTableStmt {
601 pub catalog: Option<Identifier>,
602 pub database: Option<Identifier>,
603 pub table: Identifier,
604}
605
606impl Display for TruncateTableStmt {
607 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
608 write!(f, "TRUNCATE TABLE ")?;
609 write_dot_separated_list(
610 f,
611 self.catalog
612 .iter()
613 .chain(&self.database)
614 .chain(Some(&self.table)),
615 )?;
616 Ok(())
617 }
618}
619
620#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
621pub struct VacuumTableStmt {
622 pub catalog: Option<Identifier>,
623 pub database: Option<Identifier>,
624 pub table: Identifier,
625 pub option: VacuumTableOption,
626}
627
628impl Display for VacuumTableStmt {
629 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
630 write!(f, "VACUUM TABLE ")?;
631 write_dot_separated_list(
632 f,
633 self.catalog
634 .iter()
635 .chain(&self.database)
636 .chain(Some(&self.table)),
637 )?;
638 write!(f, " {}", &self.option)?;
639
640 Ok(())
641 }
642}
643
644#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
645pub struct VacuumDropTableStmt {
646 pub catalog: Option<Identifier>,
647 pub database: Option<Identifier>,
648 pub option: VacuumDropTableOption,
649}
650
651impl Display for VacuumDropTableStmt {
652 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
653 write!(f, "VACUUM DROP TABLE ")?;
654 if self.catalog.is_some() || self.database.is_some() {
655 write!(f, "FROM ")?;
656 write_dot_separated_list(f, self.catalog.iter().chain(&self.database))?;
657 write!(f, " ")?;
658 }
659 write!(f, "{}", &self.option)?;
660
661 Ok(())
662 }
663}
664
665#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
666pub struct VacuumTemporaryFiles {
667 pub limit: Option<u64>,
668 #[drive(skip)]
669 pub retain: Option<Duration>,
670}
671
672impl Display for crate::ast::VacuumTemporaryFiles {
673 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
674 write!(f, "VACUUM TEMPORARY FILES ")?;
675 if let Some(retain) = &self.retain {
676 let days = Duration::from_secs(60 * 60 * 24);
677 if retain >= &days {
678 let days = retain.as_secs() / (60 * 60 * 24);
679 write!(f, "RETAIN {days} DAYS ")?;
680 } else {
681 let seconds = retain.as_secs();
682 write!(f, "RETAIN {seconds} SECONDS ")?;
683 }
684 }
685
686 if let Some(limit) = &self.limit {
687 write!(f, " LIMIT {limit}")?;
688 }
689
690 Ok(())
691 }
692}
693
694#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
695pub struct OptimizeTableStmt {
696 pub catalog: Option<Identifier>,
697 pub database: Option<Identifier>,
698 pub table: Identifier,
699 pub action: OptimizeTableAction,
700 pub limit: Option<u64>,
701}
702
703impl Display for OptimizeTableStmt {
704 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
705 write!(f, "OPTIMIZE TABLE ")?;
706 write_dot_separated_list(
707 f,
708 self.catalog
709 .iter()
710 .chain(&self.database)
711 .chain(Some(&self.table)),
712 )?;
713 write!(f, " {}", &self.action)?;
714 if let Some(limit) = self.limit {
715 write!(f, " LIMIT {limit}")?;
716 }
717
718 Ok(())
719 }
720}
721
722#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
723pub struct AnalyzeTableStmt {
724 pub catalog: Option<Identifier>,
725 pub database: Option<Identifier>,
726 pub table: Identifier,
727 pub no_scan: bool,
728}
729
730impl Display for AnalyzeTableStmt {
731 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
732 write!(f, "ANALYZE TABLE ")?;
733 write_dot_separated_list(
734 f,
735 self.catalog
736 .iter()
737 .chain(&self.database)
738 .chain(Some(&self.table)),
739 )?;
740 if self.no_scan {
741 write!(f, " NOSCAN")?;
742 }
743
744 Ok(())
745 }
746}
747
748#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
749pub struct ExistsTableStmt {
750 pub catalog: Option<Identifier>,
751 pub database: Option<Identifier>,
752 pub table: Identifier,
753}
754
755impl Display for ExistsTableStmt {
756 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
757 write!(f, "EXISTS TABLE ")?;
758 write_dot_separated_list(
759 f,
760 self.catalog
761 .iter()
762 .chain(&self.database)
763 .chain(Some(&self.table)),
764 )
765 }
766}
767
768#[derive(Debug, Clone, Copy, PartialEq, Eq, Drive, DriveMut)]
769pub enum Engine {
770 Null,
771 Memory,
772 Fuse,
773 View,
774 Random,
775 Iceberg,
776 Delta,
777}
778
779impl Display for Engine {
780 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
781 match self {
782 Engine::Null => write!(f, "NULL"),
783 Engine::Memory => write!(f, "MEMORY"),
784 Engine::Fuse => write!(f, "FUSE"),
785 Engine::View => write!(f, "VIEW"),
786 Engine::Random => write!(f, "RANDOM"),
787 Engine::Iceberg => write!(f, "ICEBERG"),
788 Engine::Delta => write!(f, "DELTA"),
789 }
790 }
791}
792
793impl From<&str> for Engine {
794 fn from(s: &str) -> Self {
795 match s.to_lowercase().as_str() {
796 "null" => Engine::Null,
797 "memory" => Engine::Memory,
798 "fuse" => Engine::Fuse,
799 "view" => Engine::View,
800 "random" => Engine::Random,
801 "iceberg" => Engine::Iceberg,
802 "delta" => Engine::Delta,
803 _ => unreachable!("invalid engine: {}", s),
804 }
805 }
806}
807
808#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
809pub enum CompactTarget {
810 Block,
811 Segment,
812}
813
814#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
815pub struct VacuumTableOption {
816 pub dry_run: Option<bool>,
818}
819
820impl Display for VacuumTableOption {
821 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
822 if let Some(summary) = self.dry_run {
823 write!(f, "DRY RUN")?;
824 if summary {
825 write!(f, " SUMMARY")?;
826 }
827 }
828 Ok(())
829 }
830}
831
832#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
833pub struct VacuumDropTableOption {
834 pub dry_run: Option<bool>,
836 pub limit: Option<usize>,
837}
838
839impl Display for VacuumDropTableOption {
840 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
841 if let Some(summary) = self.dry_run {
842 write!(f, "DRY RUN")?;
843 if summary {
844 write!(f, " SUMMARY")?;
845 }
846 }
847 if let Some(limit) = self.limit {
848 write!(f, " LIMIT {}", limit)?;
849 }
850 Ok(())
851 }
852}
853
854#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
855pub enum OptimizeTableAction {
856 All,
857 Purge { before: Option<TimeTravelPoint> },
858 Compact { target: CompactTarget },
859}
860
861impl Display for OptimizeTableAction {
862 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
863 match self {
864 OptimizeTableAction::All => write!(f, "ALL"),
865 OptimizeTableAction::Purge { before } => {
866 write!(f, "PURGE")?;
867 if let Some(point) = before {
868 write!(f, " BEFORE {}", point)?;
869 }
870 Ok(())
871 }
872 OptimizeTableAction::Compact { target } => {
873 match target {
874 CompactTarget::Block => {
875 write!(f, "COMPACT")?;
876 }
877 CompactTarget::Segment => {
878 write!(f, "COMPACT SEGMENT")?;
879 }
880 }
881 Ok(())
882 }
883 }
884 }
885}
886
887#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
888pub enum ColumnExpr {
889 Default(Box<Expr>),
890 Virtual(Box<Expr>),
891 Stored(Box<Expr>),
892}
893
894impl Display for ColumnExpr {
895 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
896 match self {
897 ColumnExpr::Default(expr) => {
898 write!(f, " DEFAULT {expr}")?;
899 }
900 ColumnExpr::Virtual(expr) => {
901 write!(f, " AS ({expr}) VIRTUAL")?;
902 }
903 ColumnExpr::Stored(expr) => {
904 write!(f, " AS ({expr}) STORED")?;
905 }
906 }
907 Ok(())
908 }
909}
910
911#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
912pub enum NullableConstraint {
913 Null,
914 NotNull,
915}
916
917#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
918pub struct ColumnDefinition {
919 pub name: Identifier,
920 pub data_type: TypeName,
921 pub expr: Option<ColumnExpr>,
922 pub comment: Option<String>,
923}
924
925impl Display for ColumnDefinition {
926 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
927 write!(f, "{} {}", self.name, self.data_type)?;
928 if let Some(expr) = &self.expr {
929 write!(f, "{expr}")?;
930 }
931 if let Some(comment) = &self.comment {
932 write!(f, " COMMENT {}", QuotedString(comment, '\''))?;
933 }
934 Ok(())
935 }
936}
937
938#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
939pub struct TableIndexDefinition {
940 pub index_name: Identifier,
941 pub index_type: TableIndexType,
942 pub columns: Vec<Identifier>,
943 pub sync_creation: bool,
944 pub index_options: BTreeMap<String, String>,
945}
946
947impl Display for TableIndexDefinition {
948 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
949 if !self.sync_creation {
950 write!(f, "ASYNC ")?;
951 }
952 write!(f, "{} INDEX", self.index_type)?;
953 write!(f, " {}", self.index_name)?;
954 write!(f, " (")?;
955 write_comma_separated_list(f, &self.columns)?;
956 write!(f, ")")?;
957
958 if !self.index_options.is_empty() {
959 write!(f, " ")?;
960 write_space_separated_string_map(f, &self.index_options)?;
961 }
962
963 Ok(())
964 }
965}
966
967#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
968pub enum CreateDefinition {
969 Column(ColumnDefinition),
970 TableIndex(TableIndexDefinition),
971}
972
973impl Display for CreateDefinition {
974 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
975 match self {
976 CreateDefinition::Column(column_def) => {
977 write!(f, "{}", column_def)?;
978 }
979 CreateDefinition::TableIndex(table_index_def) => {
980 write!(f, "{}", table_index_def)?;
981 }
982 }
983 Ok(())
984 }
985}
986
987#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
988pub struct ColumnComment {
989 pub name: Identifier,
990 pub comment: String,
991}
992
993impl Display for ColumnComment {
994 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
995 write!(
996 f,
997 "{} COMMENT {}",
998 self.name,
999 QuotedString(&self.comment, '\'')
1000 )?;
1001 Ok(())
1002 }
1003}
1004
1005#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
1006pub enum ModifyColumnAction {
1007 SetMaskingPolicy(Identifier, String),
1009 UnsetMaskingPolicy(Identifier),
1011 SetDataType(Vec<ColumnDefinition>),
1013 ConvertStoredComputedColumn(Identifier),
1015 Comment(Vec<ColumnComment>),
1017}
1018
1019impl Display for ModifyColumnAction {
1020 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
1021 match &self {
1022 ModifyColumnAction::SetMaskingPolicy(column, name) => {
1023 write!(f, "{} SET MASKING POLICY {}", column, name)?
1024 }
1025 ModifyColumnAction::UnsetMaskingPolicy(column) => {
1026 write!(f, "{} UNSET MASKING POLICY", column)?
1027 }
1028 ModifyColumnAction::SetDataType(column_defs) => {
1029 write_comma_separated_list(f, column_defs)?
1030 }
1031 ModifyColumnAction::ConvertStoredComputedColumn(column) => {
1032 write!(f, "{} DROP STORED", column)?
1033 }
1034 ModifyColumnAction::Comment(columns) => write_comma_separated_list(f, columns)?,
1035 }
1036
1037 Ok(())
1038 }
1039}