mz_transform/fusion/
union.rs1use mz_expr::MirRelationExpr;
13use mz_expr::visit::Visit;
14
15#[derive(Debug)]
17pub struct Union;
18
19impl crate::Transform for Union {
20 fn name(&self) -> &'static str {
21 "UnionFusion"
22 }
23
24 #[mz_ore::instrument(
25 target = "optimizer",
26 level = "debug",
27 fields(path.segment = "union")
28 )]
29 fn actually_perform_transform(
30 &self,
31 relation: &mut MirRelationExpr,
32 _: &mut crate::TransformCtx,
33 ) -> Result<(), crate::TransformError> {
34 relation.visit_mut_post(&mut Self::action)?;
35 mz_repr::explain::trace_plan(&*relation);
36 Ok(())
37 }
38}
39
40impl Union {
41 pub fn action(relation: &mut MirRelationExpr) {
47 if let MirRelationExpr::Union { inputs, .. } = relation {
48 let mut list: Vec<MirRelationExpr> = Vec::with_capacity(1 + inputs.len());
49 Self::unfold_unions_into(relation.take_dangerous(), &mut list);
50 *relation = MirRelationExpr::Union {
51 base: Box::new(list.remove(0)),
52 inputs: list,
53 }
54 }
55 }
56
57 fn unfold_unions_into(expr: MirRelationExpr, list: &mut Vec<MirRelationExpr>) {
59 let mut stack = vec![expr];
60 while let Some(expr) = stack.pop() {
61 if let MirRelationExpr::Union { base, inputs } = expr {
62 stack.extend(inputs.into_iter().rev());
63 stack.push(*base);
64 } else {
65 list.push(expr);
66 }
67 }
68 }
69}