1#[cfg(not(feature = "std"))]
19use alloc::{
20 boxed::Box,
21 format,
22 string::{String, ToString},
23 vec::Vec,
24};
25
26use core::fmt::{self, Display};
27#[cfg(feature = "serde")]
28use serde::{Deserialize, Serialize};
29#[cfg(feature = "visitor")]
30use sqltk_parser_derive::{Visit, VisitMut};
31
32pub use super::ddl::{ColumnDef, TableConstraint};
33
34use super::{
35 display_comma_separated, display_separated, query::InputFormatClause, Assignment, ClusteredBy,
36 CommentDef, CreateTableOptions, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat,
37 HiveIOFormat, HiveRowFormat, Ident, IndexType, InsertAliases, MysqlInsertPriority, ObjectName,
38 OnCommit, OnInsert, OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem,
39 Setting, SqliteOnConflict, StorageSerializationPolicy, TableObject, TableWithJoins, Tag,
40 WrappedCollection,
41};
42
43#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
47pub struct IndexColumn {
48 pub column: OrderByExpr,
49 pub operator_class: Option<Ident>,
50}
51
52impl Display for IndexColumn {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 write!(f, "{}", self.column)?;
55 if let Some(operator_class) = &self.operator_class {
56 write!(f, " {}", operator_class)?;
57 }
58 Ok(())
59 }
60}
61
62#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
66pub struct CreateIndex {
67 pub name: Option<ObjectName>,
69 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
70 pub table_name: ObjectName,
71 pub using: Option<IndexType>,
72 pub columns: Vec<IndexColumn>,
73 pub unique: bool,
74 pub concurrently: bool,
75 pub if_not_exists: bool,
76 pub include: Vec<Ident>,
77 pub nulls_distinct: Option<bool>,
78 pub with: Vec<Expr>,
80 pub predicate: Option<Expr>,
81}
82
83impl Display for CreateIndex {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 write!(
86 f,
87 "CREATE {unique}INDEX {concurrently}{if_not_exists}",
88 unique = if self.unique { "UNIQUE " } else { "" },
89 concurrently = if self.concurrently {
90 "CONCURRENTLY "
91 } else {
92 ""
93 },
94 if_not_exists = if self.if_not_exists {
95 "IF NOT EXISTS "
96 } else {
97 ""
98 },
99 )?;
100 if let Some(value) = &self.name {
101 write!(f, "{value} ")?;
102 }
103 write!(f, "ON {}", self.table_name)?;
104 if let Some(value) = &self.using {
105 write!(f, " USING {value} ")?;
106 }
107 write!(f, "({})", display_separated(&self.columns, ","))?;
108 if !self.include.is_empty() {
109 write!(f, " INCLUDE ({})", display_separated(&self.include, ","))?;
110 }
111 if let Some(value) = self.nulls_distinct {
112 if value {
113 write!(f, " NULLS DISTINCT")?;
114 } else {
115 write!(f, " NULLS NOT DISTINCT")?;
116 }
117 }
118 if !self.with.is_empty() {
119 write!(f, " WITH ({})", display_comma_separated(&self.with))?;
120 }
121 if let Some(predicate) = &self.predicate {
122 write!(f, " WHERE {predicate}")?;
123 }
124 Ok(())
125 }
126}
127
128#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
130#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
131#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
132pub struct CreateTable {
133 pub or_replace: bool,
134 pub temporary: bool,
135 pub external: bool,
136 pub global: Option<bool>,
137 pub if_not_exists: bool,
138 pub transient: bool,
139 pub volatile: bool,
140 pub iceberg: bool,
141 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
143 pub name: ObjectName,
144 pub columns: Vec<ColumnDef>,
146 pub constraints: Vec<TableConstraint>,
147 pub hive_distribution: HiveDistributionStyle,
148 pub hive_formats: Option<HiveFormat>,
149 pub table_options: CreateTableOptions,
150 pub file_format: Option<FileFormat>,
151 pub location: Option<String>,
152 pub query: Option<Box<Query>>,
153 pub without_rowid: bool,
154 pub like: Option<ObjectName>,
155 pub clone: Option<ObjectName>,
156 pub comment: Option<CommentDef>,
160 pub on_commit: Option<OnCommit>,
161 pub on_cluster: Option<Ident>,
164 pub primary_key: Option<Box<Expr>>,
167 pub order_by: Option<OneOrManyWithParens<Expr>>,
171 pub partition_by: Option<Box<Expr>>,
174 pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
177 pub clustered_by: Option<ClusteredBy>,
180 pub inherits: Option<Vec<ObjectName>>,
185 pub strict: bool,
189 pub copy_grants: bool,
192 pub enable_schema_evolution: Option<bool>,
195 pub change_tracking: Option<bool>,
198 pub data_retention_time_in_days: Option<u64>,
201 pub max_data_extension_time_in_days: Option<u64>,
204 pub default_ddl_collation: Option<String>,
207 pub with_aggregation_policy: Option<ObjectName>,
210 pub with_row_access_policy: Option<RowAccessPolicy>,
213 pub with_tags: Option<Vec<Tag>>,
216 pub external_volume: Option<String>,
219 pub base_location: Option<String>,
222 pub catalog: Option<String>,
225 pub catalog_sync: Option<String>,
228 pub storage_serialization_policy: Option<StorageSerializationPolicy>,
231}
232
233impl Display for CreateTable {
234 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
235 write!(
243 f,
244 "CREATE {or_replace}{external}{global}{temporary}{transient}{volatile}{iceberg}TABLE {if_not_exists}{name}",
245 or_replace = if self.or_replace { "OR REPLACE " } else { "" },
246 external = if self.external { "EXTERNAL " } else { "" },
247 global = self.global
248 .map(|global| {
249 if global {
250 "GLOBAL "
251 } else {
252 "LOCAL "
253 }
254 })
255 .unwrap_or(""),
256 if_not_exists = if self.if_not_exists { "IF NOT EXISTS " } else { "" },
257 temporary = if self.temporary { "TEMPORARY " } else { "" },
258 transient = if self.transient { "TRANSIENT " } else { "" },
259 volatile = if self.volatile { "VOLATILE " } else { "" },
260 iceberg = if self.iceberg { "ICEBERG " } else { "" },
262 name = self.name,
263 )?;
264 if let Some(on_cluster) = &self.on_cluster {
265 write!(f, " ON CLUSTER {}", on_cluster)?;
266 }
267 if !self.columns.is_empty() || !self.constraints.is_empty() {
268 write!(f, " ({}", display_comma_separated(&self.columns))?;
269 if !self.columns.is_empty() && !self.constraints.is_empty() {
270 write!(f, ", ")?;
271 }
272 write!(f, "{})", display_comma_separated(&self.constraints))?;
273 } else if self.query.is_none() && self.like.is_none() && self.clone.is_none() {
274 write!(f, " ()")?;
276 }
277
278 if let Some(comment) = &self.comment {
281 write!(f, " COMMENT '{comment}'")?;
282 }
283
284 if self.without_rowid {
286 write!(f, " WITHOUT ROWID")?;
287 }
288
289 if let Some(l) = &self.like {
291 write!(f, " LIKE {l}")?;
292 }
293
294 if let Some(c) = &self.clone {
295 write!(f, " CLONE {c}")?;
296 }
297
298 match &self.hive_distribution {
299 HiveDistributionStyle::PARTITIONED { columns } => {
300 write!(f, " PARTITIONED BY ({})", display_comma_separated(columns))?;
301 }
302 HiveDistributionStyle::SKEWED {
303 columns,
304 on,
305 stored_as_directories,
306 } => {
307 write!(
308 f,
309 " SKEWED BY ({})) ON ({})",
310 display_comma_separated(columns),
311 display_comma_separated(on)
312 )?;
313 if *stored_as_directories {
314 write!(f, " STORED AS DIRECTORIES")?;
315 }
316 }
317 _ => (),
318 }
319
320 if let Some(clustered_by) = &self.clustered_by {
321 write!(f, " {clustered_by}")?;
322 }
323
324 if let Some(HiveFormat {
325 row_format,
326 serde_properties,
327 storage,
328 location,
329 }) = &self.hive_formats
330 {
331 match row_format {
332 Some(HiveRowFormat::SERDE { class }) => write!(f, " ROW FORMAT SERDE '{class}'")?,
333 Some(HiveRowFormat::DELIMITED { delimiters }) => {
334 write!(f, " ROW FORMAT DELIMITED")?;
335 if !delimiters.is_empty() {
336 write!(f, " {}", display_separated(delimiters, " "))?;
337 }
338 }
339 None => (),
340 }
341 match storage {
342 Some(HiveIOFormat::IOF {
343 input_format,
344 output_format,
345 }) => write!(
346 f,
347 " STORED AS INPUTFORMAT {input_format} OUTPUTFORMAT {output_format}"
348 )?,
349 Some(HiveIOFormat::FileFormat { format }) if !self.external => {
350 write!(f, " STORED AS {format}")?
351 }
352 _ => (),
353 }
354 if let Some(serde_properties) = serde_properties.as_ref() {
355 write!(
356 f,
357 " WITH SERDEPROPERTIES ({})",
358 display_comma_separated(serde_properties)
359 )?;
360 }
361 if !self.external {
362 if let Some(loc) = location {
363 write!(f, " LOCATION '{loc}'")?;
364 }
365 }
366 }
367 if self.external {
368 if let Some(file_format) = self.file_format {
369 write!(f, " STORED AS {file_format}")?;
370 }
371 write!(f, " LOCATION '{}'", self.location.as_ref().unwrap())?;
372 }
373
374 match &self.table_options {
375 options @ CreateTableOptions::With(_)
376 | options @ CreateTableOptions::Plain(_)
377 | options @ CreateTableOptions::TableProperties(_) => write!(f, " {}", options)?,
378 _ => (),
379 }
380
381 if let Some(primary_key) = &self.primary_key {
382 write!(f, " PRIMARY KEY {}", primary_key)?;
383 }
384 if let Some(order_by) = &self.order_by {
385 write!(f, " ORDER BY {}", order_by)?;
386 }
387 if let Some(inherits) = &self.inherits {
388 write!(f, " INHERITS ({})", display_comma_separated(inherits))?;
389 }
390 if let Some(partition_by) = self.partition_by.as_ref() {
391 write!(f, " PARTITION BY {partition_by}")?;
392 }
393 if let Some(cluster_by) = self.cluster_by.as_ref() {
394 write!(f, " CLUSTER BY {cluster_by}")?;
395 }
396 if let options @ CreateTableOptions::Options(_) = &self.table_options {
397 write!(f, " {}", options)?;
398 }
399 if let Some(external_volume) = self.external_volume.as_ref() {
400 write!(f, " EXTERNAL_VOLUME = '{external_volume}'")?;
401 }
402
403 if let Some(catalog) = self.catalog.as_ref() {
404 write!(f, " CATALOG = '{catalog}'")?;
405 }
406
407 if self.iceberg {
408 if let Some(base_location) = self.base_location.as_ref() {
409 write!(f, " BASE_LOCATION = '{base_location}'")?;
410 }
411 }
412
413 if let Some(catalog_sync) = self.catalog_sync.as_ref() {
414 write!(f, " CATALOG_SYNC = '{catalog_sync}'")?;
415 }
416
417 if let Some(storage_serialization_policy) = self.storage_serialization_policy.as_ref() {
418 write!(
419 f,
420 " STORAGE_SERIALIZATION_POLICY = {storage_serialization_policy}"
421 )?;
422 }
423
424 if self.copy_grants {
425 write!(f, " COPY GRANTS")?;
426 }
427
428 if let Some(is_enabled) = self.enable_schema_evolution {
429 write!(
430 f,
431 " ENABLE_SCHEMA_EVOLUTION={}",
432 if is_enabled { "TRUE" } else { "FALSE" }
433 )?;
434 }
435
436 if let Some(is_enabled) = self.change_tracking {
437 write!(
438 f,
439 " CHANGE_TRACKING={}",
440 if is_enabled { "TRUE" } else { "FALSE" }
441 )?;
442 }
443
444 if let Some(data_retention_time_in_days) = self.data_retention_time_in_days {
445 write!(
446 f,
447 " DATA_RETENTION_TIME_IN_DAYS={data_retention_time_in_days}",
448 )?;
449 }
450
451 if let Some(max_data_extension_time_in_days) = self.max_data_extension_time_in_days {
452 write!(
453 f,
454 " MAX_DATA_EXTENSION_TIME_IN_DAYS={max_data_extension_time_in_days}",
455 )?;
456 }
457
458 if let Some(default_ddl_collation) = &self.default_ddl_collation {
459 write!(f, " DEFAULT_DDL_COLLATION='{default_ddl_collation}'",)?;
460 }
461
462 if let Some(with_aggregation_policy) = &self.with_aggregation_policy {
463 write!(f, " WITH AGGREGATION POLICY {with_aggregation_policy}",)?;
464 }
465
466 if let Some(row_access_policy) = &self.with_row_access_policy {
467 write!(f, " {row_access_policy}",)?;
468 }
469
470 if let Some(tag) = &self.with_tags {
471 write!(f, " WITH TAG ({})", display_comma_separated(tag.as_slice()))?;
472 }
473
474 if self.on_commit.is_some() {
475 let on_commit = match self.on_commit {
476 Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
477 Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
478 Some(OnCommit::Drop) => "ON COMMIT DROP",
479 None => "",
480 };
481 write!(f, " {on_commit}")?;
482 }
483 if self.strict {
484 write!(f, " STRICT")?;
485 }
486 if let Some(query) = &self.query {
487 write!(f, " AS {query}")?;
488 }
489 Ok(())
490 }
491}
492
493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
495#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
496#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
497pub struct Insert {
498 pub or: Option<SqliteOnConflict>,
500 pub ignore: bool,
502 pub into: bool,
504 pub table: TableObject,
506 pub table_alias: Option<Ident>,
508 pub columns: Vec<Ident>,
510 pub overwrite: bool,
512 pub source: Option<Box<Query>>,
514 pub assignments: Vec<Assignment>,
517 pub partitioned: Option<Vec<Expr>>,
519 pub after_columns: Vec<Ident>,
521 pub has_table_keyword: bool,
523 pub on: Option<OnInsert>,
524 pub returning: Option<Vec<SelectItem>>,
526 pub replace_into: bool,
528 pub priority: Option<MysqlInsertPriority>,
530 pub insert_alias: Option<InsertAliases>,
532 pub settings: Option<Vec<Setting>>,
538 pub format_clause: Option<InputFormatClause>,
545}
546
547impl Display for Insert {
548 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549 let table_name = if let Some(alias) = &self.table_alias {
550 format!("{0} AS {alias}", self.table)
551 } else {
552 self.table.to_string()
553 };
554
555 if let Some(on_conflict) = self.or {
556 write!(f, "INSERT {on_conflict} INTO {table_name} ")?;
557 } else {
558 write!(
559 f,
560 "{start}",
561 start = if self.replace_into {
562 "REPLACE"
563 } else {
564 "INSERT"
565 },
566 )?;
567 if let Some(priority) = self.priority {
568 write!(f, " {priority}",)?;
569 }
570
571 write!(
572 f,
573 "{ignore}{over}{int}{tbl} {table_name} ",
574 table_name = table_name,
575 ignore = if self.ignore { " IGNORE" } else { "" },
576 over = if self.overwrite { " OVERWRITE" } else { "" },
577 int = if self.into { " INTO" } else { "" },
578 tbl = if self.has_table_keyword { " TABLE" } else { "" },
579 )?;
580 }
581 if !self.columns.is_empty() {
582 write!(f, "({}) ", display_comma_separated(&self.columns))?;
583 }
584 if let Some(ref parts) = self.partitioned {
585 if !parts.is_empty() {
586 write!(f, "PARTITION ({}) ", display_comma_separated(parts))?;
587 }
588 }
589 if !self.after_columns.is_empty() {
590 write!(f, "({}) ", display_comma_separated(&self.after_columns))?;
591 }
592
593 if let Some(settings) = &self.settings {
594 write!(f, "SETTINGS {} ", display_comma_separated(settings))?;
595 }
596
597 if let Some(source) = &self.source {
598 write!(f, "{source}")?;
599 } else if !self.assignments.is_empty() {
600 write!(f, "SET ")?;
601 write!(f, "{}", display_comma_separated(&self.assignments))?;
602 } else if let Some(format_clause) = &self.format_clause {
603 write!(f, "{format_clause}")?;
604 } else if self.columns.is_empty() {
605 write!(f, "DEFAULT VALUES")?;
606 }
607
608 if let Some(insert_alias) = &self.insert_alias {
609 write!(f, " AS {0}", insert_alias.row_alias)?;
610
611 if let Some(col_aliases) = &insert_alias.col_aliases {
612 if !col_aliases.is_empty() {
613 write!(f, " ({})", display_comma_separated(col_aliases))?;
614 }
615 }
616 }
617
618 if let Some(on) = &self.on {
619 write!(f, "{on}")?;
620 }
621
622 if let Some(returning) = &self.returning {
623 write!(f, " RETURNING {}", display_comma_separated(returning))?;
624 }
625 Ok(())
626 }
627}
628
629#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
633pub struct Delete {
634 pub tables: Vec<ObjectName>,
636 pub from: FromTable,
638 pub using: Option<Vec<TableWithJoins>>,
640 pub selection: Option<Expr>,
642 pub returning: Option<Vec<SelectItem>>,
644 pub order_by: Vec<OrderByExpr>,
646 pub limit: Option<Expr>,
648}
649
650impl Display for Delete {
651 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
652 write!(f, "DELETE ")?;
653 if !self.tables.is_empty() {
654 write!(f, "{} ", display_comma_separated(&self.tables))?;
655 }
656 match &self.from {
657 FromTable::WithFromKeyword(from) => {
658 write!(f, "FROM {}", display_comma_separated(from))?;
659 }
660 FromTable::WithoutKeyword(from) => {
661 write!(f, "{}", display_comma_separated(from))?;
662 }
663 }
664 if let Some(using) = &self.using {
665 write!(f, " USING {}", display_comma_separated(using))?;
666 }
667 if let Some(selection) = &self.selection {
668 write!(f, " WHERE {selection}")?;
669 }
670 if let Some(returning) = &self.returning {
671 write!(f, " RETURNING {}", display_comma_separated(returning))?;
672 }
673 if !self.order_by.is_empty() {
674 write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
675 }
676 if let Some(limit) = &self.limit {
677 write!(f, " LIMIT {limit}")?;
678 }
679 Ok(())
680 }
681}