quaint_forked/ast/
union.rs1use crate::ast::{Expression, Query, Select};
2use std::{collections::BTreeSet, fmt};
3
4use super::CommonTableExpression;
5use super::IntoCommonTableExpression;
6
7#[derive(Debug, PartialEq, Clone, Copy)]
8pub(crate) enum UnionType {
9 All,
10 Distinct,
11}
12
13impl fmt::Display for UnionType {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 match self {
16 UnionType::All => write!(f, "UNION ALL"),
17 UnionType::Distinct => write!(f, "UNION"),
18 }
19 }
20}
21
22#[derive(Debug, PartialEq, Clone, Default)]
24pub struct Union<'a> {
25 pub(crate) selects: Vec<Select<'a>>,
26 pub(crate) types: Vec<UnionType>,
27 pub(crate) ctes: Vec<CommonTableExpression<'a>>,
28}
29
30impl<'a> From<Union<'a>> for Query<'a> {
31 fn from(ua: Union<'a>) -> Self {
32 Query::Union(Box::new(ua))
33 }
34}
35
36impl<'a> From<Union<'a>> for Expression<'a> {
37 fn from(uaua: Union<'a>) -> Self {
38 Expression::union(uaua)
39 }
40}
41
42impl<'a> Union<'a> {
43 pub fn new(q: Select<'a>) -> Self {
44 Self {
45 selects: vec![q],
46 types: Vec::new(),
47 ctes: Vec::new(),
48 }
49 }
50
51 pub fn all(mut self, q: Select<'a>) -> Self {
71 self.selects.push(q);
72 self.types.push(UnionType::All);
73 self
74 }
75
76 pub fn distinct(mut self, q: Select<'a>) -> Self {
96 self.selects.push(q);
97 self.types.push(UnionType::Distinct);
98 self
99 }
100
101 pub(crate) fn named_selection(&self) -> Vec<String> {
104 self.selects
105 .iter()
106 .fold(BTreeSet::new(), |mut acc, select| {
107 for name in select.named_selection() {
108 acc.insert(name);
109 }
110
111 acc
112 })
113 .into_iter()
114 .collect()
115 }
116
117 #[cfg(feature = "mssql")]
121 pub(crate) fn convert_tuple_selects_into_ctes(
122 mut self,
123 top_level: bool,
124 level: &mut usize,
125 ) -> either::Either<Self, (Self, Vec<CommonTableExpression<'a>>)> {
126 let mut queries = Vec::with_capacity(self.selects.len());
127 let mut combined_ctes = Vec::new();
128
129 for select in self.selects.drain(0..) {
130 let (select, ctes) = select
131 .convert_tuple_selects_to_ctes(false, level)
132 .expect_right("Nested select should always be right.");
133
134 queries.push(select);
135 combined_ctes.extend(ctes);
136 }
137
138 self.selects = queries;
139
140 if top_level {
141 self.ctes = combined_ctes;
142 either::Either::Left(self)
143 } else {
144 either::Either::Right((self, combined_ctes))
145 }
146 }
147}
148
149impl<'a> IntoCommonTableExpression<'a> for Union<'a> {}