Skip to main content

partiql/sql/
selector.rs

1use std::collections::VecDeque;
2use std::str::FromStr;
3
4use crate::parser;
5use crate::sql::Env;
6use crate::sql::Expr;
7use crate::value::PqlValue;
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum SelectorNode {
11    String(String),
12    Number(i64),
13}
14
15impl Default for SelectorNode {
16    fn default() -> Self {
17        Self::String(String::default())
18    }
19}
20
21impl From<&str> for SelectorNode {
22    fn from(s: &str) -> Self {
23        Self::String(s.to_string())
24    }
25}
26
27impl From<i64> for SelectorNode {
28    fn from(i: i64) -> Self {
29        Self::Number(i)
30    }
31}
32
33impl From<SelectorNode> for String {
34    fn from(node: SelectorNode) -> Self {
35        match node {
36            SelectorNode::String(s) => s,
37            SelectorNode::Number(i) => format!("{}", i),
38        }
39    }
40}
41
42impl SelectorNode {
43    pub fn to_string(&self) -> String {
44        String::from(self.to_owned())
45    }
46}
47
48#[derive(Debug, Default, Clone, PartialEq)]
49pub struct Selector {
50    pub data: VecDeque<SelectorNode>,
51}
52
53impl FromStr for Selector {
54    type Err = anyhow::Error;
55
56    fn from_str(s: &str) -> anyhow::Result<Self> {
57        match parser::expressions::parse_selector(s) {
58            Ok((_, r)) => Ok(r),
59            Err(_err) => anyhow::bail!("failed"),
60        }
61    }
62}
63
64impl From<&[&str]> for Selector {
65    fn from(ss: &[&str]) -> Self {
66        let data = ss
67            .iter()
68            .map(|s| SelectorNode::String(s.to_string()))
69            .collect::<VecDeque<_>>();
70        Self { data }
71    }
72}
73
74impl From<&[String]> for Selector {
75    fn from(ss: &[String]) -> Self {
76        let data = ss
77            .iter()
78            .map(|s| SelectorNode::String(s.to_string()))
79            .collect::<VecDeque<_>>();
80        Self { data }
81    }
82}
83
84impl From<&str> for Selector {
85    fn from(s: &str) -> Self {
86        let data = s
87            .to_string()
88            .split(".")
89            .map(|s| SelectorNode::String(s.to_string()))
90            .collect::<VecDeque<_>>();
91        Self { data }
92    }
93}
94
95impl From<&SelectorNode> for Selector {
96    fn from(node: &SelectorNode) -> Self {
97        Self {
98            data: vec![node]
99                .into_iter()
100                .map(|n| n.to_owned())
101                .collect::<VecDeque<_>>(),
102        }
103    }
104}
105impl From<&[SelectorNode]> for Selector {
106    fn from(nodes: &[SelectorNode]) -> Self {
107        Self {
108            data: nodes
109                .into_iter()
110                .map(|n| n.to_owned())
111                .collect::<VecDeque<_>>(),
112        }
113    }
114}
115
116impl Selector {
117    pub fn last(&self) -> Option<String> {
118        if let Some(last) = self.to_vec().last() {
119            Some(last.to_string())
120        } else {
121            None
122        }
123    }
124
125    pub fn split_first(&self) -> Option<(SelectorNode, Self)> {
126        let mut data = self.data.to_owned();
127
128        if let Some(first) = data.pop_front() {
129            Some((first, Self { data }))
130        } else {
131            None
132        }
133    }
134
135    pub fn split_last(&self) -> Option<(Self, SelectorNode)> {
136        let mut data = self.data.to_owned();
137
138        if let Some(last) = data.pop_back() {
139            Some((Self { data }, last))
140        } else {
141            None
142        }
143    }
144
145    pub fn to_string(&self) -> String {
146        self.data
147            .clone()
148            .into_iter()
149            .map(|node| node.to_string())
150            .collect::<Vec<String>>()
151            .join(".")
152    }
153
154    pub fn to_vec(&self) -> Vec<SelectorNode> {
155        self.data.clone().into_iter().collect::<Vec<SelectorNode>>()
156    }
157
158    pub fn expand_fullpath(&self, env: &Env) -> Self {
159        if let Some((head, tail)) = self.split_first() {
160            let mut selector = Selector::default();
161
162            selector.data.append(
163                &mut env
164                    .expand_fullpath_as_selector(&Selector::from(vec![head].as_slice()))
165                    .data,
166            );
167            selector.data.append(&mut tail.data.to_owned());
168            selector
169        } else {
170            todo!()
171        }
172    }
173
174    pub fn expand_fullpath2(&self, env: &Env) -> Self {
175        env.expand_fullpath_as_selector(&self)
176    }
177
178    pub fn expand_abspath(&self, env: &Env) -> Self {
179        if let Some((head, tail)) = self.split_first() {
180            let mut selector = Selector::default();
181            if head != SelectorNode::default() {
182                selector.data.push_front(SelectorNode::default());
183            }
184
185            selector.data.append(
186                &mut env
187                    .expand_fullpath_as_selector(&Selector::from(vec![head].as_slice()))
188                    .data,
189            );
190            selector.data.append(&mut tail.data.to_owned());
191            selector
192        } else {
193            todo!()
194        }
195    }
196
197    pub fn evaluate(&self, env: &Env) -> Option<PqlValue> {
198        if let Some((head, tail)) = self.expand_fullpath(&env).split_first() {
199            if let Some(expr) = env.get(head.to_string().as_str()) {
200                match expr {
201                    Expr::Value(value) => {
202                        let v = if tail.data.len() > 0 {
203                            value.select_by_selector(&tail)
204                        } else {
205                            Some(value)
206                        };
207                        v
208                    }
209                    Expr::Selector(selector) => {
210                        let s = selector.expand_fullpath(&env);
211                        s.evaluate(&env)
212                    }
213                    Expr::Star => todo!(),
214                    Expr::Func(_) => todo!(),
215                    Expr::Add(_, _) => todo!(),
216                    Expr::Sub(_, _) => todo!(),
217                    Expr::Mul(_, _) => todo!(),
218                    Expr::Div(_, _) => todo!(),
219                    Expr::Rem(_, _) => todo!(),
220                    Expr::Exp(_, _) => todo!(),
221                    Expr::Sql(_) => todo!(),
222                }
223            } else {
224                self.expand_abspath(&env).evaluate(&env)
225            }
226        } else {
227            unreachable!()
228        }
229    }
230}
231
232#[cfg(test)]
233mod tests {
234    use std::str::FromStr;
235
236    use crate::planner::Drain;
237
238    use crate::sql::Env;
239    use crate::sql::Expr;
240    use crate::sql::Field;
241    use crate::sql::Selector;
242    use crate::value::PqlValue;
243
244    fn get_data() -> anyhow::Result<PqlValue> {
245        PqlValue::from_str(
246            r#"
247{
248  'hr': {
249      'employeesNest': <<
250         {
251          'id': 3,
252          'name': 'Bob Smith',
253          'title': null,
254          'projects': [ { 'name': 'AWS Redshift Spectrum querying' },
255                        { 'name': 'AWS Redshift security' },
256                        { 'name': 'AWS Aurora security' }
257                      ]
258          },
259          {
260              'id': 4,
261              'name': 'Susan Smith',
262              'title': 'Dev Mgr',
263              'projects': []
264          },
265          {
266              'id': 6,
267              'name': 'Jane Smith',
268              'title': 'Software Eng 2',
269              'projects': [ { 'name': 'AWS Redshift security' } ]
270          }
271      >>
272    }
273}
274    "#,
275        )
276    }
277
278    #[test]
279    fn test_eval_selector_fullpath() -> anyhow::Result<()> {
280        let env = {
281            let mut env = Env::default();
282            let data = get_data()?;
283            env.insert("", &Expr::Value(data));
284            env
285        };
286
287        let selector = Selector::from_str(".hr.employeesNest.name")?;
288
289        assert_eq!(
290            selector.evaluate(&env),
291            Some(PqlValue::from_str(
292                r#"
293[
294  "Bob Smith",
295  "Susan Smith",
296  "Jane Smith"
297]
298"#
299            )?)
300        );
301        Ok(())
302    }
303
304    #[test]
305    fn test_eval_selector_aliaspath() -> anyhow::Result<()> {
306        let env = {
307            let mut env = Env::default();
308            let data = get_data()?;
309            env.insert("", &Expr::Value(data));
310            let drain = Drain(vec![
311                Field::from_str(r#"hr.employeesNest AS e"#)?,
312                Field::from_str(r#"e.projects AS p"#)?,
313            ]);
314            drain.execute(&mut env);
315            env
316        };
317
318        let selector = Selector::from_str("e.projects")?;
319        assert_eq!(
320            selector.evaluate(&env),
321            Some(PqlValue::from_str(
322                r#"
323[
324  [
325    {
326      "name": "AWS Redshift Spectrum querying"
327    },
328    {
329      "name": "AWS Redshift security"
330    },
331    {
332      "name": "AWS Aurora security"
333    }
334  ],
335  [],
336  [
337    {
338      "name": "AWS Redshift security"
339    }
340  ]
341]
342"#
343            )?)
344        );
345        Ok(())
346    }
347
348    #[test]
349    fn test_eval_selector_aliaspath2() -> anyhow::Result<()> {
350        let env = {
351            let mut env = Env::default();
352            let data = get_data()?;
353            env.insert("", &Expr::Value(data));
354            let drain = Drain(vec![
355                Field::from_str(r#"hr.employeesNest AS e"#)?,
356                Field::from_str(r#"e.projects AS p"#)?,
357            ]);
358            drain.execute(&mut env);
359            env
360        };
361
362        let selector = Selector::from_str("p")?;
363        assert_eq!(
364            selector.evaluate(&env),
365            Some(PqlValue::from_str(
366                r#"
367    [
368      [
369        {
370          "name": "AWS Redshift Spectrum querying"
371        },
372        {
373          "name": "AWS Redshift security"
374        },
375        {
376          "name": "AWS Aurora security"
377        }
378      ],
379      [],
380      [
381        {
382          "name": "AWS Redshift security"
383        }
384      ]
385    ]
386    "#
387            )?)
388        );
389        Ok(())
390    }
391
392    #[test]
393    fn test_eval_selector_num() -> anyhow::Result<()> {
394        let env = {
395            let mut env = Env::default();
396            let data = get_data()?;
397            env.insert("", &Expr::Value(data));
398            let drain = Drain(vec![Field::from_str(r#"3 AS n"#)?]);
399            drain.execute(&mut env);
400            env
401        };
402
403        let selector = Selector::from_str("n")?;
404        assert_eq!(selector.evaluate(&env), Some(PqlValue::from_str("3")?));
405        Ok(())
406    }
407}