1use crate::ast::{Action, CTEDef, Expr, GroupByMode, Qail};
4
5impl Qail {
6 pub fn to_cte(self, name: impl Into<String>) -> CTEDef {
7 let cte_name = name.into();
8 let columns: Vec<String> = self
9 .columns
10 .iter()
11 .filter_map(|c| match c {
12 Expr::Named(n) => Some(n.clone()),
13 Expr::Aliased { alias, .. } => Some(alias.clone()),
14 _ => None,
15 })
16 .collect();
17
18 CTEDef {
19 name: cte_name,
20 recursive: false,
21 columns,
22 base_query: Box::new(self),
23 recursive_query: None,
24 source_table: None,
25 }
26 }
27
28 pub fn with(self, name: impl Into<String>, query: Qail) -> Self {
29 self.with_cte(query.to_cte(name))
30 }
31
32 #[deprecated(
33 since = "0.13.0",
34 note = "Use .to_cte() for reusable CTEDef or .with() for inline CTE"
35 )]
36 pub fn as_cte(self, name: impl Into<String>) -> Self {
37 let cte_name = name.into();
38 let columns: Vec<String> = self
39 .columns
40 .iter()
41 .filter_map(|c| match c {
42 Expr::Named(n) => Some(n.clone()),
43 Expr::Aliased { alias, .. } => Some(alias.clone()),
44 _ => None,
45 })
46 .collect();
47
48 Self {
49 action: Action::With,
50 table: cte_name.clone(),
51 columns: vec![],
52 joins: vec![],
53 cages: vec![],
54 distinct: false,
55 index_def: None,
56 table_constraints: vec![],
57 set_ops: vec![],
58 having: vec![],
59 group_by_mode: GroupByMode::Simple,
60 distinct_on: vec![],
61 returning: None,
62 on_conflict: None,
63 source_query: None,
64 channel: None,
65 payload: None,
66 savepoint_name: None,
67 from_tables: vec![],
68 using_tables: vec![],
69 lock_mode: None,
70 fetch: None,
71 default_values: false,
72 overriding: None,
73 sample: None,
74 only_table: false,
75 ctes: vec![CTEDef {
76 name: cte_name,
77 recursive: false,
78 columns,
79 base_query: Box::new(self),
80 recursive_query: None,
81 source_table: None,
82 }],
83 }
84 }
85
86 pub fn recursive(mut self, recursive_part: Qail) -> Self {
87 if let Some(cte) = self.ctes.last_mut() {
88 cte.recursive = true;
89 cte.recursive_query = Some(Box::new(recursive_part));
90 }
91 self
92 }
93
94 pub fn from_cte(mut self, cte_name: impl Into<String>) -> Self {
95 if let Some(cte) = self.ctes.last_mut() {
96 cte.source_table = Some(cte_name.into());
97 }
98 self
99 }
100
101 pub fn select_from_cte(mut self, columns: &[&str]) -> Self {
102 self.columns = columns.iter().map(|c| Expr::Named(c.to_string())).collect();
103 self
104 }
105
106 pub fn with_cte(mut self, cte: CTEDef) -> Self {
107 self.ctes.push(cte);
108 self
109 }
110}