1use super::*;
16
17#[derive(Debug, Clone, PartialEq)]
23pub struct CommonTableExpression {
24 pub token: Token,
25 pub name: Identifier,
26 pub column_names: Vec<Identifier>,
27 pub query: Box<SelectStatement>,
28 pub is_recursive: bool,
29}
30
31impl fmt::Display for CommonTableExpression {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 let mut result = self.name.to_string();
34 if !self.column_names.is_empty() {
35 let cols: Vec<String> = self.column_names.iter().map(|c| c.to_string()).collect();
36 result.push_str(&format!("({})", cols.join(", ")));
37 }
38 result.push_str(&format!(" AS ({})", self.query));
39 write!(f, "{}", result)
40 }
41}
42
43#[derive(Debug, Clone, PartialEq)]
45pub struct WithClause {
46 pub token: Token,
47 pub ctes: Vec<CommonTableExpression>,
48 pub is_recursive: bool,
49}
50
51impl fmt::Display for WithClause {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 let mut result = String::from("WITH ");
54 if self.is_recursive {
55 result.push_str("RECURSIVE ");
56 }
57 let cte_strs: Vec<String> = self.ctes.iter().map(|c| c.to_string()).collect();
58 result.push_str(&cte_strs.join(", "));
59 write!(f, "{}", result)
60 }
61}
62
63#[derive(Debug, Clone, PartialEq)]
69pub enum SetOperationType {
70 Union,
71 UnionAll,
72 Intersect,
73 IntersectAll,
74 Except,
75 ExceptAll,
76}
77
78impl fmt::Display for SetOperationType {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 match self {
81 SetOperationType::Union => write!(f, "UNION"),
82 SetOperationType::UnionAll => write!(f, "UNION ALL"),
83 SetOperationType::Intersect => write!(f, "INTERSECT"),
84 SetOperationType::IntersectAll => write!(f, "INTERSECT ALL"),
85 SetOperationType::Except => write!(f, "EXCEPT"),
86 SetOperationType::ExceptAll => write!(f, "EXCEPT ALL"),
87 }
88 }
89}
90
91#[derive(Debug, Clone, PartialEq)]
93pub struct SetOperation {
94 pub operation: SetOperationType,
95 pub right: Box<SelectStatement>,
96}
97
98#[derive(Debug, Clone, PartialEq, Default)]
100pub enum GroupByModifier {
101 #[default]
102 None,
103 Rollup,
104 Cube,
105 GroupingSets(Vec<Vec<Expression>>),
108}
109
110#[derive(Debug, Clone, PartialEq, Default)]
112pub struct GroupByClause {
113 pub columns: Vec<Expression>,
114 pub modifier: GroupByModifier,
115}
116
117impl fmt::Display for GroupByClause {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 if let GroupByModifier::GroupingSets(sets) = &self.modifier {
121 let sets_str: Vec<String> = sets
122 .iter()
123 .map(|set| {
124 let cols: Vec<String> = set.iter().map(|c| c.to_string()).collect();
125 format!("({})", cols.join(", "))
126 })
127 .collect();
128 return write!(f, "GROUPING SETS ({})", sets_str.join(", "));
129 }
130
131 if self.columns.is_empty() {
133 return Ok(());
134 }
135 let cols: Vec<String> = self.columns.iter().map(|c| c.to_string()).collect();
136 match &self.modifier {
137 GroupByModifier::None => write!(f, "{}", cols.join(", ")),
138 GroupByModifier::Rollup => write!(f, "ROLLUP({})", cols.join(", ")),
139 GroupByModifier::Cube => write!(f, "CUBE({})", cols.join(", ")),
140 GroupByModifier::GroupingSets(_) => Ok(()), }
142 }
143}
144
145#[derive(Debug, Clone, PartialEq)]
147pub struct SelectStatement {
148 pub token: Token,
149 pub distinct: bool,
150 pub distinct_on: Vec<Expression>,
152 pub columns: Vec<Expression>,
153 pub with: Option<WithClause>,
154 pub table_expr: Option<Box<Expression>>,
155 pub where_clause: Option<Box<Expression>>,
156 pub group_by: GroupByClause,
157 pub having: Option<Box<Expression>>,
158 pub window_defs: Vec<WindowDefinition>,
160 pub order_by: Vec<OrderByExpression>,
161 pub limit: Option<Box<Expression>>,
162 pub offset: Option<Box<Expression>>,
163 pub set_operations: Vec<SetOperation>,
165}
166
167impl fmt::Display for SelectStatement {
168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169 let mut result = String::new();
170 if let Some(ref with) = self.with {
171 result.push_str(&format!("{} ", with));
172 }
173 result.push_str("SELECT ");
174 if !self.distinct_on.is_empty() {
175 let on_cols: Vec<String> = self.distinct_on.iter().map(|e| e.to_string()).collect();
176 result.push_str(&format!("DISTINCT ON ({}) ", on_cols.join(", ")));
177 } else if self.distinct {
178 result.push_str("DISTINCT ");
179 }
180 let cols: Vec<String> = self.columns.iter().map(|c| c.to_string()).collect();
181 result.push_str(&cols.join(", "));
182 if let Some(ref table) = self.table_expr {
183 result.push_str(&format!(" FROM {}", table));
184 }
185 if let Some(ref where_clause) = self.where_clause {
186 result.push_str(&format!(" WHERE {}", where_clause));
187 }
188 if !self.group_by.columns.is_empty()
189 || matches!(self.group_by.modifier, GroupByModifier::GroupingSets(_))
190 {
191 result.push_str(&format!(" GROUP BY {}", self.group_by));
192 }
193 if let Some(ref having) = self.having {
194 result.push_str(&format!(" HAVING {}", having));
195 }
196 if !self.window_defs.is_empty() {
197 let wins: Vec<String> = self.window_defs.iter().map(|w| w.to_string()).collect();
198 result.push_str(&format!(" WINDOW {}", wins.join(", ")));
199 }
200 for set_op in &self.set_operations {
202 result.push_str(&format!(" {} {}", set_op.operation, set_op.right));
203 }
204 if !self.order_by.is_empty() {
205 let orders: Vec<String> = self.order_by.iter().map(|o| o.to_string()).collect();
206 result.push_str(&format!(" ORDER BY {}", orders.join(", ")));
207 }
208 if let Some(ref limit) = self.limit {
209 result.push_str(&format!(" LIMIT {}", limit));
210 }
211 if let Some(ref offset) = self.offset {
212 result.push_str(&format!(" OFFSET {}", offset));
213 }
214 write!(f, "{}", result)
215 }
216}