1use super::*;
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18pub struct Query {
19 pub ctes: Vec<Cte>,
21 pub body: SetExpr,
23 pub order_by: Vec<OrderByExpr>,
25 pub limit: Option<Expr>,
27 pub offset: Option<Expr>,
29 pub fetch: Option<Fetch>,
31}
32
33impl fmt::Display for Query {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 if !self.ctes.is_empty() {
36 write!(f, "WITH {} ", display_comma_separated(&self.ctes))?;
37 }
38 write!(f, "{}", self.body)?;
39 if !self.order_by.is_empty() {
40 write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
41 }
42 if let Some(ref limit) = self.limit {
43 write!(f, " LIMIT {}", limit)?;
44 }
45 if let Some(ref offset) = self.offset {
46 write!(f, " OFFSET {}", offset)?;
47 }
48 if let Some(ref fetch) = self.fetch {
49 write!(f, " {}", fetch)?;
50 }
51 Ok(())
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Hash)]
58pub enum SetExpr {
59 Select(Box<Select>),
61 Query(Box<Query>),
64 SetOperation {
66 op: SetOperator,
67 all: bool,
68 left: Box<SetExpr>,
69 right: Box<SetExpr>,
70 },
71 Values(Values),
72 ParameterizedValue(Vec<usize>),
73 }
75
76impl fmt::Display for SetExpr {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 match self {
79 SetExpr::Select(s) => write!(f, "{}", s),
80 SetExpr::Query(q) => write!(f, "({})", q),
81 SetExpr::Values(v) => write!(f, "{}", v),
82 SetExpr::SetOperation {
83 left,
84 right,
85 op,
86 all,
87 } => {
88 let all_str = if *all { " ALL" } else { "" };
89 write!(f, "{} {}{} {}", left, op, all_str, right)
90 }
91 SetExpr::ParameterizedValue(params) => write!(
92 f,
93 "VALUES({})",
94 params
95 .iter()
96 .map(|i| format!("${}", i))
97 .collect::<Vec<String>>()
98 .join(", ")
99 ),
100 }
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq, Hash)]
105pub enum SetOperator {
106 Union,
107 Except,
108 Intersect,
109}
110
111impl fmt::Display for SetOperator {
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 f.write_str(match self {
114 SetOperator::Union => "UNION",
115 SetOperator::Except => "EXCEPT",
116 SetOperator::Intersect => "INTERSECT",
117 })
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
125pub struct Select {
126 pub distinct: bool,
127 pub projection: Vec<SelectItem>,
129 pub from: Vec<TableWithJoins>,
131 pub selection: Option<Expr>,
133 pub group_by: Vec<Expr>,
135 pub having: Option<Expr>,
137}
138
139impl fmt::Display for Select {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 write!(
142 f,
143 "SELECT{} {}",
144 if self.distinct { " DISTINCT" } else { "" },
145 display_comma_separated(&self.projection)
146 )?;
147 if !self.from.is_empty() {
148 write!(f, " FROM {}", display_comma_separated(&self.from))?;
149 }
150 if let Some(ref selection) = self.selection {
151 write!(f, " WHERE {}", selection)?;
152 }
153 if !self.group_by.is_empty() {
154 write!(f, " GROUP BY {}", display_comma_separated(&self.group_by))?;
155 }
156 if let Some(ref having) = self.having {
157 write!(f, " HAVING {}", having)?;
158 }
159 Ok(())
160 }
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Hash)]
168pub struct Cte {
169 pub alias: TableAlias,
170 pub query: Query,
171}
172
173impl fmt::Display for Cte {
174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 write!(f, "{} AS ({})", self.alias, self.query)
176 }
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Hash)]
181pub enum SelectItem {
182 UnnamedExpr(Expr),
184 ExprWithAlias { expr: Expr, alias: Ident },
186 QualifiedWildcard(ObjectName),
188 Wildcard,
190}
191
192impl fmt::Display for SelectItem {
193 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194 match &self {
195 SelectItem::UnnamedExpr(expr) => write!(f, "{}", expr),
196 SelectItem::ExprWithAlias { expr, alias } => write!(f, "{} AS {}", expr, alias),
197 SelectItem::QualifiedWildcard(prefix) => write!(f, "{}.*", prefix),
198 SelectItem::Wildcard => write!(f, "*"),
199 }
200 }
201}
202
203#[derive(Debug, Clone, PartialEq, Eq, Hash)]
204pub struct TableWithJoins {
205 pub relation: TableFactor,
206 pub joins: Vec<Join>,
207}
208
209impl fmt::Display for TableWithJoins {
210 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
211 write!(f, "{}", self.relation)?;
212 for join in &self.joins {
213 write!(f, "{}", join)?;
214 }
215 Ok(())
216 }
217}
218
219#[derive(Debug, Clone, PartialEq, Eq, Hash)]
221pub enum TableFactor {
222 Table {
223 name: ObjectName,
224 alias: Option<TableAlias>,
225 args: Vec<Expr>,
229 with_hints: Vec<Expr>,
231 },
232 Derived {
233 lateral: bool,
234 subquery: Box<Query>,
235 alias: Option<TableAlias>,
236 },
237 NestedJoin(Box<TableWithJoins>),
242}
243
244impl fmt::Display for TableFactor {
245 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246 match self {
247 TableFactor::Table {
248 name,
249 alias,
250 args,
251 with_hints,
252 } => {
253 write!(f, "{}", name)?;
254 if !args.is_empty() {
255 write!(f, "({})", display_comma_separated(args))?;
256 }
257 if let Some(alias) = alias {
258 write!(f, " AS {}", alias)?;
259 }
260 if !with_hints.is_empty() {
261 write!(f, " WITH ({})", display_comma_separated(with_hints))?;
262 }
263 Ok(())
264 }
265 TableFactor::Derived {
266 lateral,
267 subquery,
268 alias,
269 } => {
270 if *lateral {
271 write!(f, "LATERAL ")?;
272 }
273 write!(f, "({})", subquery)?;
274 if let Some(alias) = alias {
275 write!(f, " AS {}", alias)?;
276 }
277 Ok(())
278 }
279 TableFactor::NestedJoin(table_reference) => write!(f, "({})", table_reference),
280 }
281 }
282}
283
284#[derive(Debug, Clone, PartialEq, Eq, Hash)]
285pub struct TableAlias {
286 pub name: Ident,
287 pub columns: Vec<Ident>,
288}
289
290impl fmt::Display for TableAlias {
291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292 write!(f, "{}", self.name)?;
293 if !self.columns.is_empty() {
294 write!(f, " ({})", display_comma_separated(&self.columns))?;
295 }
296 Ok(())
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Eq, Hash)]
301pub struct Join {
302 pub relation: TableFactor,
303 pub join_operator: JoinOperator,
304}
305
306impl fmt::Display for Join {
307 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308 fn prefix(constraint: &JoinConstraint) -> &'static str {
309 match constraint {
310 JoinConstraint::Natural => "NATURAL ",
311 _ => "",
312 }
313 }
314 fn suffix(constraint: &JoinConstraint) -> impl fmt::Display + '_ {
315 struct Suffix<'a>(&'a JoinConstraint);
316 impl<'a> fmt::Display for Suffix<'a> {
317 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
318 match self.0 {
319 JoinConstraint::On(expr) => write!(f, " ON {}", expr),
320 JoinConstraint::Using(attrs) => {
321 write!(f, " USING({})", display_comma_separated(attrs))
322 }
323 _ => Ok(()),
324 }
325 }
326 }
327 Suffix(constraint)
328 }
329 match &self.join_operator {
330 JoinOperator::Inner(constraint) => write!(
331 f,
332 " {}JOIN {}{}",
333 prefix(constraint),
334 self.relation,
335 suffix(constraint)
336 ),
337 JoinOperator::LeftOuter(constraint) => write!(
338 f,
339 " {}LEFT JOIN {}{}",
340 prefix(constraint),
341 self.relation,
342 suffix(constraint)
343 ),
344 JoinOperator::RightOuter(constraint) => write!(
345 f,
346 " {}RIGHT JOIN {}{}",
347 prefix(constraint),
348 self.relation,
349 suffix(constraint)
350 ),
351 JoinOperator::FullOuter(constraint) => write!(
352 f,
353 " {}FULL JOIN {}{}",
354 prefix(constraint),
355 self.relation,
356 suffix(constraint)
357 ),
358 JoinOperator::CrossJoin => write!(f, " CROSS JOIN {}", self.relation),
359 JoinOperator::CrossApply => write!(f, " CROSS APPLY {}", self.relation),
360 JoinOperator::OuterApply => write!(f, " OUTER APPLY {}", self.relation),
361 }
362 }
363}
364
365#[derive(Debug, Clone, PartialEq, Eq, Hash)]
366pub enum JoinOperator {
367 Inner(JoinConstraint),
368 LeftOuter(JoinConstraint),
369 RightOuter(JoinConstraint),
370 FullOuter(JoinConstraint),
371 CrossJoin,
372 CrossApply,
374 OuterApply,
376}
377
378#[derive(Debug, Clone, PartialEq, Eq, Hash)]
379pub enum JoinConstraint {
380 On(Expr),
381 Using(Vec<Ident>),
382 Natural,
383}
384
385#[derive(Debug, Clone, PartialEq, Eq, Hash)]
387pub struct OrderByExpr {
388 pub expr: Expr,
389 pub asc: Option<bool>,
390}
391
392impl fmt::Display for OrderByExpr {
393 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
394 match self.asc {
395 Some(true) => write!(f, "{} ASC", self.expr),
396 Some(false) => write!(f, "{} DESC", self.expr),
397 None => write!(f, "{}", self.expr),
398 }
399 }
400}
401
402#[derive(Debug, Clone, PartialEq, Eq, Hash)]
403pub struct Fetch {
404 pub with_ties: bool,
405 pub percent: bool,
406 pub quantity: Option<Expr>,
407}
408
409impl fmt::Display for Fetch {
410 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
411 let extension = if self.with_ties { "WITH TIES" } else { "ONLY" };
412 if let Some(ref quantity) = self.quantity {
413 let percent = if self.percent { " PERCENT" } else { "" };
414 write!(f, "FETCH FIRST {}{} ROWS {}", quantity, percent, extension)
415 } else {
416 write!(f, "FETCH FIRST ROWS {}", extension)
417 }
418 }
419}
420
421#[derive(Debug, Clone, PartialEq, Eq, Hash)]
422pub struct Values(pub Vec<Vec<Expr>>);
423
424impl fmt::Display for Values {
425 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426 write!(f, "VALUES ")?;
427 let mut delim = "";
428 for row in &self.0 {
429 write!(f, "{}", delim)?;
430 delim = ", ";
431 write!(f, "({})", display_comma_separated(row))?;
432 }
433 Ok(())
434 }
435}