1#[cfg(not(feature = "std"))]
2use alloc::{boxed::Box, vec::Vec};
3
4use super::display_utils::{SpaceOrNewline, indented_list};
5use crate::dml::{MergeClause, OutputClause, Update};
6use crate::*;
7
8#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11pub struct Query {
12 pub with: Option<With>,
14 pub body: Box<SetExpr>,
16 pub order_by: Option<OrderBy>,
18 pub limit: Option<Expr>,
20 pub offset: Option<Expr>,
22}
23
24impl fmt::Display for Query {
25 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26 if let Some(ref with) = self.with {
27 with.fmt(f)?;
28 SpaceOrNewline.fmt(f)?;
29 }
30 self.body.fmt(f)?;
31 if let Some(ref order_by) = self.order_by {
32 SpaceOrNewline.fmt(f)?;
33 order_by.fmt(f)?;
34 }
35
36 if let Some(ref offset) = self.offset {
37 SpaceOrNewline.fmt(f)?;
38 f.write_str("OFFSET ")?;
39 offset.fmt(f)?;
40 }
41 if let Some(ref limit) = self.limit {
42 SpaceOrNewline.fmt(f)?;
43 f.write_str("LIMIT ")?;
44 limit.fmt(f)?;
45 }
46 Ok(())
47 }
48}
49
50#[allow(clippy::large_enum_variant)]
53#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
54pub enum SetExpr {
55 Select(Box<Select>),
57 Query(Box<Query>),
60 SetOperation {
62 op: SetOperator,
63 set_quantifier: SetQuantifier,
64 left: Box<SetExpr>,
65 right: Box<SetExpr>,
66 },
67 Values(Values),
68 Insert(Insert),
69 Update(Update),
70 Delete(Delete),
71 Merge {
72 into: bool,
74 table: RelNamed,
76 source: RelNamed,
78 on: Box<Expr>,
80 clauses: Vec<MergeClause>,
82 output: Option<OutputClause>,
84 },
85 Source(String),
86 Copy(Box<Copy>),
87}
88
89impl SetExpr {
90 pub fn as_select(&self) -> Option<&Select> {
92 if let Self::Select(select) = self {
93 Some(&**select)
94 } else {
95 None
96 }
97 }
98}
99
100impl fmt::Display for SetExpr {
101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102 match self {
103 SetExpr::Select(s) => s.fmt(f),
104 SetExpr::Query(q) => {
105 f.write_str("(")?;
106 q.fmt(f)?;
107 f.write_str(")")
108 }
109 SetExpr::Values(v) => v.fmt(f),
110 SetExpr::Insert(v) => v.fmt(f),
111 SetExpr::Update(v) => v.fmt(f),
112 SetExpr::Delete(v) => v.fmt(f),
113 SetExpr::Merge {
114 into,
115 table,
116 source,
117 on,
118 clauses,
119 output,
120 } => {
121 write!(
122 f,
123 "MERGE{int} {table} USING {source} ",
124 int = if *into { " INTO" } else { "" }
125 )?;
126 write!(f, "ON {on} ")?;
127 write!(f, "{}", display_separated(clauses, " "))?;
128 if let Some(output) = output {
129 write!(f, " {output}")?;
130 }
131 Ok(())
132 }
133 SetExpr::SetOperation {
134 left,
135 right,
136 op,
137 set_quantifier,
138 } => {
139 Indent(left).fmt(f)?;
140 SpaceOrNewline.fmt(f)?;
141
142 op.fmt(f)?;
143 f.write_str(" ")?;
144 set_quantifier.fmt(f)?;
145
146 SpaceOrNewline.fmt(f)?;
147 Indent(right).fmt(f)?;
148 Ok(())
149 }
150 SetExpr::Source(s) => f.write_str(s),
151 SetExpr::Copy(c) => c.fmt(f),
152 }
153 }
154}
155
156#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
157pub struct Copy {
158 pub source: SetExpr,
159 pub target: Expr,
160 pub options: String,
161}
162
163impl fmt::Display for Copy {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 f.write_str("COPY(")?;
166 self.source.fmt(f)?;
167 f.write_str(") TO ")?;
168 self.target.fmt(f)?;
169 f.write_str(" (")?;
170 f.write_str(&self.options)?;
171 f.write_str(")")?;
172 Ok(())
173 }
174}
175
176#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
177pub enum SetOperator {
178 Union,
179 Except,
180 Intersect,
181 Minus,
182}
183
184impl fmt::Display for SetOperator {
185 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186 f.write_str(match self {
187 SetOperator::Union => "UNION",
188 SetOperator::Except => "EXCEPT",
189 SetOperator::Intersect => "INTERSECT",
190 SetOperator::Minus => "MINUS",
191 })
192 }
193}
194
195#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
197pub enum SetQuantifier {
198 All,
199 Distinct,
200 ByName,
201 AllByName,
202 DistinctByName,
203}
204
205impl fmt::Display for SetQuantifier {
206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207 match self {
208 SetQuantifier::All => write!(f, "ALL"),
209 SetQuantifier::Distinct => write!(f, "DISTINCT"),
210 SetQuantifier::ByName => write!(f, "BY NAME"),
211 SetQuantifier::AllByName => write!(f, "ALL BY NAME"),
212 SetQuantifier::DistinctByName => write!(f, "DISTINCT BY NAME"),
213 }
214 }
215}
216
217#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
221pub struct Select {
222 pub from: Vec<RelNamed>,
224 pub selection: Option<Expr>,
226 pub group_by: Vec<Expr>,
228 pub distinct: Option<Distinct>,
230 pub projection: Vec<SelectItem>,
232 pub having: Option<Expr>,
234}
235
236impl fmt::Display for Select {
237 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
238 let mut is_first = true;
239 fn space_or_nl(f: &mut fmt::Formatter<'_>, is_first: &mut bool) -> fmt::Result {
240 if *is_first {
241 *is_first = false;
242 return Ok(());
243 }
244 SpaceOrNewline.fmt(f)
245 }
246
247 if !f.alternate() {
248 space_or_nl(f, &mut is_first)?;
249 f.write_str("SELECT")?;
250 if let Some(ref distinct) = self.distinct {
251 f.write_str(" ")?;
252 distinct.fmt(f)?;
253 }
254 if !self.projection.is_empty() {
255 indented_list(f, &self.projection)?;
256 }
257 }
258
259 if !self.from.is_empty() {
260 space_or_nl(f, &mut is_first)?;
261 f.write_str("FROM")?;
262 indented_list(f, &self.from)?;
263 }
264 if let Some(ref selection) = self.selection {
265 space_or_nl(f, &mut is_first)?;
266 f.write_str("WHERE ")?;
267 selection.fmt(f)?;
268 }
269
270 if !self.group_by.is_empty() {
271 space_or_nl(f, &mut is_first)?;
272 f.write_str("GROUP BY ")?;
273 display_comma_separated(&self.group_by).fmt(f)?;
274 }
275
276 if f.alternate() {
277 space_or_nl(f, &mut is_first)?;
278 write!(f, "SELECT")?;
279 if let Some(ref distinct) = self.distinct {
280 f.write_str(" ")?;
281 distinct.fmt(f)?;
282 }
283 if !self.projection.is_empty() {
284 indented_list(f, &self.projection)?;
285 }
286 }
287 if let Some(ref having) = self.having {
288 space_or_nl(f, &mut is_first)?;
289 f.write_str("HAVING")?;
290 Indent(having).fmt(f)?;
291 }
292 Ok(())
293 }
294}
295
296#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
298pub struct LateralView {
299 pub lateral_view: Expr,
301 pub lateral_view_name: ObjectName,
303 pub lateral_col_alias: Vec<Ident>,
305 pub outer: bool,
307}
308
309impl fmt::Display for LateralView {
310 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311 write!(
312 f,
313 " LATERAL VIEW{outer} {} {}",
314 self.lateral_view,
315 self.lateral_view_name,
316 outer = if self.outer { " OUTER" } else { "" }
317 )?;
318 if !self.lateral_col_alias.is_empty() {
319 write!(
320 f,
321 " AS {}",
322 display_comma_separated(&self.lateral_col_alias)
323 )?;
324 }
325 Ok(())
326 }
327}
328
329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
330pub struct With {
331 pub recursive: bool,
333 pub cte_tables: Vec<Cte>,
334}
335
336impl fmt::Display for With {
337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338 f.write_str("WITH ")?;
339 if self.recursive {
340 f.write_str("RECURSIVE ")?;
341 }
342 display_comma_separated(&self.cte_tables).fmt(f)?;
343 Ok(())
344 }
345}
346
347#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
348pub enum CteAsMaterialized {
349 Materialized,
351 NotMaterialized,
353}
354
355impl fmt::Display for CteAsMaterialized {
356 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
357 match *self {
358 CteAsMaterialized::Materialized => {
359 write!(f, "MATERIALIZED")?;
360 }
361 CteAsMaterialized::NotMaterialized => {
362 write!(f, "NOT MATERIALIZED")?;
363 }
364 };
365 Ok(())
366 }
367}
368
369#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
374pub struct Cte {
375 pub alias: TableAlias,
376 pub query: Box<Query>,
377 pub materialized: Option<CteAsMaterialized>,
378}
379
380impl fmt::Display for Cte {
381 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
382 self.alias.fmt(f)?;
383 f.write_str(" AS")?;
384 if let Some(materialized) = self.materialized.as_ref() {
385 f.write_str(" ")?;
386 materialized.fmt(f)?;
387 };
388 f.write_str(" (")?;
389 NewLine.fmt(f)?;
390 Indent(&self.query).fmt(f)?;
391 NewLine.fmt(f)?;
392 f.write_str(")")?;
393 Ok(())
394 }
395}
396
397#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
399pub struct SelectItem {
400 pub expr: Expr,
401 pub alias: Option<Ident>,
402}
403
404impl SelectItem {
405 pub fn unnamed(expr: Expr) -> Self {
406 SelectItem { expr, alias: None }
407 }
408}
409
410impl fmt::Display for SelectItem {
411 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412 if f.alternate()
413 && let Some(alias) = &self.alias
414 {
415 write!(f, "{:05} = ", &alias.value)?;
416 }
417
418 self.expr.fmt(f)?;
419
420 if !f.alternate()
421 && let Some(alias) = &self.alias
422 {
423 f.write_str(" AS ")?;
424 alias.fmt(f)?;
425 }
426 Ok(())
427 }
428}
429
430#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
437pub struct ExprWithAlias {
438 pub expr: Expr,
439 pub alias: Option<Ident>,
440}
441
442impl fmt::Display for ExprWithAlias {
443 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444 let ExprWithAlias { expr, alias } = self;
445 write!(f, "{expr}")?;
446 if let Some(alias) = alias {
447 write!(f, " AS {alias}")?;
448 }
449 Ok(())
450 }
451}
452
453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
455pub struct RelNamed {
456 pub lateral: bool,
457 pub alias: Option<TableAlias>,
458 pub expr: RelExpr,
459}
460
461impl RelNamed {
462 pub fn unnamed(expr: RelExpr) -> Self {
463 Self {
464 expr,
465 alias: None,
466 lateral: false,
467 }
468 }
469}
470
471impl fmt::Display for RelNamed {
472 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
473 if self.lateral && !matches!(self.expr, RelExpr::Table(..)) {
474 write!(f, "LATERAL ")?;
475 }
476 if f.alternate()
477 && let Some(alias) = &self.alias
478 {
479 write!(f, "{alias} = ")?;
480 }
481 self.expr.fmt(f)?;
482 if !f.alternate()
483 && let Some(alias) = &self.alias
484 {
485 write!(f, " AS {alias}")?;
486 }
487 Ok(())
488 }
489}
490
491#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
492pub enum RelExpr {
493 Table(ObjectName),
494 Subquery(Box<Query>),
495 Function {
496 name: ObjectName,
497 args: Vec<Expr>,
498 ordinality: bool,
499 },
500}
501
502impl RelExpr {
503 pub fn unnamed(self) -> RelNamed {
504 RelNamed::unnamed(self)
505 }
506
507 pub fn alias(self, alias: Ident) -> RelNamed {
508 RelNamed {
509 expr: self,
510 alias: Some(TableAlias::simple(alias)),
511 lateral: false,
512 }
513 }
514
515 pub fn alias_cols(self, alias: Ident, cols: Vec<Ident>) -> RelNamed {
516 RelNamed {
517 expr: self,
518 alias: Some(TableAlias::new(alias, cols)),
519 lateral: false,
520 }
521 }
522
523 pub fn subquery(query: Query) -> Self {
524 RelExpr::Subquery(Box::new(query))
525 }
526
527 pub fn function(name: Ident, args: Vec<Expr>) -> Self {
528 RelExpr::Function {
529 name: ObjectName(vec![name]),
530 args: args.into_iter().collect(),
531 ordinality: false,
532 }
533 }
534}
535
536impl fmt::Display for RelExpr {
537 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
538 match self {
539 RelExpr::Table(name) => {
540 name.fmt(f)?;
541 }
542 RelExpr::Subquery(subquery) => {
543 f.write_str("(")?;
544 NewLine.fmt(f)?;
545 Indent(subquery).fmt(f)?;
546 NewLine.fmt(f)?;
547 f.write_str(")")?;
548 }
549 RelExpr::Function {
550 name,
551 args,
552 ordinality,
553 } => {
554 write!(f, "{name}({})", display_comma_separated(args))?;
555 if *ordinality {
556 write!(f, " WITH ORDINALITY")?;
557 }
558 }
559 }
560 Ok(())
561 }
562}
563
564#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
565pub struct TableAlias {
566 pub name: Ident,
567 pub columns: Vec<Ident>,
568}
569
570impl TableAlias {
571 fn new(name: Ident, columns: Vec<Ident>) -> Self {
572 Self { name, columns }
573 }
574
575 pub fn simple(name: Ident) -> Self {
576 Self::new(name, vec![])
577 }
578}
579
580impl fmt::Display for TableAlias {
581 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
582 write!(f, "{}", self.name)?;
583 if !self.columns.is_empty() {
584 write!(f, " ({})", display_comma_separated(&self.columns))?;
585 }
586 Ok(())
587 }
588}
589
590#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
591pub enum TableVersion {
592 ForSystemTimeAsOf(Expr),
595 Function(Expr),
598}
599
600impl Display for TableVersion {
601 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
602 match self {
603 TableVersion::ForSystemTimeAsOf(e) => write!(f, "FOR SYSTEM_TIME AS OF {e}")?,
604 TableVersion::Function(func) => write!(f, "{func}")?,
605 }
606 Ok(())
607 }
608}
609
610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
611pub struct Join {
612 pub relation: RelNamed,
613 pub join_operator: JoinOperator,
614}
615
616impl fmt::Display for Join {
617 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
618 fn prefix(constraint: &JoinConstraint) -> &'static str {
619 match constraint {
620 JoinConstraint::Natural => "NATURAL ",
621 _ => "",
622 }
623 }
624 fn suffix(constraint: &'_ JoinConstraint) -> impl fmt::Display + '_ {
625 struct Suffix<'a>(&'a JoinConstraint);
626 impl fmt::Display for Suffix<'_> {
627 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
628 match self.0 {
629 JoinConstraint::On(expr) => write!(f, " ON {expr}"),
630 JoinConstraint::Using(attrs) => {
631 write!(f, " USING({})", display_comma_separated(attrs))
632 }
633 _ => Ok(()),
634 }
635 }
636 }
637 Suffix(constraint)
638 }
639
640 match &self.join_operator {
641 JoinOperator::Join(constraint) => f.write_fmt(format_args!(
642 "{}JOIN {}{}",
643 prefix(constraint),
644 self.relation,
645 suffix(constraint)
646 )),
647 JoinOperator::Inner(constraint) => f.write_fmt(format_args!(
648 "{}INNER JOIN {}{}",
649 prefix(constraint),
650 self.relation,
651 suffix(constraint)
652 )),
653 JoinOperator::Left(constraint) => f.write_fmt(format_args!(
654 "{}LEFT JOIN {}{}",
655 prefix(constraint),
656 self.relation,
657 suffix(constraint)
658 )),
659 JoinOperator::LeftOuter(constraint) => f.write_fmt(format_args!(
660 "{}LEFT OUTER JOIN {}{}",
661 prefix(constraint),
662 self.relation,
663 suffix(constraint)
664 )),
665 JoinOperator::Right(constraint) => f.write_fmt(format_args!(
666 "{}RIGHT JOIN {}{}",
667 prefix(constraint),
668 self.relation,
669 suffix(constraint)
670 )),
671 JoinOperator::RightOuter(constraint) => f.write_fmt(format_args!(
672 "{}RIGHT OUTER JOIN {}{}",
673 prefix(constraint),
674 self.relation,
675 suffix(constraint)
676 )),
677 JoinOperator::FullOuter(constraint) => f.write_fmt(format_args!(
678 "{}FULL JOIN {}{}",
679 prefix(constraint),
680 self.relation,
681 suffix(constraint)
682 )),
683 JoinOperator::CrossJoin => f.write_fmt(format_args!("CROSS JOIN {}", self.relation)),
684 JoinOperator::Semi(constraint) => f.write_fmt(format_args!(
685 "{}SEMI JOIN {}{}",
686 prefix(constraint),
687 self.relation,
688 suffix(constraint)
689 )),
690 JoinOperator::LeftSemi(constraint) => f.write_fmt(format_args!(
691 "{}LEFT SEMI JOIN {}{}",
692 prefix(constraint),
693 self.relation,
694 suffix(constraint)
695 )),
696 JoinOperator::RightSemi(constraint) => f.write_fmt(format_args!(
697 "{}RIGHT SEMI JOIN {}{}",
698 prefix(constraint),
699 self.relation,
700 suffix(constraint)
701 )),
702 JoinOperator::Anti(constraint) => f.write_fmt(format_args!(
703 "{}ANTI JOIN {}{}",
704 prefix(constraint),
705 self.relation,
706 suffix(constraint)
707 )),
708 JoinOperator::LeftAnti(constraint) => f.write_fmt(format_args!(
709 "{}LEFT ANTI JOIN {}{}",
710 prefix(constraint),
711 self.relation,
712 suffix(constraint)
713 )),
714 JoinOperator::RightAnti(constraint) => f.write_fmt(format_args!(
715 "{}RIGHT ANTI JOIN {}{}",
716 prefix(constraint),
717 self.relation,
718 suffix(constraint)
719 )),
720 JoinOperator::CrossApply => f.write_fmt(format_args!("CROSS APPLY {}", self.relation)),
721 JoinOperator::OuterApply => f.write_fmt(format_args!("OUTER APPLY {}", self.relation)),
722 JoinOperator::AsOf {
723 match_condition,
724 constraint,
725 } => f.write_fmt(format_args!(
726 "ASOF JOIN {} MATCH_CONDITION ({match_condition}){}",
727 self.relation,
728 suffix(constraint)
729 )),
730 JoinOperator::StraightJoin(constraint) => f.write_fmt(format_args!(
731 "STRAIGHT_JOIN {}{}",
732 self.relation,
733 suffix(constraint)
734 )),
735 }
736 }
737}
738
739#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
740pub enum JoinOperator {
741 Join(JoinConstraint),
742 Inner(JoinConstraint),
743 Left(JoinConstraint),
744 LeftOuter(JoinConstraint),
745 Right(JoinConstraint),
746 RightOuter(JoinConstraint),
747 FullOuter(JoinConstraint),
748 CrossJoin,
749 Semi(JoinConstraint),
751 LeftSemi(JoinConstraint),
753 RightSemi(JoinConstraint),
755 Anti(JoinConstraint),
757 LeftAnti(JoinConstraint),
759 RightAnti(JoinConstraint),
761 CrossApply,
763 OuterApply,
765 AsOf {
770 match_condition: Expr,
771 constraint: JoinConstraint,
772 },
773 StraightJoin(JoinConstraint),
777}
778
779#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
780pub enum JoinConstraint {
781 On(Expr),
782 Using(Vec<ObjectName>),
783 Natural,
784 None,
785}
786
787#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
788pub enum OrderByKind {
789 All(OrderByOptions),
794
795 Expressions(Vec<OrderByExpr>),
797}
798
799#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
800pub struct OrderBy {
801 pub exprs: Vec<OrderByExpr>,
802}
803
804impl fmt::Display for OrderBy {
805 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
806 write!(f, "ORDER BY")?;
807 write!(f, " {}", display_comma_separated(&self.exprs))?;
808
809 Ok(())
810 }
811}
812
813#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
815pub struct OrderByExpr {
816 pub expr: Expr,
817 pub options: OrderByOptions,
818}
819
820impl fmt::Display for OrderByExpr {
821 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
822 write!(f, "{}{}", self.expr, self.options)?;
823 Ok(())
824 }
825}
826
827#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
828pub struct OrderByOptions {
829 pub asc: Option<bool>,
831 pub nulls_first: Option<bool>,
833}
834
835impl fmt::Display for OrderByOptions {
836 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
837 match self.asc {
838 Some(true) => write!(f, " ASC")?,
839 Some(false) => write!(f, " DESC")?,
840 None => (),
841 }
842 match self.nulls_first {
843 Some(true) => write!(f, " NULLS FIRST")?,
844 Some(false) => write!(f, " NULLS LAST")?,
845 None => (),
846 }
847 Ok(())
848 }
849}
850
851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
852pub enum Distinct {
853 Distinct,
855
856 On(Vec<Expr>),
858}
859
860impl fmt::Display for Distinct {
861 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
862 match self {
863 Distinct::Distinct => write!(f, "DISTINCT"),
864 Distinct::On(col_names) => {
865 let col_names = display_comma_separated(col_names);
866 write!(f, "DISTINCT ON ({col_names})")
867 }
868 }
869 }
870}
871
872#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
873pub struct Values {
874 pub explicit_row: bool,
877 pub rows: Vec<Vec<Expr>>,
878}
879
880impl fmt::Display for Values {
881 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
882 f.write_str("VALUES")?;
883 let prefix = if self.explicit_row { "ROW" } else { "" };
884 let mut delim = "";
885 for row in &self.rows {
886 f.write_str(delim)?;
887 delim = ",";
888 SpaceOrNewline.fmt(f)?;
889 Indent(format_args!("{prefix}({})", display_comma_separated(row))).fmt(f)?;
890 }
891 Ok(())
892 }
893}
894
895#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
896pub struct SelectInto {
897 pub temporary: bool,
898 pub unlogged: bool,
899 pub table: bool,
900 pub name: ObjectName,
901}
902
903impl fmt::Display for SelectInto {
904 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
905 let temporary = if self.temporary { " TEMPORARY" } else { "" };
906 let unlogged = if self.unlogged { " UNLOGGED" } else { "" };
907 let table = if self.table { " TABLE" } else { "" };
908
909 write!(f, "INTO{}{}{} {}", temporary, unlogged, table, self.name)
910 }
911}