mz_transform/
threshold_elision.rs1use itertools::Itertools;
19use mz_expr::MirRelationExpr;
20
21use crate::TransformCtx;
22use crate::analysis::{DerivedBuilder, NonNegative, SubtreeSize};
23
24#[derive(Debug)]
26pub struct ThresholdElision;
27
28impl crate::Transform for ThresholdElision {
29 fn name(&self) -> &'static str {
30 "ThresholdElision"
31 }
32
33 #[mz_ore::instrument(
34 target = "optimizer",
35 level = "debug",
36 fields(path.segment = "threshold_elision")
37 )]
38 fn actually_perform_transform(
39 &self,
40 relation: &mut MirRelationExpr,
41 ctx: &mut TransformCtx,
42 ) -> Result<(), crate::TransformError> {
43 let mut builder = DerivedBuilder::new(ctx.features);
44 builder.require(NonNegative);
45 builder.require(SubtreeSize);
46 let derived = builder.visit(&*relation);
47
48 let mut todo = vec![(&mut *relation, derived.as_view())];
50 while let Some((expr, mut view)) = todo.pop() {
51 if let MirRelationExpr::Threshold { input } = expr {
52 if *view
53 .last_child()
54 .value::<NonNegative>()
55 .expect("NonNegative required")
56 {
57 *expr = input.take_dangerous();
58 view = view.last_child();
59 }
60 }
61 todo.extend(expr.children_mut().rev().zip_eq(view.children_rev()))
62 }
63
64 mz_repr::explain::trace_plan(&*relation);
65 Ok(())
66 }
67}