1use super::{
4 aggregate, function, visitor::Acceptor, AggregateColumn, Column, Expr, Function, Identifier,
5 Value, Visitor,
6};
7use crate::{
8 namer::{self, FIELD},
9 And, Factor,
10};
11use colored::Colorize;
12use itertools::Itertools;
13use std::{fmt, sync::Arc};
14
15#[derive(Clone, Debug, Hash, PartialEq, Eq)]
20pub enum Split {
21 Map(Map),
22 Reduce(Reduce),
23}
24
25impl Split {
26 pub fn filter(expr: Expr) -> Map {
27 Map::new(vec![], Some(expr), vec![], None)
28 }
29
30 pub fn order_by(expr: Expr, asc: bool) -> Map {
31 Map::new(vec![], None, vec![(expr, asc)], None)
32 }
33
34 pub fn reduce<S: Into<String>>(name: S, aggregate: AggregateColumn) -> Reduce {
35 Reduce::new(vec![(name.into(), aggregate)], vec![], None)
36 }
37
38 pub fn group_by(expr: Expr) -> Reduce {
39 if let Expr::Column(col) = expr {
40 Reduce::new(vec![], vec![col], None)
42 } else {
43 let name = namer::name_from_content(FIELD, &expr);
45 let map = Map::new(vec![(name.clone(), expr)], None, vec![], None);
46 Reduce::new(vec![], vec![name.into()], Some(map))
47 }
48 }
49
50 pub fn into_map(self) -> Map {
51 match self {
52 Split::Map(map) => map,
53 Split::Reduce(reduce) => reduce.into_map(),
54 }
55 }
56
57 pub fn into_reduce(self, aggregate: aggregate::Aggregate) -> Reduce {
58 match self {
59 Split::Map(map) => map.into_reduce(aggregate),
60 Split::Reduce(reduce) => reduce,
61 }
62 }
63
64 pub fn len(&self) -> usize {
65 match self {
66 Split::Map(m) => m.len(),
67 Split::Reduce(r) => r.len(),
68 }
69 }
70
71 pub fn map_last<F: FnOnce(Split) -> Split>(self, f: F) -> Self {
72 match self {
73 Split::Map(m) => m.map_last(f).into(),
74 Split::Reduce(r) => r.map_last(f).into(),
75 }
76 }
77
78 pub fn map_last_map<F: FnOnce(Map) -> Map>(self, f: F) -> Self {
79 match self {
80 Split::Map(m) => m.map_last_map(f).into(),
81 Split::Reduce(r) => r.map_last_map(f).into(),
82 }
83 }
84
85 pub fn map_last_reduce<F: FnOnce(Reduce) -> Reduce>(self, f: F) -> Self {
86 match self {
87 Split::Map(m) => m.map_last_reduce(f).into(),
88 Split::Reduce(r) => r.map_last_reduce(f).into(),
89 }
90 }
91}
92
93impl Default for Split {
94 fn default() -> Self {
95 Split::Reduce(Reduce::default())
96 }
97}
98
99impl fmt::Display for Split {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self {
102 Split::Map(map) => map.fmt(f),
103 Split::Reduce(reduce) => reduce.fmt(f),
104 }
105 }
106}
107
108impl From<Map> for Split {
109 fn from(map: Map) -> Self {
110 Split::Map(map)
111 }
112}
113
114impl From<Reduce> for Split {
115 fn from(reduce: Reduce) -> Self {
116 Split::Reduce(reduce)
117 }
118}
119
120impl And<Split> for Split {
121 type Product = Split;
122
123 fn and(self, other: Split) -> Self::Product {
124 match (self, other) {
125 (Split::Map(s), Split::Map(o)) => s.and(o).into(),
126 (Split::Map(s), Split::Reduce(o)) => s.and(o).into(),
127 (Split::Reduce(s), Split::Map(o)) => s.and(o).into(),
128 (Split::Reduce(s), Split::Reduce(o)) => s.and(o).into(),
129 }
130 }
131}
132
133#[derive(Clone, Default, Debug, Hash, PartialEq, Eq)]
135pub struct Map {
136 pub named_exprs: Vec<(String, Expr)>,
137 pub filter: Option<Expr>,
138 pub order_by: Vec<(Expr, bool)>,
139 pub reduce: Option<Box<Reduce>>,
140}
141
142impl Map {
143 pub fn new(
145 named_exprs: Vec<(String, Expr)>,
146 filter: Option<Expr>,
147 order_by: Vec<(Expr, bool)>,
148 reduce: Option<Reduce>,
149 ) -> Self {
150 Map {
151 named_exprs: named_exprs.into_iter().unique().collect(),
152 filter,
153 order_by: order_by.into_iter().unique().collect(),
154 reduce: reduce.map(Box::new),
155 }
156 }
157
158 pub fn named_exprs(&self) -> &[(String, Expr)] {
159 &self.named_exprs
160 }
161
162 pub fn filter(&self) -> &Option<Expr> {
163 &self.filter
164 }
165
166 pub fn order_by(&self) -> &Vec<(Expr, bool)> {
167 &self.order_by
168 }
169
170 pub fn reduce(&self) -> Option<&Reduce> {
171 self.reduce.as_deref()
172 }
173
174 pub fn into_reduce(self, aggregate: aggregate::Aggregate) -> Reduce {
175 let Map {
176 named_exprs,
177 filter,
178 order_by,
179 reduce,
180 } = self;
181 let (named_aliases, aliased_expr): (Vec<(String, AggregateColumn)>, Vec<(String, Expr)>) =
182 named_exprs
183 .into_iter()
184 .map(|(name, expr)| {
185 let alias = namer::name_from_content(FIELD, &expr);
186 (
187 (name, AggregateColumn::new(aggregate, alias.clone().into())),
188 (alias, expr),
189 )
190 })
191 .unzip();
192 Reduce::new(
193 named_aliases,
194 vec![],
195 Some(Map::new(aliased_expr, filter, order_by, reduce.map(|r| *r))),
196 )
197 }
198
199 pub fn len(&self) -> usize {
200 1 + self.reduce().map_or(0, |r| r.len())
201 }
202
203 pub fn map_last<F: FnOnce(Split) -> Split>(self, f: F) -> Self {
204 match self.reduce {
205 Some(reduce) => Map::new(
206 self.named_exprs,
207 self.filter,
208 self.order_by,
209 Some(reduce.map_last(f)),
210 ),
211 None => {
212 let split = f(self.clone().into());
213 if let Split::Map(map) = split {
214 map
215 } else {
216 self
217 }
218 }
219 }
220 }
221
222 pub fn map_last_map<F: FnOnce(Map) -> Map>(self, f: F) -> Self {
223 match self.reduce {
224 Some(reduce) => match reduce.map {
225 Some(_) => Map::new(
226 self.named_exprs,
227 self.filter,
228 self.order_by,
229 Some(reduce.map_last_map(f)),
230 ),
231 None => f(Map::new(
232 self.named_exprs,
233 self.filter,
234 self.order_by,
235 Some(*reduce),
236 )),
237 },
238 None => f(self),
239 }
240 }
241
242 pub fn map_last_reduce<F: FnOnce(Reduce) -> Reduce>(self, f: F) -> Self {
243 match self.reduce {
244 Some(reduce) => Map::new(
245 self.named_exprs,
246 self.filter,
247 self.order_by,
248 Some(reduce.map_last_reduce(f)),
249 ),
250 None => self,
251 }
252 }
253}
254
255impl fmt::Display for Map {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 let Map {
258 named_exprs,
259 filter,
260 order_by,
261 reduce,
262 } = self;
263 write!(
264 f,
265 "{}\n{}",
266 named_exprs
267 .iter()
268 .map(|(n, e)| format!("{} -> {}", n, e.to_string().yellow()))
269 .chain(
270 filter
271 .into_iter()
272 .map(|e| format!("WHERE -> {}", e.to_string().yellow()))
273 )
274 .chain(
275 order_by
276 .iter()
277 .map(|(e, _)| format!("ORDER BY -> {}", e.to_string().yellow()))
278 )
279 .join("\n"),
280 reduce.as_deref().map_or(String::new(), ToString::to_string),
281 )
282 }
283}
284
285impl And<Self> for Map {
287 type Product = Self;
288
289 fn and(self, other: Self) -> Self::Product {
290 match (self.reduce, other.reduce) {
291 (None, None) => Map::new(
292 self.named_exprs
293 .into_iter()
294 .chain(other.named_exprs)
295 .collect(),
296 self.filter.into_iter().chain(other.filter).last(),
297 self.order_by.into_iter().chain(other.order_by).collect(),
298 None,
299 ),
300 (Some(s), Some(o)) => Map::new(
301 self.named_exprs
302 .into_iter()
303 .chain(other.named_exprs)
304 .collect(),
305 self.filter.into_iter().chain(other.filter).last(),
306 self.order_by.into_iter().chain(other.order_by).collect(),
307 Some(s.and(*o)),
308 ),
309 (None, Some(o)) => {
310 let (reduce, named_exprs) = self.named_exprs.into_iter().fold(
311 (*o, vec![]),
312 |(reduce, mut named_exprs), (name, expr)| {
313 let (reduce, expr) = reduce.and(expr);
314 named_exprs.push((name, expr));
315 (reduce, named_exprs)
316 },
317 );
318 let (reduce, filter) =
319 self.filter
320 .into_iter()
321 .fold((reduce, None), |(reduce, _), expr| {
322 let (reduce, expr) = reduce.and(expr);
323 (reduce, Some(expr))
324 });
325 let (reduce, order_by) = self.order_by.into_iter().fold(
326 (reduce, vec![]),
327 |(reduce, mut order_by), (expr, asc)| {
328 let (reduce, expr) = reduce.and(expr);
329 order_by.push((expr, asc));
330 (reduce, order_by)
331 },
332 );
333 Map::new(
334 named_exprs.into_iter().chain(other.named_exprs).collect(),
335 filter.into_iter().chain(other.filter).last(),
336 order_by.into_iter().chain(other.order_by).collect(),
337 Some(reduce),
338 )
339 }
340 (Some(s), None) => {
341 let (reduce, named_exprs) = other.named_exprs.into_iter().fold(
342 (*s, vec![]),
343 |(reduce, mut named_exprs), (name, expr)| {
344 let (reduce, expr) = reduce.and(expr);
345 named_exprs.push((name, expr));
346 (reduce, named_exprs)
347 },
348 );
349 let (reduce, filter) =
350 other
351 .filter
352 .into_iter()
353 .fold((reduce, None), |(reduce, _), expr| {
354 let (reduce, expr) = reduce.and(expr);
355 (reduce, Some(expr))
356 });
357 let (reduce, order_by) = other.order_by.into_iter().fold(
358 (reduce, vec![]),
359 |(reduce, mut order_by), (expr, asc)| {
360 let (reduce, expr) = reduce.and(expr);
361 order_by.push((expr, asc));
362 (reduce, order_by)
363 },
364 );
365 Map::new(
366 self.named_exprs.into_iter().chain(named_exprs).collect(),
367 self.filter.into_iter().chain(filter).last(),
368 self.order_by.into_iter().chain(order_by).collect(),
369 Some(reduce),
370 )
371 }
372 }
373 }
374}
375
376impl And<Reduce> for Map {
377 type Product = Self;
378
379 fn and(self, other: Reduce) -> Self::Product {
380 self.and(other.into_map())
381 }
382}
383impl And<Expr> for Map {
385 type Product = (Map, Expr);
386
387 fn and(self, expr: Expr) -> Self::Product {
388 let Map {
389 named_exprs,
390 filter,
391 order_by,
392 reduce,
393 } = self;
394 let (reduce, expr) = if let Some(r) = reduce {
396 let (r, expr) = r.and(expr);
397 (Some(r), expr)
398 } else {
399 (None, expr)
400 };
401 let patterns: Vec<(String, Expr)> = expr
403 .columns()
404 .into_iter()
405 .map(|c| {
406 let column = Expr::Column(c.clone());
407 (namer::name_from_content(FIELD, &column), column)
408 })
409 .chain(named_exprs.clone())
410 .unique()
411 .collect();
412 let (expr, matched) = expr.alias(patterns);
414 (
416 Map::new(
417 named_exprs.into_iter().chain(matched).collect(),
418 filter,
419 order_by,
420 reduce,
421 ),
422 expr,
423 )
424 }
425}
426
427#[derive(Clone, Default, Debug, Hash, PartialEq, Eq)]
428pub struct Reduce {
429 pub named_aggregates: Vec<(String, AggregateColumn)>,
430 pub group_by: Vec<Column>,
431 pub map: Option<Box<Map>>,
432}
433
434impl Reduce {
435 pub fn new(
436 named_aggregates: Vec<(String, AggregateColumn)>,
437 group_by: Vec<Column>,
438 map: Option<Map>,
439 ) -> Self {
440 Reduce {
441 named_aggregates: named_aggregates.into_iter().unique().collect(),
442 group_by: group_by.into_iter().unique().collect(),
443 map: map.map(Box::new),
444 }
445 }
446
447 pub fn named_aggregates(&self) -> &[(String, AggregateColumn)] {
448 &self.named_aggregates
449 }
450
451 pub fn group_by(&self) -> &[Column] {
452 &self.group_by
453 }
454
455 pub fn map(&self) -> Option<&Map> {
456 self.map.as_deref()
457 }
458
459 pub fn into_map(self) -> Map {
460 let Reduce {
461 named_aggregates,
462 group_by,
463 map,
464 } = self;
465 let (named_aliases, aliased_expr): (Vec<(String, Expr)>, Vec<(String, AggregateColumn)>) =
466 named_aggregates
467 .into_iter()
468 .map(|(name, aggregate)| {
469 let alias = namer::name_from_content(FIELD, &aggregate);
470 ((name, Expr::col(alias.clone())), (alias.clone(), aggregate))
471 })
472 .unzip();
473 if aliased_expr.is_empty() && group_by.is_empty() {
475 Map::new(named_aliases, None, vec![], None)
476 } else {
477 Map::new(
478 named_aliases,
479 None,
480 vec![],
481 Some(Reduce::new(aliased_expr, group_by, map.map(|m| *m))),
482 )
483 }
484 }
485
486 pub fn len(&self) -> usize {
487 1 + self.map().map_or(0, |m| m.len())
488 }
489
490 pub fn map_last<F: FnOnce(Split) -> Split>(self, f: F) -> Self {
491 match self.map {
492 Some(map) => Reduce::new(self.named_aggregates, self.group_by, Some(map.map_last(f))),
493 None => {
494 let split = f(self.clone().into());
495 if let Split::Reduce(reduce) = split {
496 reduce
497 } else {
498 self
499 }
500 }
501 }
502 }
503
504 pub fn map_last_map<F: FnOnce(Map) -> Map>(self, f: F) -> Self {
505 match self.map {
506 Some(map) => Reduce::new(
507 self.named_aggregates,
508 self.group_by,
509 Some(map.map_last_map(f)),
510 ),
511 None => self,
512 }
513 }
514
515 pub fn map_last_reduce<F: FnOnce(Reduce) -> Reduce>(self, f: F) -> Self {
516 match self.map {
517 Some(map) => match map.reduce {
518 Some(_) => Reduce::new(
519 self.named_aggregates,
520 self.group_by,
521 Some(map.map_last_reduce(f)),
522 ),
523 None => f(Reduce::new(
524 self.named_aggregates,
525 self.group_by,
526 Some(*map),
527 )),
528 },
529 None => f(self),
530 }
531 }
532}
533
534impl fmt::Display for Reduce {
535 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
536 let Reduce {
537 named_aggregates: named_exprs,
538 group_by,
539 map,
540 } = self;
541 write!(
542 f,
543 "{}\n{}",
544 named_exprs
545 .iter()
546 .map(|(n, e)| format!("{} -> {}", n, e.to_string().red()))
547 .chain(
548 group_by
549 .iter()
550 .map(|e| format!("GROUP BY -> {}", e.to_string().red()))
551 )
552 .join("\n"),
553 map.as_deref().map_or(String::new(), ToString::to_string),
554 )
555 }
556}
557
558impl And<Self> for Reduce {
560 type Product = Self;
561
562 fn and(self, other: Self) -> Self::Product {
563 match (self.map, other.map) {
564 (None, None) => Reduce::new(
565 self.named_aggregates
566 .into_iter()
567 .chain(other.named_aggregates)
568 .collect(),
569 self.group_by.into_iter().chain(other.group_by).collect(),
570 None,
571 ),
572 (Some(s), Some(o)) => Reduce::new(
573 self.named_aggregates
574 .into_iter()
575 .chain(other.named_aggregates)
576 .collect(),
577 self.group_by.into_iter().chain(other.group_by).collect(),
578 Some(s.and(*o)),
579 ),
580 (None, Some(o)) => {
581 let (map, named_aggregates) = self.named_aggregates.into_iter().fold(
582 (*o, vec![]),
583 |(map, mut named_aggregates), (name, aggregate)| {
584 let (map, expr) = map.and(Expr::from(aggregate));
585 named_aggregates.push((name, expr.try_into().unwrap()));
586 (map, named_aggregates)
587 },
588 );
589 let (map, group_by) =
590 self.group_by
591 .into_iter()
592 .fold((map, vec![]), |(map, mut group_by), col| {
593 let (map, col) = map.and(Expr::from(col));
594 group_by.push(col.try_into().unwrap());
595 (map, group_by)
596 });
597 Reduce::new(
598 named_aggregates
599 .into_iter()
600 .chain(other.named_aggregates)
601 .collect(),
602 group_by.into_iter().chain(other.group_by).collect(),
603 Some(map),
604 )
605 }
606 (Some(s), None) => {
607 let (map, named_aggregates) = other.named_aggregates.into_iter().fold(
608 (*s, vec![]),
609 |(map, mut named_aggregates), (name, aggregate)| {
610 let (map, expr) = map.and(Expr::from(aggregate));
611 named_aggregates.push((name, expr.try_into().unwrap()));
612 (map, named_aggregates)
613 },
614 );
615 let (map, group_by) =
616 other
617 .group_by
618 .into_iter()
619 .fold((map, vec![]), |(map, mut group_by), col| {
620 let (map, col) = map.and(Expr::from(col));
621 group_by.push(col.try_into().unwrap());
622 (map, group_by)
623 });
624 Reduce::new(
625 self.named_aggregates
626 .into_iter()
627 .chain(named_aggregates)
628 .collect(),
629 self.group_by.into_iter().chain(group_by).collect(),
630 Some(map),
631 )
632 }
633 }
634 }
635}
636
637impl And<Map> for Reduce {
638 type Product = Map;
639
640 fn and(self, other: Map) -> Self::Product {
641 self.into_map().and(other)
642 }
643}
644
645impl And<Expr> for Reduce {
647 type Product = (Reduce, Expr);
648
649 fn and(self, expr: Expr) -> Self::Product {
650 let Reduce {
651 named_aggregates,
652 group_by,
653 map,
654 } = self;
655 let (map, expr) = if let Some(m) = map {
657 let (m, expr) = m.and(expr);
658 (Some(m), expr)
659 } else {
660 (None, expr)
661 };
662 let patterns: Vec<(String, Expr)> = expr
664 .columns()
665 .into_iter()
666 .map(|c| {
667 let column = Expr::Column(c.clone());
668 (namer::name_from_content(FIELD, &column), column)
669 })
670 .chain(
671 group_by
672 .clone()
673 .into_iter()
674 .map(|col| (namer::name_from_content(FIELD, &col), Expr::Column(col))),
675 )
676 .unique()
677 .collect();
678 let (expr, matched) = expr.alias(patterns);
680 let matched: Vec<_> = matched
682 .into_iter()
683 .map(|(n, e)| (n, AggregateColumn::try_from(e).unwrap())) .collect();
685 (
687 Reduce::new(
688 named_aggregates.into_iter().chain(matched).collect(),
689 group_by,
690 map,
691 ),
692 expr,
693 )
694 }
695}
696
697#[derive(Clone, Debug)]
698pub struct SplitVisitor(String);
699
700impl<'a> Visitor<'a, Split> for SplitVisitor {
701 fn column(&self, column: &'a Column) -> Split {
702 Map::new(
703 vec![(self.0.clone(), Expr::Column(column.clone()))],
704 None,
705 vec![],
706 None,
707 )
708 .into()
709 }
710
711 fn value(&self, value: &'a Value) -> Split {
712 Map::new(
713 vec![(self.0.clone(), Expr::Value(value.clone()))],
714 None,
715 vec![],
716 None,
717 )
718 .into()
719 }
720
721 fn function(&self, function: &'a function::Function, arguments: Vec<Split>) -> Split {
722 let arguments: Vec<Map> = arguments.into_iter().map(|s| s.into_map()).collect();
723 let named_exprs: Vec<(String, Expr)> = arguments
724 .iter()
725 .map(|m| m.named_exprs()[0].clone())
726 .collect();
727 let Map {
728 named_exprs: _,
729 filter,
730 order_by,
731 reduce,
732 } = Map::all(arguments);
733 Map::new(
734 vec![(
735 self.0.clone(),
736 Expr::Function(Function::new(
737 function.clone(),
738 named_exprs
739 .into_iter()
740 .filter_map(|(n, e)| (n == self.0).then(|| Arc::new(e)))
741 .collect(),
742 )),
743 )],
744 filter,
745 order_by,
746 reduce.map(|r| *r),
747 )
748 .into()
749 }
750
751 fn aggregate(&self, aggregate: &'a aggregate::Aggregate, argument: Split) -> Split {
752 argument.into_reduce(aggregate.clone()).into()
753 }
754
755 fn structured(&self, fields: Vec<(Identifier, Split)>) -> Split {
756 let (identifiers, fields): (Vec<Identifier>, Vec<Split>) = fields.into_iter().unzip();
757 let Map {
758 named_exprs,
759 filter,
760 order_by,
761 reduce,
762 } = Split::all(fields).into_map();
763 Map::new(
764 vec![(
765 self.0.clone(),
766 Expr::Struct(
767 identifiers
768 .into_iter()
769 .zip(
770 named_exprs
771 .into_iter()
772 .filter_map(|(n, e)| (n == self.0).then(|| Arc::new(e))),
773 )
774 .collect(),
775 ),
776 )],
777 filter,
778 order_by,
779 reduce.map(|r| *r),
780 )
781 .into()
782 }
783}
784
785impl<S: Into<String>> From<(S, Expr)> for Split {
787 fn from((name, expr): (S, Expr)) -> Self {
788 expr.accept(SplitVisitor(name.into()))
789 }
790}
791
792impl<S: Into<String>> FromIterator<(S, Expr)> for Split {
793 fn from_iter<T: IntoIterator<Item = (S, Expr)>>(iter: T) -> Self {
794 Split::all(iter.into_iter().map_into())
795 }
796}
797
798#[cfg(test)]
799mod tests {
800 use super::*;
801
802 #[test]
803 fn test_map() {
804 let map = Map::new(
805 vec![
806 ("a".into(), expr!(cos(x + y))),
807 ("b".into(), expr!(sin(x - y))),
808 ],
809 None,
810 vec![],
811 None,
812 );
813 println!("map = {map}");
814 let map = map.and(Split::filter(expr!(gt(x, 2))));
816 println!("Extended map = {map}");
817 assert_eq!(map.len(), 1);
818 }
819
820 #[test]
821 fn test_reduce() {
822 let reduce = Reduce::new(
823 vec![
824 ("a".into(), expr!(count(x)).try_into().unwrap()),
825 ("b".into(), expr!(sum(y)).try_into().unwrap()),
826 ],
827 vec![],
828 None,
829 );
830 println!("reduce = {reduce}");
831
832 let reduce = reduce.and(Reduce::new(vec![], vec!["z".into()], None));
833 println!("reduce and group by = {}", reduce);
834 assert_eq!(reduce.len(), 1);
835 let map = reduce.clone().into_map();
836 println!("reduce into map = {}", map);
837 assert_eq!(map.len(), 2);
838 }
839
840 #[test]
841 fn test_and_split() {
842 let a = Split::default();
843 println!("a = {a}");
844 println!("a = {a:?}");
845 let b = Split::from(("b", expr!(exp(a))));
846 println!("b = {b}");
847 println!("b = {b:?}");
848 let c = a.and(b);
849 println!("a & b = {}", c);
850 assert_eq!(c.len(), 1);
851 }
852
853 #[test]
854 fn test_split_merge() {
855 let u = Split::from(("u", expr!(sum(cos(x)))));
856 println!("u = {u}");
857 let v = Split::from(("v", expr!(sin(y))));
858 println!("v = {v}");
859 let w = u.and(v);
860 println!("u & v = {}", w);
861 assert_eq!(w.len(), 3);
862 }
863
864 #[test]
865 fn test_split_merge_all() {
866 let u = Split::from(("u", expr!(1)));
867 println!("u = {u}");
868 let v = Split::from(("v", expr!(y)));
869 println!("v = {v}");
870 let w = Split::filter(expr!(lt(x, 5))).into();
871 println!("w = {w}");
872 let fact: Split = Factor::all([u, v, w]);
873 println!("u & v & w = {fact}");
874 if let Split::Map(m) = fact {
875 assert!(m.reduce == None)
876 }
877 }
878
879 #[test]
880 fn test_plus() {
881 println!(
882 "sum = {}",
883 Split::from(("a", expr!(1 + sum(x)))).and(Split::from(("b", expr!(count(y)))))
884 );
885 }
886
887 #[test]
888 fn test_and_expr() {
889 let s = Split::from(("a", expr!(1 + sum(x)))).and(Split::from(("b", expr!(count(1 + y)))));
890 let e = expr!(x);
891 println!("expr = {}", e);
892 if let Split::Map(m) = s {
893 let (m, e) = m.and(e);
894 println!("replaced split = {}", m);
895 println!("replaced expr = {}", e);
896 }
897 }
898
899 #[test]
900 fn test_reduce_and_expr() {
901 let reduce = Reduce::default();
902 println!("reduce = {}", reduce);
903 let (reduce, expr) = reduce.and(expr!(sum(1 + a)));
904 println!("reduce = {}, expr = {}", reduce, expr);
905 }
906
907 #[test]
908 fn test_reduce_and_where() {
909 let reduce = Reduce::new(
910 vec![
911 ("a".into(), expr!(count(x)).try_into().unwrap()),
912 ("b".into(), expr!(sum(y)).try_into().unwrap()),
913 ],
914 vec![],
915 None,
916 );
917 println!("reduce = {}", reduce);
918 let filter: Split = Split::filter(expr!(lt(x, 5)))
919 .into_reduce(aggregate::Aggregate::First)
920 .into();
921 let split: Split = reduce.into();
922 let split = split.and(filter);
923 println!("split = {}", split);
924 }
925
926 #[test]
927 fn test_split_map_reduce_map_expr() {
928 let split = Split::from_iter([
929 ("a", expr!(1 + sum(x))),
930 ("b", expr!(count(1 + y))),
931 ("c", expr!(c)),
932 ]);
933 println!("split = {split}");
934 }
935
936 #[test]
937 fn test_split_map_reduce_map_group_by_expr() {
938 let split = Split::from(("b", expr!(2 * count(1 + y))));
939 let split = split.and(Split::group_by(expr!(x - y)).into());
940 let split = split.and(Split::from(("a", expr!(x - y))));
941 println!("split = {split}");
942 }
943}