Skip to main content

partiql/planner/
project.rs

1use collect_mac::collect;
2use indexmap::IndexMap as Map;
3use itertools::Itertools;
4
5use crate::sql::Env;
6use crate::sql::Expr;
7use crate::sql::Field;
8use crate::sql::Selector;
9use crate::value::PqlValue;
10
11#[derive(Debug, Default, Clone)]
12pub struct Projection(pub Vec<Field>);
13
14impl Projection {
15    pub fn execute(self, env: &Env) -> Vec<PqlValue> {
16        let v = self.step12(env);
17        let v = self.step3(v);
18        let v = self.step4(v);
19        v
20    }
21
22    pub fn execute_old(self, data: PqlValue, env: &Env) -> Vec<PqlValue> {
23        let v = self.step1(data, env);
24        let v = self.step2(v);
25        let v = self.step3(v);
26        let v = self.step4(v);
27        v
28    }
29
30    pub fn step1(&self, data: PqlValue, env: &Env) -> PqlValue {
31        let fields = self
32            .0
33            .iter()
34            .map(|field| field.expand_fullpath(&env))
35            .collect::<Vec<Field>>();
36        let projected = data.select_by_fields(&fields, &env).unwrap_or_default();
37        projected
38    }
39
40    pub fn step2(&self, data: PqlValue) -> Rows {
41        Rows::from(data)
42    }
43
44    pub fn step12(&self, env: &Env) -> Rows {
45        let obj = self
46            .0
47            .iter()
48            .map(|field| {
49                let field = field.expand_fullpath(&env);
50                let (alias, expr) = field.rename();
51                let value = expr.eval(env);
52                (alias, value)
53            })
54            .collect::<Map<String, PqlValue>>();
55        Rows::from(PqlValue::Object(obj))
56    }
57
58    pub fn step3(&self, rows: Rows) -> Records {
59        Records::from(rows)
60    }
61
62    pub fn step4(&self, records: Records) -> Vec<PqlValue> {
63        records.into_list()
64    }
65}
66
67impl PqlValue {
68    pub fn project_by_selector(
69        &self,
70        alias: Option<String>,
71        selector: &Selector,
72    ) -> (String, Self) {
73        if let Some(value) = self.select_by_selector(&selector) {
74            let key = alias.clone().unwrap_or({
75                let last = selector.to_vec().last().unwrap().to_string();
76                last
77            });
78            (key, value)
79        } else {
80            dbg!(&selector);
81            todo!()
82        }
83    }
84
85    pub fn select_by_fields(&self, field_list: &[Field], env: &Env) -> Option<Self> {
86        let mut new_map = Map::<String, Self>::new();
87
88        for field in field_list {
89            match &field.expr {
90                Expr::Selector(selector) => {
91                    if let Some(value) = self.select_by_selector(&selector) {
92                        let key = field.alias.clone().unwrap_or({
93                            let last = selector.to_vec().last().unwrap().to_string();
94                            last
95                        });
96                        new_map.insert(key, value);
97                    } else {
98                        dbg!(&selector);
99                        todo!()
100                    }
101                }
102                _ => {
103                    let value = field.to_owned().expr.eval(&env);
104                    let key = field.alias.clone().unwrap_or_default();
105                    new_map.insert(key, value);
106                }
107            }
108        }
109
110        Some(Self::Object(new_map))
111    }
112}
113
114#[derive(Debug, Default, Clone)]
115pub struct Rows {
116    data: Map<String, Vec<PqlValue>>,
117    size: usize,
118    keys: Vec<String>,
119}
120
121impl From<PqlValue> for Rows {
122    fn from(value: PqlValue) -> Self {
123        let mut size = 0;
124
125        let data = match value {
126            PqlValue::Object(record) => record
127                .into_iter()
128                .map(|(key, val)| match val {
129                    PqlValue::Array(array) => {
130                        if size == 0 {
131                            size = array.len();
132                        }
133                        (key, array)
134                    }
135                    _ => {
136                        size = 1;
137                        (key, vec![val])
138                    }
139                })
140                .collect::<Map<String, Vec<PqlValue>>>(),
141            _ => {
142                dbg!(&value);
143                unreachable!()
144            }
145        };
146
147        let keys = data.keys().map(String::from).collect();
148        Self { data, size, keys }
149    }
150}
151
152impl From<Rows> for PqlValue {
153    fn from(records: Rows) -> Self {
154        let array = records
155            .data
156            .into_iter()
157            .map(|(k, v)| {
158                PqlValue::Object(collect! {
159                    as Map<String, PqlValue>:
160                    k => PqlValue::Array(v)
161                })
162            })
163            .collect::<Vec<_>>();
164        PqlValue::Array(array)
165    }
166}
167
168#[derive(Debug, Default, Clone)]
169pub struct Records(pub Vec<Map<String, Vec<PqlValue>>>);
170
171impl From<Rows> for Records {
172    fn from(rows: Rows) -> Self {
173        let records = {
174            let mut records = Vec::<Map<String, Vec<PqlValue>>>::new();
175            for i in 0..rows.size {
176                let mut record = Map::<String, Vec<PqlValue>>::new();
177                for key in &rows.keys {
178                    let v = rows.data.get(key.as_str()).unwrap().get(i).unwrap();
179                    match v {
180                        PqlValue::Array(array) => {
181                            record.insert(key.to_string(), array.to_owned());
182                        }
183                        _ => {
184                            record.insert(key.to_string(), vec![v.to_owned()]);
185                        }
186                    }
187                }
188                records.push(record);
189            }
190            records
191        };
192        Self(records)
193    }
194}
195
196impl From<Records> for PqlValue {
197    fn from(records: Records) -> Self {
198        Self::Array(
199            records
200                .0
201                .into_iter()
202                .map(|obj| {
203                    Self::Object(
204                        obj.into_iter()
205                            .map(|(k, v)| (k, Self::Array(v)))
206                            .collect::<Map<String, _>>(),
207                    )
208                })
209                .collect::<Vec<_>>(),
210        )
211    }
212}
213
214impl Records {
215    pub fn into_list(self) -> Vec<PqlValue> {
216        self.0
217            .into_iter()
218            .map(|record| {
219                let record = record
220                    .into_iter()
221                    .filter_map(|(k, v)| if !v.is_empty() { Some((k, v)) } else { None })
222                    .collect::<Map<String, Vec<PqlValue>>>();
223
224                let keys = record.keys();
225                let it = record.values().into_iter().multi_cartesian_product();
226                it.map(|prod| {
227                    let map = keys
228                        .clone()
229                        .into_iter()
230                        .zip(prod.into_iter())
231                        .map(|(key, p)| (key.to_owned(), p.to_owned()))
232                        .collect::<Map<String, _>>();
233                    let v = PqlValue::Object(map);
234                    v
235                })
236                .collect::<Vec<PqlValue>>()
237            })
238            .flatten()
239            .collect::<Vec<PqlValue>>()
240    }
241}
242
243#[cfg(test)]
244mod tests {
245    use super::Records;
246    use super::Rows;
247    use crate::value::PqlValue;
248    use std::str::FromStr;
249
250    #[test]
251    fn test_convert_coloumnar_to_rowwise() -> anyhow::Result<()> {
252        let form0 = PqlValue::from_str(
253            r#"
254{
255  "projectName": [
256    [
257      "AWS Redshift security",
258      "AWS Aurora security"
259    ],
260    [
261      "AWS Redshift security"
262    ]
263  ],
264  "employeeName": [
265    "Bob Smith",
266    "Jane Smith"
267  ]
268}
269"#,
270        )?;
271        let form1 = PqlValue::from_str(
272            r#"
273[
274  {
275    "projectName": [
276      [
277        "AWS Redshift security",
278        "AWS Aurora security"
279      ],
280      [
281        "AWS Redshift security"
282      ]
283    ]
284  },
285  {
286    "employeeName": [
287      "Bob Smith",
288      "Jane Smith"
289    ]
290  }
291]
292"#,
293        )?;
294        let form2 = PqlValue::from_str(
295            r#"
296[
297  {
298    "projectName": [
299      "AWS Redshift security",
300      "AWS Aurora security"
301    ],
302    "employeeName": [
303      "Bob Smith"
304    ]
305  },
306  {
307    "projectName": [
308      "AWS Redshift security"
309    ],
310    "employeeName": [
311      "Jane Smith"
312    ]
313  }
314]
315"#,
316        )?;
317        let form3 = PqlValue::from_str(
318            r#"
319[
320  {
321    "projectName": "AWS Redshift security",
322    "employeeName": "Bob Smith"
323  },
324  {
325    "projectName": "AWS Aurora security",
326    "employeeName": "Bob Smith"
327  },
328  {
329    "projectName": "AWS Redshift security",
330    "employeeName": "Jane Smith"
331  }
332]
333"#,
334        )?;
335
336        let rows = Rows::from(form0.to_owned());
337        assert_eq!(PqlValue::from(rows.to_owned()), form1);
338
339        let records = Records::from(rows);
340        assert_eq!(PqlValue::from(records.to_owned()), form2);
341
342        let list = records.into_list();
343        assert_eq!(PqlValue::from(list.to_owned()), form3);
344
345        Ok(())
346    }
347}