1#[cfg(not(feature = "std"))]
2use alloc::{boxed::Box, vec::Vec};
3
4use core::fmt::{self, Display};
5
6use crate::{RelNamed, SelectInto, TableAlias, Values};
7
8use super::display_utils::{Indent, SpaceOrNewline, indented_list};
9use super::{Expr, Ident, ObjectName, OrderByExpr, Query, SelectItem, display_comma_separated};
10
11#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
13pub struct Insert {
14 pub table: ObjectName,
16 pub columns: Vec<Ident>,
18 pub source: Box<Query>,
20}
21
22impl Display for Insert {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 write!(f, "INSERT INTO {} ", self.table)?;
25
26 if !self.columns.is_empty() {
27 write!(f, "({})", display_comma_separated(&self.columns))?;
28 SpaceOrNewline.fmt(f)?;
29 }
30 self.source.fmt(f)?;
31 Ok(())
32 }
33}
34
35#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
37pub struct Delete {
38 pub tables: Vec<ObjectName>,
40 pub from: FromTable,
42 pub using: Option<Vec<RelNamed>>,
44 pub selection: Option<Expr>,
46 pub returning: Option<Vec<SelectItem>>,
48 pub order_by: Vec<OrderByExpr>,
50 pub limit: Option<Expr>,
52}
53
54impl Display for Delete {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.write_str("DELETE")?;
57 if !self.tables.is_empty() {
58 indented_list(f, &self.tables)?;
59 }
60 match &self.from {
61 FromTable::WithFromKeyword(from) => {
62 f.write_str(" FROM")?;
63 indented_list(f, from)?;
64 }
65 FromTable::WithoutKeyword(from) => {
66 indented_list(f, from)?;
67 }
68 }
69 if let Some(using) = &self.using {
70 SpaceOrNewline.fmt(f)?;
71 f.write_str("USING")?;
72 indented_list(f, using)?;
73 }
74 if let Some(selection) = &self.selection {
75 SpaceOrNewline.fmt(f)?;
76 f.write_str("WHERE")?;
77 SpaceOrNewline.fmt(f)?;
78 Indent(selection).fmt(f)?;
79 }
80 if let Some(returning) = &self.returning {
81 SpaceOrNewline.fmt(f)?;
82 f.write_str("RETURNING")?;
83 indented_list(f, returning)?;
84 }
85 if !self.order_by.is_empty() {
86 SpaceOrNewline.fmt(f)?;
87 f.write_str("ORDER BY")?;
88 indented_list(f, &self.order_by)?;
89 }
90 if let Some(limit) = &self.limit {
91 SpaceOrNewline.fmt(f)?;
92 f.write_str("LIMIT")?;
93 SpaceOrNewline.fmt(f)?;
94 Indent(limit).fmt(f)?;
95 }
96 Ok(())
97 }
98}
99#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
106pub enum FromTable {
107 WithFromKeyword(Vec<RelNamed>),
109 WithoutKeyword(Vec<RelNamed>),
112}
113impl Display for FromTable {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 match self {
116 FromTable::WithFromKeyword(tables) => {
117 write!(f, "FROM {}", display_comma_separated(tables))
118 }
119 FromTable::WithoutKeyword(tables) => {
120 write!(f, "{}", display_comma_separated(tables))
121 }
122 }
123 }
124}
125
126#[allow(clippy::large_enum_variant)]
127#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
128pub struct Update {
129 pub table: ObjectName,
131 pub alias: Option<TableAlias>,
133 pub assignments: Vec<Assignment>,
135 pub from: Vec<RelNamed>,
137 pub selection: Option<Expr>,
139 pub returning: Option<Vec<SelectItem>>,
141 pub limit: Option<Expr>,
143}
144
145impl fmt::Display for Update {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 f.write_str("UPDATE ")?;
148 self.table.fmt(f)?;
149 if let Some(alias) = &self.alias {
150 f.write_str(" AS ")?;
151 alias.fmt(f)?;
152 }
153 if !self.assignments.is_empty() {
154 SpaceOrNewline.fmt(f)?;
155 f.write_str("SET")?;
156 indented_list(f, &self.assignments)?;
157 }
158 if !self.from.is_empty() {
159 SpaceOrNewline.fmt(f)?;
160 f.write_str("FROM")?;
161 indented_list(f, &self.from)?;
162 }
163 if let Some(selection) = &self.selection {
164 SpaceOrNewline.fmt(f)?;
165 f.write_str("WHERE")?;
166 SpaceOrNewline.fmt(f)?;
167 Indent(selection).fmt(f)?;
168 }
169 if let Some(returning) = &self.returning {
170 SpaceOrNewline.fmt(f)?;
171 f.write_str("RETURNING")?;
172 indented_list(f, returning)?;
173 }
174 if let Some(limit) = &self.limit {
175 SpaceOrNewline.fmt(f)?;
176 write!(f, "LIMIT {limit}")?;
177 }
178 Ok(())
179 }
180}
181
182#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
184pub struct Assignment {
185 pub target: AssignmentTarget,
186 pub value: Expr,
187}
188
189impl fmt::Display for Assignment {
190 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191 write!(f, "{} = {}", self.target, self.value)
192 }
193}
194
195#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
199pub enum AssignmentTarget {
200 ColumnName(ObjectName),
202 Tuple(Vec<ObjectName>),
204}
205
206impl fmt::Display for AssignmentTarget {
207 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208 match self {
209 AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
210 AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
211 }
212 }
213}
214
215#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
224pub enum MergeClauseKind {
225 Matched,
227 NotMatched,
229 NotMatchedByTarget,
233 NotMatchedBySource,
237}
238
239impl Display for MergeClauseKind {
240 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241 match self {
242 MergeClauseKind::Matched => write!(f, "MATCHED"),
243 MergeClauseKind::NotMatched => write!(f, "NOT MATCHED"),
244 MergeClauseKind::NotMatchedByTarget => write!(f, "NOT MATCHED BY TARGET"),
245 MergeClauseKind::NotMatchedBySource => write!(f, "NOT MATCHED BY SOURCE"),
246 }
247 }
248}
249
250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
255pub enum MergeInsertKind {
256 Values(Values),
263 Row,
271}
272
273impl Display for MergeInsertKind {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 match self {
276 MergeInsertKind::Values(values) => {
277 write!(f, "{values}")
278 }
279 MergeInsertKind::Row => {
280 write!(f, "ROW")
281 }
282 }
283 }
284}
285
286#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
297pub struct MergeInsertExpr {
298 pub columns: Vec<Ident>,
306 pub kind: MergeInsertKind,
308}
309
310impl Display for MergeInsertExpr {
311 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312 if !self.columns.is_empty() {
313 write!(f, "({}) ", display_comma_separated(self.columns.as_slice()))?;
314 }
315 write!(f, "{}", self.kind)
316 }
317}
318
319#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
329pub enum MergeAction {
330 Insert(MergeInsertExpr),
337 Update { assignments: Vec<Assignment> },
344 Delete,
346}
347
348impl Display for MergeAction {
349 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
350 match self {
351 MergeAction::Insert(insert) => {
352 write!(f, "INSERT {insert}")
353 }
354 MergeAction::Update { assignments } => {
355 write!(f, "UPDATE SET {}", display_comma_separated(assignments))
356 }
357 MergeAction::Delete => {
358 write!(f, "DELETE")
359 }
360 }
361 }
362}
363
364#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
373pub struct MergeClause {
374 pub clause_kind: MergeClauseKind,
375 pub predicate: Option<Expr>,
376 pub action: MergeAction,
377}
378
379impl Display for MergeClause {
380 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
381 let MergeClause {
382 clause_kind,
383 predicate,
384 action,
385 } = self;
386
387 write!(f, "WHEN {clause_kind}")?;
388 if let Some(pred) = predicate {
389 write!(f, " AND {pred}")?;
390 }
391 write!(f, " THEN {action}")
392 }
393}
394
395#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
401pub enum OutputClause {
402 Output {
403 select_items: Vec<SelectItem>,
404 into_table: Option<SelectInto>,
405 },
406 Returning {
407 select_items: Vec<SelectItem>,
408 },
409}
410
411impl fmt::Display for OutputClause {
412 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413 match self {
414 OutputClause::Output {
415 select_items,
416 into_table,
417 } => {
418 f.write_str("OUTPUT ")?;
419 display_comma_separated(select_items).fmt(f)?;
420 if let Some(into_table) = into_table {
421 f.write_str(" ")?;
422 into_table.fmt(f)?;
423 }
424 Ok(())
425 }
426 OutputClause::Returning { select_items } => {
427 f.write_str("RETURNING ")?;
428 display_comma_separated(select_items).fmt(f)
429 }
430 }
431 }
432}