1#[cfg(not(feature = "std"))]
14use alloc::{boxed::Box, vec::Vec};
15
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19use crate::ast::*;
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct Query {
26 pub with: Option<With>,
28 pub body: SetExpr,
30 pub order_by: Vec<OrderByExpr>,
32 pub limit: Option<Expr>,
34 pub offset: Option<String>,
39 pub fetch: Option<Fetch>,
44}
45
46impl Query {
47 pub fn as_simple_values(&self) -> Option<&Values> {
49 match &self {
50 Query {
51 with: None,
52 body: SetExpr::Values(values),
53 order_by,
54 limit: None,
55 offset: None,
56 fetch: None,
57 } if order_by.is_empty() => Some(values),
58 _ => None,
59 }
60 }
61}
62
63impl fmt::Display for Query {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 if let Some(ref with) = self.with {
66 write!(f, "{} ", with)?;
67 }
68 write!(f, "{}", self.body)?;
69 if !self.order_by.is_empty() {
70 write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
71 }
72 if let Some(ref limit) = self.limit {
73 write!(f, " LIMIT {}", limit)?;
74 }
75 if let Some(ref offset) = self.offset {
76 write!(f, " OFFSET {}", offset)?;
77 }
78 if let Some(ref fetch) = self.fetch {
79 write!(f, " {}", fetch)?;
80 }
81 Ok(())
82 }
83}
84
85#[allow(clippy::large_enum_variant)]
88#[derive(Debug, Clone, PartialEq, Eq, Hash)]
89#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
90pub enum SetExpr {
91 Select(Box<Select>),
93 Query(Box<Query>),
96 SetOperation {
98 op: SetOperator,
99 all: bool,
100 corresponding: Corresponding,
101 left: Box<SetExpr>,
102 right: Box<SetExpr>,
103 },
104 Values(Values),
105}
106
107impl fmt::Display for SetExpr {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 match self {
110 SetExpr::Select(s) => write!(f, "{}", s),
111 SetExpr::Query(q) => write!(f, "({})", q),
112 SetExpr::Values(v) => write!(f, "{}", v),
113 SetExpr::SetOperation {
114 left,
115 right,
116 op,
117 all,
118 corresponding,
119 } => {
120 let all_str = if *all { " ALL" } else { "" };
121 write!(f, "{} {}{}{} {}", left, op, all_str, corresponding, right)
122 }
123 }
124 }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Hash)]
128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
129pub enum SetOperator {
130 Union,
131 Except,
132 Intersect,
133}
134
135impl fmt::Display for SetOperator {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 f.write_str(match self {
138 SetOperator::Union => "UNION",
139 SetOperator::Except => "EXCEPT",
140 SetOperator::Intersect => "INTERSECT",
141 })
142 }
143}
144
145#[derive(Debug, Clone, PartialEq, Eq, Hash)]
146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
147pub struct Corresponding {
149 pub corresponding: bool,
150 pub column_list: Option<Vec<Ident>>,
151}
152
153impl Corresponding {
154 pub fn with_column_list(column_list: Option<Vec<Ident>>) -> Self {
155 Self {
156 corresponding: true,
157 column_list,
158 }
159 }
160
161 pub fn none() -> Self {
162 Self {
163 corresponding: false,
164 column_list: None,
165 }
166 }
167
168 pub fn is_corresponding(&self) -> bool {
169 self.corresponding
170 }
171
172 pub fn column_list(&self) -> Option<&[Ident]> {
173 self.column_list.as_deref()
174 }
175}
176
177impl fmt::Display for Corresponding {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 if self.corresponding {
180 write!(f, " CORRESPONDING")?;
181 if let Some(column_list) = &self.column_list {
182 write!(f, " BY ({})", display_comma_separated(column_list))?;
183 }
184 }
185 Ok(())
186 }
187}
188
189#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
194pub struct Select {
195 pub distinct: Distinct,
196 pub projection: Vec<SelectItem>,
198 pub from: Vec<TableWithJoins>,
200 pub lateral_views: Vec<LateralView>,
202 pub selection: Option<Expr>,
204 pub group_by: Vec<Expr>,
206 pub having: Option<Expr>,
208 pub window: Vec<NamedWindow>,
210}
211
212impl fmt::Display for Select {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(f, "SELECT{}", &self.distinct)?;
215 write!(f, " {}", display_comma_separated(&self.projection))?;
216 if !self.from.is_empty() {
217 write!(f, " FROM {}", display_comma_separated(&self.from))?;
218 }
219 if !self.lateral_views.is_empty() {
220 for lv in &self.lateral_views {
221 write!(f, "{}", lv)?;
222 }
223 }
224 if let Some(ref selection) = self.selection {
225 write!(f, " WHERE {}", selection)?;
226 }
227 if !self.group_by.is_empty() {
228 write!(f, " GROUP BY {}", display_comma_separated(&self.group_by))?;
229 }
230 if let Some(ref having) = self.having {
231 write!(f, " HAVING {}", having)?;
232 }
233 if !self.window.is_empty() {
234 write!(f, " WINDOW {}", display_comma_separated(&self.window))?;
235 }
236 Ok(())
237 }
238}
239
240#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
243#[expect(clippy::enum_variant_names)]
244pub enum Distinct {
245 #[default]
247 All,
248 Distinct,
250 DistinctOn(Vec<Expr>),
252}
253
254impl Distinct {
255 pub const fn is_all(&self) -> bool {
256 matches!(self, Distinct::All)
257 }
258
259 pub const fn is_distinct(&self) -> bool {
260 matches!(self, Distinct::Distinct)
261 }
262}
263
264impl fmt::Display for Distinct {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 match self {
267 Distinct::All => write!(f, ""),
268 Distinct::Distinct => write!(f, " DISTINCT"),
269 Distinct::DistinctOn(exprs) => {
270 write!(f, " DISTINCT ON ({})", display_comma_separated(exprs))
271 }
272 }
273 }
274}
275
276#[derive(Debug, Clone, PartialEq, Eq, Hash)]
278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
279pub struct LateralView {
280 pub lateral_view: Expr,
282 pub lateral_view_name: ObjectName,
284 pub lateral_col_alias: Vec<Ident>,
286 pub outer: bool,
288}
289
290impl fmt::Display for LateralView {
291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292 write!(
293 f,
294 " LATERAL VIEW{outer} {} {}",
295 self.lateral_view,
296 self.lateral_view_name,
297 outer = if self.outer { " OUTER" } else { "" }
298 )?;
299 if !self.lateral_col_alias.is_empty() {
300 write!(
301 f,
302 " AS {}",
303 display_comma_separated(&self.lateral_col_alias)
304 )?;
305 }
306 Ok(())
307 }
308}
309
310#[derive(Debug, Clone, PartialEq, Eq, Hash)]
311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
312pub struct With {
313 pub recursive: bool,
314 pub cte_tables: Vec<Cte>,
315}
316
317impl fmt::Display for With {
318 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
319 write!(
320 f,
321 "WITH {}{}",
322 if self.recursive { "RECURSIVE " } else { "" },
323 display_comma_separated(&self.cte_tables)
324 )
325 }
326}
327
328#[derive(Debug, Clone, PartialEq, Eq, Hash)]
334#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
335pub struct Cte {
336 pub alias: TableAlias,
337 pub cte_inner: CteInner,
338}
339
340impl fmt::Display for Cte {
341 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 match &self.cte_inner {
343 CteInner::Query(query) => write!(f, "{} AS ({})", self.alias, query)?,
344 CteInner::ChangeLog(obj_name) => {
345 write!(f, "{} AS changelog from {}", self.alias, obj_name)?
346 }
347 }
348 Ok(())
349 }
350}
351
352#[derive(Debug, Clone, PartialEq, Eq, Hash)]
353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
354pub enum CteInner {
355 Query(Box<Query>),
356 ChangeLog(ObjectName),
357}
358
359#[derive(Debug, Clone, PartialEq, Eq, Hash)]
361#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
362pub enum SelectItem {
363 UnnamedExpr(Expr),
365 ExprQualifiedWildcard(Expr, Vec<Ident>),
369 ExprWithAlias { expr: Expr, alias: Ident },
371 QualifiedWildcard(ObjectName, Option<Vec<Expr>>),
373 Wildcard(Option<Vec<Expr>>),
375}
376
377impl fmt::Display for SelectItem {
378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379 match &self {
380 SelectItem::UnnamedExpr(expr) => write!(f, "{}", expr),
381 SelectItem::ExprWithAlias { expr, alias } => write!(f, "{} AS {}", expr, alias),
382 SelectItem::ExprQualifiedWildcard(expr, prefix) => write!(
383 f,
384 "({}){}.*",
385 expr,
386 prefix
387 .iter()
388 .format_with("", |i, f| f(&format_args!(".{i}")))
389 ),
390 SelectItem::QualifiedWildcard(prefix, except) => match except {
391 Some(cols) => write!(
392 f,
393 "{}.* EXCEPT ({})",
394 prefix,
395 cols.iter()
396 .map(|v| v.to_string())
397 .collect::<Vec<String>>()
398 .as_slice()
399 .join(", ")
400 ),
401 None => write!(f, "{}.*", prefix),
402 },
403 SelectItem::Wildcard(except) => match except {
404 Some(cols) => write!(
405 f,
406 "* EXCEPT ({})",
407 cols.iter()
408 .map(|v| v.to_string())
409 .collect::<Vec<String>>()
410 .as_slice()
411 .join(", ")
412 ),
413 None => write!(f, "*"),
414 },
415 }
416 }
417}
418
419#[derive(Debug, Clone, PartialEq, Eq, Hash)]
420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
421pub struct TableWithJoins {
422 pub relation: TableFactor,
423 pub joins: Vec<Join>,
424}
425
426impl fmt::Display for TableWithJoins {
427 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428 write!(f, "{}", self.relation)?;
429 for join in &self.joins {
430 write!(f, "{}", join)?;
431 }
432 Ok(())
433 }
434}
435
436#[derive(Debug, Clone, PartialEq, Eq, Hash)]
438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
439pub enum TableFactor {
440 Table {
441 name: ObjectName,
442 alias: Option<TableAlias>,
443 as_of: Option<AsOf>,
444 },
445 Derived {
446 lateral: bool,
447 subquery: Box<Query>,
448 alias: Option<TableAlias>,
449 },
450 TableFunction {
454 name: ObjectName,
455 alias: Option<TableAlias>,
456 args: Vec<FunctionArg>,
457 with_ordinality: bool,
458 },
459 NestedJoin(Box<TableWithJoins>),
466}
467
468impl fmt::Display for TableFactor {
469 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
470 match self {
471 TableFactor::Table { name, alias, as_of } => {
472 write!(f, "{}", name)?;
473 if let Some(as_of) = as_of {
474 write!(f, "{}", as_of)?
475 }
476 if let Some(alias) = alias {
477 write!(f, " AS {}", alias)?;
478 }
479 Ok(())
480 }
481 TableFactor::Derived {
482 lateral,
483 subquery,
484 alias,
485 } => {
486 if *lateral {
487 write!(f, "LATERAL ")?;
488 }
489 write!(f, "({})", subquery)?;
490 if let Some(alias) = alias {
491 write!(f, " AS {}", alias)?;
492 }
493 Ok(())
494 }
495 TableFactor::TableFunction {
496 name,
497 alias,
498 args,
499 with_ordinality,
500 } => {
501 write!(f, "{}({})", name, display_comma_separated(args))?;
502 if *with_ordinality {
503 write!(f, " WITH ORDINALITY")?;
504 }
505 if let Some(alias) = alias {
506 write!(f, " AS {}", alias)?;
507 }
508 Ok(())
509 }
510 TableFactor::NestedJoin(table_reference) => write!(f, "({})", table_reference),
511 }
512 }
513}
514
515#[derive(Debug, Clone, PartialEq, Eq, Hash)]
516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
517pub struct TableAlias {
518 pub name: Ident,
519 pub columns: Vec<Ident>,
520}
521
522impl fmt::Display for TableAlias {
523 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
524 write!(f, "{}", self.name)?;
525 if !self.columns.is_empty() {
526 write!(f, " ({})", display_comma_separated(&self.columns))?;
527 }
528 Ok(())
529 }
530}
531
532#[derive(Debug, Clone, PartialEq, Eq, Hash)]
533#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
534pub struct Join {
535 pub relation: TableFactor,
536 pub join_operator: JoinOperator,
537}
538
539impl fmt::Display for Join {
540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541 fn prefix(constraint: &JoinConstraint) -> &'static str {
542 match constraint {
543 JoinConstraint::Natural => "NATURAL ",
544 _ => "",
545 }
546 }
547 fn suffix(constraint: &'_ JoinConstraint) -> impl fmt::Display + '_ {
548 struct Suffix<'a>(&'a JoinConstraint);
549 impl fmt::Display for Suffix<'_> {
550 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551 match self.0 {
552 JoinConstraint::On(expr) => write!(f, " ON {}", expr),
553 JoinConstraint::Using(attrs) => {
554 write!(f, " USING({})", display_comma_separated(attrs))
555 }
556 _ => Ok(()),
557 }
558 }
559 }
560 Suffix(constraint)
561 }
562 match &self.join_operator {
563 JoinOperator::Inner(constraint) => write!(
564 f,
565 " {}JOIN {}{}",
566 prefix(constraint),
567 self.relation,
568 suffix(constraint)
569 ),
570 JoinOperator::LeftOuter(constraint) => write!(
571 f,
572 " {}LEFT JOIN {}{}",
573 prefix(constraint),
574 self.relation,
575 suffix(constraint)
576 ),
577 JoinOperator::RightOuter(constraint) => write!(
578 f,
579 " {}RIGHT JOIN {}{}",
580 prefix(constraint),
581 self.relation,
582 suffix(constraint)
583 ),
584 JoinOperator::FullOuter(constraint) => write!(
585 f,
586 " {}FULL JOIN {}{}",
587 prefix(constraint),
588 self.relation,
589 suffix(constraint)
590 ),
591 JoinOperator::CrossJoin => write!(f, " CROSS JOIN {}", self.relation),
592 JoinOperator::AsOfInner(constraint) => write!(
593 f,
594 " {}ASOF JOIN {}{}",
595 prefix(constraint),
596 self.relation,
597 suffix(constraint)
598 ),
599 JoinOperator::AsOfLeft(constraint) => write!(
600 f,
601 " {}ASOF LEFT JOIN {}{}",
602 prefix(constraint),
603 self.relation,
604 suffix(constraint)
605 ),
606 }
607 }
608}
609
610#[derive(Debug, Clone, PartialEq, Eq, Hash)]
611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
612pub enum JoinOperator {
613 Inner(JoinConstraint),
614 LeftOuter(JoinConstraint),
615 RightOuter(JoinConstraint),
616 FullOuter(JoinConstraint),
617 CrossJoin,
618 AsOfInner(JoinConstraint),
619 AsOfLeft(JoinConstraint),
620}
621
622#[derive(Debug, Clone, PartialEq, Eq, Hash)]
623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
624pub enum JoinConstraint {
625 On(Expr),
626 Using(Vec<Ident>),
627 Natural,
628 None,
629}
630
631#[derive(Debug, Clone, PartialEq, Eq, Hash)]
633#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
634pub struct OrderByExpr {
635 pub expr: Expr,
636 pub asc: Option<bool>,
638 pub nulls_first: Option<bool>,
640}
641
642impl fmt::Display for OrderByExpr {
643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644 write!(f, "{}", self.expr)?;
645 match self.asc {
646 Some(true) => write!(f, " ASC")?,
647 Some(false) => write!(f, " DESC")?,
648 None => (),
649 }
650 match self.nulls_first {
651 Some(true) => write!(f, " NULLS FIRST")?,
652 Some(false) => write!(f, " NULLS LAST")?,
653 None => (),
654 }
655 Ok(())
656 }
657}
658
659#[derive(Debug, Clone, PartialEq, Eq, Hash)]
660#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
661pub struct Fetch {
662 pub with_ties: bool,
663 pub quantity: Option<String>,
664}
665
666impl fmt::Display for Fetch {
667 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
668 let extension = if self.with_ties { "WITH TIES" } else { "ONLY" };
669 if let Some(ref quantity) = self.quantity {
670 write!(f, "FETCH FIRST {} ROWS {}", quantity, extension)
671 } else {
672 write!(f, "FETCH FIRST ROWS {}", extension)
673 }
674 }
675}
676
677#[derive(Debug, Clone, PartialEq, Eq, Hash)]
678#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
679pub struct Top {
680 pub with_ties: bool,
682 pub percent: bool,
683 pub quantity: Option<Expr>,
684}
685
686impl fmt::Display for Top {
687 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
688 let extension = if self.with_ties { " WITH TIES" } else { "" };
689 if let Some(ref quantity) = self.quantity {
690 let percent = if self.percent { " PERCENT" } else { "" };
691 write!(f, "TOP ({}){}{}", quantity, percent, extension)
692 } else {
693 write!(f, "TOP{}", extension)
694 }
695 }
696}
697
698#[derive(Debug, Clone, PartialEq, Eq, Hash)]
699#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
700pub struct Values(pub Vec<Vec<Expr>>);
701
702impl fmt::Display for Values {
703 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
704 write!(f, "VALUES ")?;
705 let mut delim = "";
706 for row in &self.0 {
707 write!(f, "{}", delim)?;
708 delim = ", ";
709 write!(f, "({})", display_comma_separated(row))?;
710 }
711 Ok(())
712 }
713}
714
715#[derive(Debug, Clone, PartialEq, Eq, Hash)]
717#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
718pub struct NamedWindow {
719 pub name: Ident,
720 pub window_spec: WindowSpec,
721}
722
723impl fmt::Display for NamedWindow {
724 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
725 write!(f, "{} AS ({})", self.name, self.window_spec)
726 }
727}