partiql/planner/
project.rs1use 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}