mz_transform/analysis/
monotonic.rs1use std::collections::BTreeSet;
16
17use mz_expr::{Id, MirRelationExpr};
18use mz_repr::GlobalId;
19
20use crate::analysis::common_lattice::BoolLattice;
21use crate::analysis::{Analysis, Derived, Lattice};
22
23#[derive(Debug)]
25pub struct Monotonic {
26 global_monotonic_ids: BTreeSet<GlobalId>,
27}
28
29impl Monotonic {
30 pub fn new(global_monotonic_ids: BTreeSet<GlobalId>) -> Self {
32 Self {
33 global_monotonic_ids,
34 }
35 }
36
37 #[inline]
38 fn has_monotonic_children(
39 expr: &MirRelationExpr,
40 index: usize,
41 results: &[bool],
42 depends: &Derived,
43 ) -> bool {
44 depends
45 .children_of_rev(index, expr.children().count())
46 .fold(true, |acc, child| acc && results[child])
47 }
48}
49
50impl Analysis for Monotonic {
51 type Value = bool;
52
53 fn derive(
54 &self,
55 expr: &MirRelationExpr,
56 index: usize,
57 results: &[Self::Value],
58 depends: &Derived,
59 ) -> Self::Value {
60 use Id::*;
61 match expr {
62 MirRelationExpr::Get { id: Global(id), .. } => self.global_monotonic_ids.contains(id),
63 MirRelationExpr::Get { id: Local(id), .. } => {
64 let index = *depends
65 .bindings()
66 .get(id)
67 .expect("Dependency info not found");
68 *results.get(index).unwrap_or(&false)
69 }
70 MirRelationExpr::Project { .. }
72 | MirRelationExpr::Map { .. }
73 | MirRelationExpr::ArrangeBy { .. }
74 | MirRelationExpr::Threshold { .. }
75 | MirRelationExpr::Let { .. }
76 | MirRelationExpr::LetRec { .. } => results[index - 1],
77 MirRelationExpr::Union { .. } | MirRelationExpr::Join { .. } => {
79 Self::has_monotonic_children(expr, index, results, depends)
80 }
81 MirRelationExpr::TopK { .. } => false,
84 MirRelationExpr::Negate { .. } => false,
85 MirRelationExpr::Filter { predicates, .. } => {
86 let is_monotonic = results[index - 1];
87 is_monotonic && !predicates.iter().any(|p| p.contains_temporal())
92 }
93 MirRelationExpr::Reduce { aggregates, .. } => {
94 results[index - 1] && aggregates.is_empty()
97 }
98 MirRelationExpr::FlatMap { func, .. } => {
99 results[index - 1] && func.preserves_monotonicity()
100 }
101 MirRelationExpr::Constant { rows: Ok(rows), .. } => {
102 rows.iter().all(|(_, diff)| diff.is_positive())
103 }
104 MirRelationExpr::Constant { rows: Err(_), .. } => false,
106 }
107 }
108
109 fn lattice() -> Option<Box<dyn Lattice<Self::Value>>> {
110 Some(Box::new(BoolLattice))
111 }
112}