mz_compute/render/
threshold.rs1use differential_dataflow::operators::arrange::Arranged;
15use differential_dataflow::trace::Cursor;
16use differential_dataflow::trace::cursor::BatchCursor;
17use mz_compute_types::plan::scalar::LirScalarExpr;
18use mz_compute_types::plan::threshold::{BasicThresholdPlan, ThresholdPlan};
19use mz_repr::{Diff, Row, Timestamp};
20use mz_row_spine::{DatumSeq, RowRowBuilder};
21
22use crate::extensions::arrange::{KeyCollection, MzArrange};
23use crate::extensions::reduce::MzReduce;
24use crate::render::RenderTimestamp;
25use crate::render::context::{ArrangementFlavor, CollectionBundle, Context};
26use crate::typedefs::{ErrBatcher, RowRowAgent, RowRowEnter, RowRowSpine};
27
28fn threshold_local<'scope, T: RenderTimestamp>(
34 arrangement: Arranged<'scope, RowRowAgent<T, Diff>>,
35 name: &str,
36) -> Arranged<'scope, RowRowAgent<T, Diff>> {
37 arrangement.mz_reduce_abelian::<_, RowRowBuilder<_, _>, RowRowSpine<_, _>, _>(
38 name,
39 move |_key, s, t| {
40 for (record, count) in s.iter() {
41 if count.is_positive() {
42 t.push((
43 <BatchCursor<RowRowSpine<T, Diff>> as Cursor>::owned_val(*record),
44 *count,
45 ));
46 }
47 }
48 },
49 )
50}
51
52fn threshold_trace<'scope, T: RenderTimestamp>(
54 arrangement: Arranged<'scope, RowRowEnter<Timestamp, Diff, T>>,
55 name: &str,
56) -> Arranged<'scope, RowRowAgent<T, Diff>> {
57 let logic = move |_key: DatumSeq<'_>, s: &[(DatumSeq<'_>, Diff)], t: &mut Vec<(Row, Diff)>| {
58 for (record, count) in s.iter() {
59 if count.is_positive() {
60 t.push((
61 <BatchCursor<RowRowSpine<T, Diff>> as Cursor>::owned_val(*record),
62 *count,
63 ));
64 }
65 }
66 };
67 arrangement.mz_reduce_abelian::<_, RowRowBuilder<T, Diff>, RowRowSpine<T, Diff>, _>(name, logic)
68}
69
70pub fn build_threshold_basic<'scope, T: RenderTimestamp>(
75 input: CollectionBundle<'scope, T>,
76 key: Vec<LirScalarExpr>,
77) -> CollectionBundle<'scope, T> {
78 let arrangement = input
79 .arrangement(&key)
80 .expect("Arrangement ensured to exist");
81 match arrangement {
82 ArrangementFlavor::Local(oks, errs) => {
83 let oks = threshold_local(oks, "Threshold local");
84 CollectionBundle::from_expressions(key, ArrangementFlavor::Local(oks, errs))
85 }
86 ArrangementFlavor::Trace(_, oks, errs) => {
87 let oks = threshold_trace(oks, "Threshold trace");
88 let errs: KeyCollection<_, _, _> = errs.as_collection(|k, _| k.clone()).into();
89 let errs = errs.mz_arrange::<ErrBatcher<_, _>, _>("Arrange threshold basic err");
90 CollectionBundle::from_expressions(key, ArrangementFlavor::Local(oks, errs))
91 }
92 }
93}
94
95impl<'scope, T: RenderTimestamp> Context<'scope, T> {
96 pub(crate) fn render_threshold(
97 &self,
98 input: CollectionBundle<'scope, T>,
99 threshold_plan: ThresholdPlan,
100 ) -> CollectionBundle<'scope, T> {
101 match threshold_plan {
102 ThresholdPlan::Basic(BasicThresholdPlan {
103 ensure_arrangement: (key, _, _),
104 }) => {
105 build_threshold_basic(input, key)
109 }
110 }
111 }
112}