qail_core/ast/cmd/
cte.rs

1//! CTE (Common Table Expression) builder methods.
2
3use 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}