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            vector: None,
76            score_threshold: None,
77            vector_name: None,
78            with_vector: false,
79            vector_size: None,
80            distance: None,
81            on_disk: None,
82            function_def: None,
83            trigger_def: None,
84            raw_value: None,
85            redis_ttl: None,
86            redis_set_condition: None,
87            ctes: vec![CTEDef {
88                name: cte_name,
89                recursive: false,
90                columns,
91                base_query: Box::new(self),
92                recursive_query: None,
93                source_table: None,
94            }],
95        }
96    }
97
98    pub fn recursive(mut self, recursive_part: Qail) -> Self {
99        if let Some(cte) = self.ctes.last_mut() {
100            cte.recursive = true;
101            cte.recursive_query = Some(Box::new(recursive_part));
102        }
103        self
104    }
105
106    pub fn from_cte(mut self, cte_name: impl Into<String>) -> Self {
107        if let Some(cte) = self.ctes.last_mut() {
108            cte.source_table = Some(cte_name.into());
109        }
110        self
111    }
112
113    pub fn select_from_cte(mut self, columns: &[&str]) -> Self {
114        self.columns = columns.iter().map(|c| Expr::Named(c.to_string())).collect();
115        self
116    }
117
118    pub fn with_cte(mut self, cte: CTEDef) -> Self {
119        self.ctes.push(cte);
120        self
121    }
122}