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}