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 len(&self) -> usize {
118 self.data.len()
119 }
120
121 pub fn get(&self, ith: usize) -> Option<SelectorNode> {
122 self.data.get(ith).map(|e| e.to_owned())
123 }
124
125 pub fn last(&self) -> Option<String> {
126 if let Some(last) = self.to_vec().last() {
127 Some(last.to_string())
128 } else {
129 None
130 }
131 }
132
133 pub fn split_first(&self) -> Option<(SelectorNode, Self)> {
134 let mut data = self.data.to_owned();
135
136 if let Some(first) = data.pop_front() {
137 Some((first, Self { data }))
138 } else {
139 None
140 }
141 }
142
143 pub fn split_last(&self) -> Option<(Self, SelectorNode)> {
144 let mut data = self.data.to_owned();
145
146 if let Some(last) = data.pop_back() {
147 Some((Self { data }, last))
148 } else {
149 None
150 }
151 }
152
153 pub fn to_string(&self) -> String {
154 self.data
155 .clone()
156 .into_iter()
157 .map(|node| node.to_string())
158 .collect::<Vec<String>>()
159 .join(".")
160 }
161
162 pub fn to_vec(&self) -> Vec<SelectorNode> {
163 self.data.clone().into_iter().collect::<Vec<SelectorNode>>()
164 }
165
166 pub fn expand_fullpath(&self, env: &Env) -> Self {
167 if let Some((head, tail)) = self.split_first() {
168 let mut selector = Selector::default();
169
170 selector.data.append(
171 &mut env
172 .expand_fullpath_as_selector(&Selector::from(vec![head].as_slice()))
173 .data,
174 );
175 selector.data.append(&mut tail.data.to_owned());
176 selector
177 } else {
178 todo!()
179 }
180 }
181
182 pub fn expand_fullpath2(&self, env: &Env) -> Self {
183 env.expand_fullpath_as_selector(&self)
184 }
185
186 pub fn expand_abspath(&self, env: &Env) -> Self {
187 if let Some((head, tail)) = self.split_first() {
188 let mut selector = Selector::default();
189 if head != SelectorNode::default() {
190 selector.data.push_front(SelectorNode::default());
191 }
192
193 selector.data.append(
194 &mut env
195 .expand_fullpath_as_selector(&Selector::from(vec![head].as_slice()))
196 .data,
197 );
198 selector.data.append(&mut tail.data.to_owned());
199 selector
200 } else {
201 todo!()
202 }
203 }
204
205 pub fn evaluate(&self, env: &Env) -> Option<PqlValue> {
206 if let Some((head, tail)) = self.expand_fullpath(&env).split_first() {
207 if let Some(expr) = env.get(head.to_string().as_str()) {
208 match expr {
209 Expr::Value(value) => {
210 let v = if tail.data.len() > 0 {
211 value.select_by_selector(&tail)
212 } else {
213 Some(value)
214 };
215 v
216 }
217 Expr::Selector(selector) => {
218 let s = selector.expand_fullpath(&env);
219 s.evaluate(&env)
220 }
221 Expr::Star => todo!(),
222 Expr::Func(_) => todo!(),
223 Expr::Add(_, _) => todo!(),
224 Expr::Sub(_, _) => todo!(),
225 Expr::Mul(_, _) => todo!(),
226 Expr::Div(_, _) => todo!(),
227 Expr::Rem(_, _) => todo!(),
228 Expr::Exp(_, _) => todo!(),
229 Expr::Sql(_) => todo!(),
230 }
231 } else {
232 self.expand_abspath(&env).evaluate(&env)
233 }
234 } else {
235 unreachable!()
236 }
237 }
238
239 pub fn intersect(&self, other: &Selector) -> Selector {
240 let mut res = Selector::default();
241
242 for (a, b) in self.data.iter().zip(other.data.iter()) {
243 if a == b {
244 res.data.push_back(a.to_owned())
245 } else {
246 break;
247 }
248 }
249
250 res
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use std::str::FromStr;
257
258 use crate::planner::Drain;
259
260 use crate::sql::Env;
261 use crate::sql::Expr;
262 use crate::sql::Field;
263 use crate::sql::Selector;
264 use crate::value::PqlValue;
265
266 fn get_data() -> anyhow::Result<PqlValue> {
267 PqlValue::from_str(
268 r#"
269{
270 'hr': {
271 'employeesNest': <<
272 {
273 'id': 3,
274 'name': 'Bob Smith',
275 'title': null,
276 'projects': [ { 'name': 'AWS Redshift Spectrum querying' },
277 { 'name': 'AWS Redshift security' },
278 { 'name': 'AWS Aurora security' }
279 ]
280 },
281 {
282 'id': 4,
283 'name': 'Susan Smith',
284 'title': 'Dev Mgr',
285 'projects': []
286 },
287 {
288 'id': 6,
289 'name': 'Jane Smith',
290 'title': 'Software Eng 2',
291 'projects': [ { 'name': 'AWS Redshift security' } ]
292 }
293 >>
294 }
295}
296 "#,
297 )
298 }
299
300 #[test]
301 fn test_eval_selector_fullpath() -> anyhow::Result<()> {
302 let env = {
303 let mut env = Env::default();
304 let data = get_data()?;
305 env.insert("", &Expr::Value(data));
306 env
307 };
308
309 let selector = Selector::from_str(".hr.employeesNest.name")?;
310
311 assert_eq!(
312 selector.evaluate(&env),
313 Some(PqlValue::from_str(
314 r#"
315[
316 "Bob Smith",
317 "Susan Smith",
318 "Jane Smith"
319]
320"#
321 )?)
322 );
323 Ok(())
324 }
325
326 #[test]
327 fn test_eval_selector_aliaspath() -> anyhow::Result<()> {
328 let env = {
329 let mut env = Env::default();
330 let data = get_data()?;
331 env.insert("", &Expr::Value(data));
332 let drain = Drain(vec![
333 Field::from_str(r#"hr.employeesNest AS e"#)?,
334 Field::from_str(r#"e.projects AS p"#)?,
335 ]);
336 drain.execute(&mut env);
337 env
338 };
339
340 let selector = Selector::from_str("e.projects")?;
341 assert_eq!(
342 selector.evaluate(&env),
343 Some(PqlValue::from_str(
344 r#"
345[
346 [
347 {
348 "name": "AWS Redshift Spectrum querying"
349 },
350 {
351 "name": "AWS Redshift security"
352 },
353 {
354 "name": "AWS Aurora security"
355 }
356 ],
357 [],
358 [
359 {
360 "name": "AWS Redshift security"
361 }
362 ]
363]
364"#
365 )?)
366 );
367 Ok(())
368 }
369
370 #[test]
371 fn test_eval_selector_aliaspath2() -> anyhow::Result<()> {
372 let env = {
373 let mut env = Env::default();
374 let data = get_data()?;
375 env.insert("", &Expr::Value(data));
376 let drain = Drain(vec![
377 Field::from_str(r#"hr.employeesNest AS e"#)?,
378 Field::from_str(r#"e.projects AS p"#)?,
379 ]);
380 drain.execute(&mut env);
381 env
382 };
383
384 let selector = Selector::from_str("p")?;
385 assert_eq!(
386 selector.evaluate(&env),
387 Some(PqlValue::from_str(
388 r#"
389 [
390 [
391 {
392 "name": "AWS Redshift Spectrum querying"
393 },
394 {
395 "name": "AWS Redshift security"
396 },
397 {
398 "name": "AWS Aurora security"
399 }
400 ],
401 [],
402 [
403 {
404 "name": "AWS Redshift security"
405 }
406 ]
407 ]
408 "#
409 )?)
410 );
411 Ok(())
412 }
413
414 #[test]
415 fn test_eval_selector_num() -> anyhow::Result<()> {
416 let env = {
417 let mut env = Env::default();
418 let data = get_data()?;
419 env.insert("", &Expr::Value(data));
420 let drain = Drain(vec![Field::from_str(r#"3 AS n"#)?]);
421 drain.execute(&mut env);
422 env
423 };
424
425 let selector = Selector::from_str("n")?;
426 assert_eq!(selector.evaluate(&env), Some(PqlValue::from_str("3")?));
427 Ok(())
428 }
429
430 #[test]
431 fn test_calculate_common_path() -> anyhow::Result<()> {
432 let abc = Selector::from("a.b.c");
433 let abd = Selector::from("a.b.d");
434
435 let res = abc.intersect(&abd);
436
437 assert_eq!(res, Selector::from("a.b"));
438
439 Ok(())
440 }
441}