1#[cfg(not(feature = "std"))]
2use alloc::{
3 boxed::Box,
4 format,
5 string::{String, ToString},
6 vec::Vec,
7};
8
9use core::fmt::{self, Display};
10
11use crate::{RelNamed, SelectInto, TableAlias, Values};
12
13use super::display_utils::{Indent, SpaceOrNewline, indented_list};
14use super::{Expr, Ident, ObjectName, OrderByExpr, Query, SelectItem, display_comma_separated};
15
16#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
18pub struct Insert {
19 pub table: ObjectName,
21 pub columns: Vec<Ident>,
23 pub source: Box<Query>,
25}
26
27impl Display for Insert {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 write!(f, "INSERT INTO {} ", self.table)?;
30
31 if !self.columns.is_empty() {
32 write!(f, "({})", display_comma_separated(&self.columns))?;
33 SpaceOrNewline.fmt(f)?;
34 }
35 self.source.fmt(f)?;
36 Ok(())
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
42pub struct Delete {
43 pub tables: Vec<ObjectName>,
45 pub from: FromTable,
47 pub using: Option<Vec<RelNamed>>,
49 pub selection: Option<Expr>,
51 pub returning: Option<Vec<SelectItem>>,
53 pub order_by: Vec<OrderByExpr>,
55 pub limit: Option<Expr>,
57}
58
59impl Display for Delete {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.write_str("DELETE")?;
62 if !self.tables.is_empty() {
63 indented_list(f, &self.tables)?;
64 }
65 match &self.from {
66 FromTable::WithFromKeyword(from) => {
67 f.write_str(" FROM")?;
68 indented_list(f, from)?;
69 }
70 FromTable::WithoutKeyword(from) => {
71 indented_list(f, from)?;
72 }
73 }
74 if let Some(using) = &self.using {
75 SpaceOrNewline.fmt(f)?;
76 f.write_str("USING")?;
77 indented_list(f, using)?;
78 }
79 if let Some(selection) = &self.selection {
80 SpaceOrNewline.fmt(f)?;
81 f.write_str("WHERE")?;
82 SpaceOrNewline.fmt(f)?;
83 Indent(selection).fmt(f)?;
84 }
85 if let Some(returning) = &self.returning {
86 SpaceOrNewline.fmt(f)?;
87 f.write_str("RETURNING")?;
88 indented_list(f, returning)?;
89 }
90 if !self.order_by.is_empty() {
91 SpaceOrNewline.fmt(f)?;
92 f.write_str("ORDER BY")?;
93 indented_list(f, &self.order_by)?;
94 }
95 if let Some(limit) = &self.limit {
96 SpaceOrNewline.fmt(f)?;
97 f.write_str("LIMIT")?;
98 SpaceOrNewline.fmt(f)?;
99 Indent(limit).fmt(f)?;
100 }
101 Ok(())
102 }
103}
104#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
111pub enum FromTable {
112 WithFromKeyword(Vec<RelNamed>),
114 WithoutKeyword(Vec<RelNamed>),
117}
118impl Display for FromTable {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 match self {
121 FromTable::WithFromKeyword(tables) => {
122 write!(f, "FROM {}", display_comma_separated(tables))
123 }
124 FromTable::WithoutKeyword(tables) => {
125 write!(f, "{}", display_comma_separated(tables))
126 }
127 }
128 }
129}
130
131#[allow(clippy::large_enum_variant)]
132#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
133pub struct Update {
134 pub table: ObjectName,
136 pub alias: Option<TableAlias>,
138 pub assignments: Vec<Assignment>,
140 pub from: Vec<RelNamed>,
142 pub selection: Option<Expr>,
144 pub returning: Option<Vec<SelectItem>>,
146 pub limit: Option<Expr>,
148}
149
150impl fmt::Display for Update {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 f.write_str("UPDATE ")?;
153 self.table.fmt(f)?;
154 if let Some(alias) = &self.alias {
155 f.write_str(" AS ")?;
156 alias.fmt(f)?;
157 }
158 if !self.assignments.is_empty() {
159 SpaceOrNewline.fmt(f)?;
160 f.write_str("SET")?;
161 indented_list(f, &self.assignments)?;
162 }
163 if !self.from.is_empty() {
164 SpaceOrNewline.fmt(f)?;
165 f.write_str("FROM")?;
166 indented_list(f, &self.from)?;
167 }
168 if let Some(selection) = &self.selection {
169 SpaceOrNewline.fmt(f)?;
170 f.write_str("WHERE")?;
171 SpaceOrNewline.fmt(f)?;
172 Indent(selection).fmt(f)?;
173 }
174 if let Some(returning) = &self.returning {
175 SpaceOrNewline.fmt(f)?;
176 f.write_str("RETURNING")?;
177 indented_list(f, returning)?;
178 }
179 if let Some(limit) = &self.limit {
180 SpaceOrNewline.fmt(f)?;
181 write!(f, "LIMIT {limit}")?;
182 }
183 Ok(())
184 }
185}
186
187#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
189pub struct Assignment {
190 pub target: AssignmentTarget,
191 pub value: Expr,
192}
193
194impl fmt::Display for Assignment {
195 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196 write!(f, "{} = {}", self.target, self.value)
197 }
198}
199
200#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
204pub enum AssignmentTarget {
205 ColumnName(ObjectName),
207 Tuple(Vec<ObjectName>),
209}
210
211impl fmt::Display for AssignmentTarget {
212 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213 match self {
214 AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
215 AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
216 }
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
229pub enum MergeClauseKind {
230 Matched,
232 NotMatched,
234 NotMatchedByTarget,
238 NotMatchedBySource,
242}
243
244impl Display for MergeClauseKind {
245 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246 match self {
247 MergeClauseKind::Matched => write!(f, "MATCHED"),
248 MergeClauseKind::NotMatched => write!(f, "NOT MATCHED"),
249 MergeClauseKind::NotMatchedByTarget => write!(f, "NOT MATCHED BY TARGET"),
250 MergeClauseKind::NotMatchedBySource => write!(f, "NOT MATCHED BY SOURCE"),
251 }
252 }
253}
254
255#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
260pub enum MergeInsertKind {
261 Values(Values),
268 Row,
276}
277
278impl Display for MergeInsertKind {
279 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280 match self {
281 MergeInsertKind::Values(values) => {
282 write!(f, "{values}")
283 }
284 MergeInsertKind::Row => {
285 write!(f, "ROW")
286 }
287 }
288 }
289}
290
291#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
302pub struct MergeInsertExpr {
303 pub columns: Vec<Ident>,
311 pub kind: MergeInsertKind,
313}
314
315impl Display for MergeInsertExpr {
316 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317 if !self.columns.is_empty() {
318 write!(f, "({}) ", display_comma_separated(self.columns.as_slice()))?;
319 }
320 write!(f, "{}", self.kind)
321 }
322}
323
324#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
334pub enum MergeAction {
335 Insert(MergeInsertExpr),
342 Update { assignments: Vec<Assignment> },
349 Delete,
351}
352
353impl Display for MergeAction {
354 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
355 match self {
356 MergeAction::Insert(insert) => {
357 write!(f, "INSERT {insert}")
358 }
359 MergeAction::Update { assignments } => {
360 write!(f, "UPDATE SET {}", display_comma_separated(assignments))
361 }
362 MergeAction::Delete => {
363 write!(f, "DELETE")
364 }
365 }
366 }
367}
368
369#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
378pub struct MergeClause {
379 pub clause_kind: MergeClauseKind,
380 pub predicate: Option<Expr>,
381 pub action: MergeAction,
382}
383
384impl Display for MergeClause {
385 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
386 let MergeClause {
387 clause_kind,
388 predicate,
389 action,
390 } = self;
391
392 write!(f, "WHEN {clause_kind}")?;
393 if let Some(pred) = predicate {
394 write!(f, " AND {pred}")?;
395 }
396 write!(f, " THEN {action}")
397 }
398}
399
400#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
406pub enum OutputClause {
407 Output {
408 select_items: Vec<SelectItem>,
409 into_table: Option<SelectInto>,
410 },
411 Returning {
412 select_items: Vec<SelectItem>,
413 },
414}
415
416impl fmt::Display for OutputClause {
417 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418 match self {
419 OutputClause::Output {
420 select_items,
421 into_table,
422 } => {
423 f.write_str("OUTPUT ")?;
424 display_comma_separated(select_items).fmt(f)?;
425 if let Some(into_table) = into_table {
426 f.write_str(" ")?;
427 into_table.fmt(f)?;
428 }
429 Ok(())
430 }
431 OutputClause::Returning { select_items } => {
432 f.write_str("RETURNING ")?;
433 display_comma_separated(select_items).fmt(f)
434 }
435 }
436 }
437}