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 sqlparser_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, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat,
37 HiveRowFormat, Ident, InsertAliases, MysqlInsertPriority, ObjectName, OnCommit, OnInsert,
38 OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem, Setting, SqlOption,
39 SqliteOnConflict, StorageSerializationPolicy, TableEngine, 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 CreateIndex {
48 pub name: Option<ObjectName>,
50 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
51 pub table_name: ObjectName,
52 pub using: Option<Ident>,
53 pub columns: Vec<OrderByExpr>,
54 pub unique: bool,
55 pub concurrently: bool,
56 pub if_not_exists: bool,
57 pub include: Vec<Ident>,
58 pub nulls_distinct: Option<bool>,
59 pub with: Vec<Expr>,
61 pub predicate: Option<Expr>,
62}
63
64impl Display for CreateIndex {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 write!(
67 f,
68 "CREATE {unique}INDEX {concurrently}{if_not_exists}",
69 unique = if self.unique { "UNIQUE " } else { "" },
70 concurrently = if self.concurrently {
71 "CONCURRENTLY "
72 } else {
73 ""
74 },
75 if_not_exists = if self.if_not_exists {
76 "IF NOT EXISTS "
77 } else {
78 ""
79 },
80 )?;
81 if let Some(value) = &self.name {
82 write!(f, "{value} ")?;
83 }
84 write!(f, "ON {}", self.table_name)?;
85 if let Some(value) = &self.using {
86 write!(f, " USING {value} ")?;
87 }
88 write!(f, "({})", display_separated(&self.columns, ","))?;
89 if !self.include.is_empty() {
90 write!(f, " INCLUDE ({})", display_separated(&self.include, ","))?;
91 }
92 if let Some(value) = self.nulls_distinct {
93 if value {
94 write!(f, " NULLS DISTINCT")?;
95 } else {
96 write!(f, " NULLS NOT DISTINCT")?;
97 }
98 }
99 if !self.with.is_empty() {
100 write!(f, " WITH ({})", display_comma_separated(&self.with))?;
101 }
102 if let Some(predicate) = &self.predicate {
103 write!(f, " WHERE {predicate}")?;
104 }
105 Ok(())
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
112#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
113pub struct CreateTable {
114 pub or_replace: bool,
115 pub temporary: bool,
116 pub external: bool,
117 pub global: Option<bool>,
118 pub if_not_exists: bool,
119 pub transient: bool,
120 pub volatile: bool,
121 pub iceberg: bool,
122 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
124 pub name: ObjectName,
125 pub columns: Vec<ColumnDef>,
127 pub constraints: Vec<TableConstraint>,
128 pub hive_distribution: HiveDistributionStyle,
129 pub hive_formats: Option<HiveFormat>,
130 pub table_properties: Vec<SqlOption>,
131 pub with_options: Vec<SqlOption>,
132 pub file_format: Option<FileFormat>,
133 pub location: Option<String>,
134 pub query: Option<Box<Query>>,
135 pub without_rowid: bool,
136 pub like: Option<ObjectName>,
137 pub clone: Option<ObjectName>,
138 pub engine: Option<TableEngine>,
139 pub comment: Option<CommentDef>,
140 pub auto_increment_offset: Option<u32>,
141 pub default_charset: Option<String>,
142 pub collation: Option<String>,
143 pub on_commit: Option<OnCommit>,
144 pub on_cluster: Option<Ident>,
147 pub primary_key: Option<Box<Expr>>,
150 pub order_by: Option<OneOrManyWithParens<Expr>>,
154 pub partition_by: Option<Box<Expr>>,
157 pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
160 pub clustered_by: Option<ClusteredBy>,
163 pub options: Option<Vec<SqlOption>>,
166 pub strict: bool,
170 pub copy_grants: bool,
173 pub enable_schema_evolution: Option<bool>,
176 pub change_tracking: Option<bool>,
179 pub data_retention_time_in_days: Option<u64>,
182 pub max_data_extension_time_in_days: Option<u64>,
185 pub default_ddl_collation: Option<String>,
188 pub with_aggregation_policy: Option<ObjectName>,
191 pub with_row_access_policy: Option<RowAccessPolicy>,
194 pub with_tags: Option<Vec<Tag>>,
197 pub external_volume: Option<String>,
200 pub base_location: Option<String>,
203 pub catalog: Option<String>,
206 pub catalog_sync: Option<String>,
209 pub storage_serialization_policy: Option<StorageSerializationPolicy>,
212}
213
214impl Display for CreateTable {
215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216 write!(
224 f,
225 "CREATE {or_replace}{external}{global}{temporary}{transient}{volatile}{iceberg}TABLE {if_not_exists}{name}",
226 or_replace = if self.or_replace { "OR REPLACE " } else { "" },
227 external = if self.external { "EXTERNAL " } else { "" },
228 global = self.global
229 .map(|global| {
230 if global {
231 "GLOBAL "
232 } else {
233 "LOCAL "
234 }
235 })
236 .unwrap_or(""),
237 if_not_exists = if self.if_not_exists { "IF NOT EXISTS " } else { "" },
238 temporary = if self.temporary { "TEMPORARY " } else { "" },
239 transient = if self.transient { "TRANSIENT " } else { "" },
240 volatile = if self.volatile { "VOLATILE " } else { "" },
241 iceberg = if self.iceberg { "ICEBERG " } else { "" },
243 name = self.name,
244 )?;
245 if let Some(on_cluster) = &self.on_cluster {
246 write!(f, " ON CLUSTER {}", on_cluster)?;
247 }
248 if !self.columns.is_empty() || !self.constraints.is_empty() {
249 write!(f, " ({}", display_comma_separated(&self.columns))?;
250 if !self.columns.is_empty() && !self.constraints.is_empty() {
251 write!(f, ", ")?;
252 }
253 write!(f, "{})", display_comma_separated(&self.constraints))?;
254 } else if self.query.is_none() && self.like.is_none() && self.clone.is_none() {
255 write!(f, " ()")?;
257 }
258
259 if let Some(CommentDef::AfterColumnDefsWithoutEq(comment)) = &self.comment {
262 write!(f, " COMMENT '{comment}'")?;
263 }
264
265 if self.without_rowid {
267 write!(f, " WITHOUT ROWID")?;
268 }
269
270 if let Some(l) = &self.like {
272 write!(f, " LIKE {l}")?;
273 }
274
275 if let Some(c) = &self.clone {
276 write!(f, " CLONE {c}")?;
277 }
278
279 match &self.hive_distribution {
280 HiveDistributionStyle::PARTITIONED { columns } => {
281 write!(f, " PARTITIONED BY ({})", display_comma_separated(columns))?;
282 }
283 HiveDistributionStyle::SKEWED {
284 columns,
285 on,
286 stored_as_directories,
287 } => {
288 write!(
289 f,
290 " SKEWED BY ({})) ON ({})",
291 display_comma_separated(columns),
292 display_comma_separated(on)
293 )?;
294 if *stored_as_directories {
295 write!(f, " STORED AS DIRECTORIES")?;
296 }
297 }
298 _ => (),
299 }
300
301 if let Some(clustered_by) = &self.clustered_by {
302 write!(f, " {clustered_by}")?;
303 }
304
305 if let Some(HiveFormat {
306 row_format,
307 serde_properties,
308 storage,
309 location,
310 }) = &self.hive_formats
311 {
312 match row_format {
313 Some(HiveRowFormat::SERDE { class }) => write!(f, " ROW FORMAT SERDE '{class}'")?,
314 Some(HiveRowFormat::DELIMITED { delimiters }) => {
315 write!(f, " ROW FORMAT DELIMITED")?;
316 if !delimiters.is_empty() {
317 write!(f, " {}", display_separated(delimiters, " "))?;
318 }
319 }
320 None => (),
321 }
322 match storage {
323 Some(HiveIOFormat::IOF {
324 input_format,
325 output_format,
326 }) => write!(
327 f,
328 " STORED AS INPUTFORMAT {input_format} OUTPUTFORMAT {output_format}"
329 )?,
330 Some(HiveIOFormat::FileFormat { format }) if !self.external => {
331 write!(f, " STORED AS {format}")?
332 }
333 _ => (),
334 }
335 if let Some(serde_properties) = serde_properties.as_ref() {
336 write!(
337 f,
338 " WITH SERDEPROPERTIES ({})",
339 display_comma_separated(serde_properties)
340 )?;
341 }
342 if !self.external {
343 if let Some(loc) = location {
344 write!(f, " LOCATION '{loc}'")?;
345 }
346 }
347 }
348 if self.external {
349 if let Some(file_format) = self.file_format {
350 write!(f, " STORED AS {file_format}")?;
351 }
352 write!(f, " LOCATION '{}'", self.location.as_ref().unwrap())?;
353 }
354 if !self.table_properties.is_empty() {
355 write!(
356 f,
357 " TBLPROPERTIES ({})",
358 display_comma_separated(&self.table_properties)
359 )?;
360 }
361 if !self.with_options.is_empty() {
362 write!(f, " WITH ({})", display_comma_separated(&self.with_options))?;
363 }
364 if let Some(engine) = &self.engine {
365 write!(f, " ENGINE={engine}")?;
366 }
367 if let Some(comment_def) = &self.comment {
368 match comment_def {
369 CommentDef::WithEq(comment) => {
370 write!(f, " COMMENT = '{comment}'")?;
371 }
372 CommentDef::WithoutEq(comment) => {
373 write!(f, " COMMENT '{comment}'")?;
374 }
375 CommentDef::AfterColumnDefsWithoutEq(_) => (),
377 }
378 }
379
380 if let Some(auto_increment_offset) = self.auto_increment_offset {
381 write!(f, " AUTO_INCREMENT {auto_increment_offset}")?;
382 }
383 if let Some(primary_key) = &self.primary_key {
384 write!(f, " PRIMARY KEY {}", primary_key)?;
385 }
386 if let Some(order_by) = &self.order_by {
387 write!(f, " ORDER BY {}", order_by)?;
388 }
389 if let Some(partition_by) = self.partition_by.as_ref() {
390 write!(f, " PARTITION BY {partition_by}")?;
391 }
392 if let Some(cluster_by) = self.cluster_by.as_ref() {
393 write!(f, " CLUSTER BY {cluster_by}")?;
394 }
395
396 if let Some(options) = self.options.as_ref() {
397 write!(
398 f,
399 " OPTIONS({})",
400 display_comma_separated(options.as_slice())
401 )?;
402 }
403
404 if let Some(external_volume) = self.external_volume.as_ref() {
405 write!(f, " EXTERNAL_VOLUME = '{external_volume}'")?;
406 }
407
408 if let Some(catalog) = self.catalog.as_ref() {
409 write!(f, " CATALOG = '{catalog}'")?;
410 }
411
412 if self.iceberg {
413 if let Some(base_location) = self.base_location.as_ref() {
414 write!(f, " BASE_LOCATION = '{base_location}'")?;
415 }
416 }
417
418 if let Some(catalog_sync) = self.catalog_sync.as_ref() {
419 write!(f, " CATALOG_SYNC = '{catalog_sync}'")?;
420 }
421
422 if let Some(storage_serialization_policy) = self.storage_serialization_policy.as_ref() {
423 write!(
424 f,
425 " STORAGE_SERIALIZATION_POLICY = {storage_serialization_policy}"
426 )?;
427 }
428
429 if self.copy_grants {
430 write!(f, " COPY GRANTS")?;
431 }
432
433 if let Some(is_enabled) = self.enable_schema_evolution {
434 write!(
435 f,
436 " ENABLE_SCHEMA_EVOLUTION={}",
437 if is_enabled { "TRUE" } else { "FALSE" }
438 )?;
439 }
440
441 if let Some(is_enabled) = self.change_tracking {
442 write!(
443 f,
444 " CHANGE_TRACKING={}",
445 if is_enabled { "TRUE" } else { "FALSE" }
446 )?;
447 }
448
449 if let Some(data_retention_time_in_days) = self.data_retention_time_in_days {
450 write!(
451 f,
452 " DATA_RETENTION_TIME_IN_DAYS={data_retention_time_in_days}",
453 )?;
454 }
455
456 if let Some(max_data_extension_time_in_days) = self.max_data_extension_time_in_days {
457 write!(
458 f,
459 " MAX_DATA_EXTENSION_TIME_IN_DAYS={max_data_extension_time_in_days}",
460 )?;
461 }
462
463 if let Some(default_ddl_collation) = &self.default_ddl_collation {
464 write!(f, " DEFAULT_DDL_COLLATION='{default_ddl_collation}'",)?;
465 }
466
467 if let Some(with_aggregation_policy) = &self.with_aggregation_policy {
468 write!(f, " WITH AGGREGATION POLICY {with_aggregation_policy}",)?;
469 }
470
471 if let Some(row_access_policy) = &self.with_row_access_policy {
472 write!(f, " {row_access_policy}",)?;
473 }
474
475 if let Some(tag) = &self.with_tags {
476 write!(f, " WITH TAG ({})", display_comma_separated(tag.as_slice()))?;
477 }
478
479 if let Some(default_charset) = &self.default_charset {
480 write!(f, " DEFAULT CHARSET={default_charset}")?;
481 }
482 if let Some(collation) = &self.collation {
483 write!(f, " COLLATE={collation}")?;
484 }
485
486 if self.on_commit.is_some() {
487 let on_commit = match self.on_commit {
488 Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
489 Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
490 Some(OnCommit::Drop) => "ON COMMIT DROP",
491 None => "",
492 };
493 write!(f, " {on_commit}")?;
494 }
495 if self.strict {
496 write!(f, " STRICT")?;
497 }
498 if let Some(query) = &self.query {
499 write!(f, " AS {query}")?;
500 }
501 Ok(())
502 }
503}
504
505#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
507#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
508#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
509pub struct Insert {
510 pub or: Option<SqliteOnConflict>,
512 pub ignore: bool,
514 pub into: bool,
516 pub table: TableObject,
518 pub table_alias: Option<Ident>,
520 pub columns: Vec<Ident>,
522 pub overwrite: bool,
524 pub source: Option<Box<Query>>,
526 pub assignments: Vec<Assignment>,
529 pub partitioned: Option<Vec<Expr>>,
531 pub after_columns: Vec<Ident>,
533 pub has_table_keyword: bool,
535 pub on: Option<OnInsert>,
536 pub returning: Option<Vec<SelectItem>>,
538 pub replace_into: bool,
540 pub priority: Option<MysqlInsertPriority>,
542 pub insert_alias: Option<InsertAliases>,
544 pub settings: Option<Vec<Setting>>,
550 pub format_clause: Option<InputFormatClause>,
557}
558
559impl Display for Insert {
560 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561 let table_name = if let Some(alias) = &self.table_alias {
562 format!("{0} AS {alias}", self.table)
563 } else {
564 self.table.to_string()
565 };
566
567 if let Some(on_conflict) = self.or {
568 write!(f, "INSERT {on_conflict} INTO {table_name} ")?;
569 } else {
570 write!(
571 f,
572 "{start}",
573 start = if self.replace_into {
574 "REPLACE"
575 } else {
576 "INSERT"
577 },
578 )?;
579 if let Some(priority) = self.priority {
580 write!(f, " {priority}",)?;
581 }
582
583 write!(
584 f,
585 "{ignore}{over}{int}{tbl} {table_name} ",
586 table_name = table_name,
587 ignore = if self.ignore { " IGNORE" } else { "" },
588 over = if self.overwrite { " OVERWRITE" } else { "" },
589 int = if self.into { " INTO" } else { "" },
590 tbl = if self.has_table_keyword { " TABLE" } else { "" },
591 )?;
592 }
593 if !self.columns.is_empty() {
594 write!(f, "({}) ", display_comma_separated(&self.columns))?;
595 }
596 if let Some(ref parts) = self.partitioned {
597 if !parts.is_empty() {
598 write!(f, "PARTITION ({}) ", display_comma_separated(parts))?;
599 }
600 }
601 if !self.after_columns.is_empty() {
602 write!(f, "({}) ", display_comma_separated(&self.after_columns))?;
603 }
604
605 if let Some(settings) = &self.settings {
606 write!(f, "SETTINGS {} ", display_comma_separated(settings))?;
607 }
608
609 if let Some(source) = &self.source {
610 write!(f, "{source}")?;
611 } else if !self.assignments.is_empty() {
612 write!(f, "SET ")?;
613 write!(f, "{}", display_comma_separated(&self.assignments))?;
614 } else if let Some(format_clause) = &self.format_clause {
615 write!(f, "{format_clause}")?;
616 } else if self.columns.is_empty() {
617 write!(f, "DEFAULT VALUES")?;
618 }
619
620 if let Some(insert_alias) = &self.insert_alias {
621 write!(f, " AS {0}", insert_alias.row_alias)?;
622
623 if let Some(col_aliases) = &insert_alias.col_aliases {
624 if !col_aliases.is_empty() {
625 write!(f, " ({})", display_comma_separated(col_aliases))?;
626 }
627 }
628 }
629
630 if let Some(on) = &self.on {
631 write!(f, "{on}")?;
632 }
633
634 if let Some(returning) = &self.returning {
635 write!(f, " RETURNING {}", display_comma_separated(returning))?;
636 }
637 Ok(())
638 }
639}
640
641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
644#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
645pub struct Delete {
646 pub tables: Vec<ObjectName>,
648 pub from: FromTable,
650 pub using: Option<Vec<TableWithJoins>>,
652 pub selection: Option<Expr>,
654 pub returning: Option<Vec<SelectItem>>,
656 pub order_by: Vec<OrderByExpr>,
658 pub limit: Option<Expr>,
660}
661
662impl Display for Delete {
663 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664 write!(f, "DELETE ")?;
665 if !self.tables.is_empty() {
666 write!(f, "{} ", display_comma_separated(&self.tables))?;
667 }
668 match &self.from {
669 FromTable::WithFromKeyword(from) => {
670 write!(f, "FROM {}", display_comma_separated(from))?;
671 }
672 FromTable::WithoutKeyword(from) => {
673 write!(f, "{}", display_comma_separated(from))?;
674 }
675 }
676 if let Some(using) = &self.using {
677 write!(f, " USING {}", display_comma_separated(using))?;
678 }
679 if let Some(selection) = &self.selection {
680 write!(f, " WHERE {selection}")?;
681 }
682 if let Some(returning) = &self.returning {
683 write!(f, " RETURNING {}", display_comma_separated(returning))?;
684 }
685 if !self.order_by.is_empty() {
686 write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
687 }
688 if let Some(limit) = &self.limit {
689 write!(f, " LIMIT {limit}")?;
690 }
691 Ok(())
692 }
693}