1use columnation::Columnation;
17use differential_dataflow::Data;
18use differential_dataflow::difference::Abelian;
19use differential_dataflow::operators::arrange::{Arranged, TraceAgent};
20use differential_dataflow::trace::cursor::{BatchCursor, BatchDiff, BatchVal, BatchValOwn};
21use differential_dataflow::trace::implementations::BatchContainer;
22use differential_dataflow::trace::{Builder, Cursor, Navigable, Trace, TraceReader};
23use mz_timely_util::columnation::ColumnationStack;
24use timely::Container;
25use timely::container::PushInto;
26
27use crate::extensions::arrange::ArrangementSize;
28
29pub trait ClearContainer {
30 fn clear(&mut self);
31}
32
33impl<T> ClearContainer for Vec<T> {
34 fn clear(&mut self) {
35 Vec::clear(self)
36 }
37}
38
39impl<D, T, R> ClearContainer for ColumnationStack<(D, T, R)>
40where
41 D: Columnation + Clone + 'static,
42 T: Columnation + Clone + 'static,
43 R: Columnation + Clone + 'static,
44{
45 fn clear(&mut self) {
46 ColumnationStack::clear(self)
47 }
48}
49
50pub(crate) trait MzReduce<'scope, T1: TraceReader> {
52 fn mz_reduce_abelian<L, Bu, T2, KC>(
54 self,
55 name: &str,
56 logic: L,
57 ) -> Arranged<'scope, TraceAgent<T2>>
58 where
59 T1: TraceReader<Batch: Navigable>,
63 KC: BatchContainer,
64 BatchCursor<T1>: Cursor<Time = T1::Time, KeyContainer = KC>,
65 for<'a> BatchCursor<T1>: Cursor<Key<'a> = KC::ReadItem<'a>>,
66 T2: Trace<Batch: Navigable, Time = T1::Time> + 'static,
67 BatchCursor<T2>: Cursor<Time = T2::Time, KeyContainer = KC>,
68 for<'a> BatchCursor<T2>:
69 Cursor<Key<'a> = KC::ReadItem<'a>, ValOwn: Data, Time = T2::Time, Diff: Abelian>,
70 Bu: Builder<Time = T1::Time, Output = T2::Batch> + 'static,
71 Bu::Input: Container
72 + Default
73 + ClearContainer
74 + PushInto<((KC::Owned, BatchValOwn<T2>), T2::Time, BatchDiff<T2>)>,
75 L: FnMut(
76 KC::ReadItem<'_>,
77 &[(BatchVal<'_, T1>, BatchDiff<T1>)],
78 &mut Vec<(BatchValOwn<T2>, BatchDiff<T2>)>,
79 ) + 'static,
80 Arranged<'scope, TraceAgent<T2>>: ArrangementSize;
81}
82
83impl<'scope, T1> MzReduce<'scope, T1> for Arranged<'scope, T1>
84where
85 T1: TraceReader + Clone + 'static,
86{
87 fn mz_reduce_abelian<L, Bu, T2, KC>(
89 self,
90 name: &str,
91 logic: L,
92 ) -> Arranged<'scope, TraceAgent<T2>>
93 where
94 T1: TraceReader<Batch: Navigable>,
95 KC: BatchContainer,
96 BatchCursor<T1>: Cursor<Time = T1::Time, KeyContainer = KC>,
97 for<'a> BatchCursor<T1>: Cursor<Key<'a> = KC::ReadItem<'a>>,
98 T2: Trace<Batch: Navigable, Time = T1::Time> + 'static,
99 BatchCursor<T2>: Cursor<Time = T2::Time, KeyContainer = KC>,
100 for<'a> BatchCursor<T2>:
101 Cursor<Key<'a> = KC::ReadItem<'a>, ValOwn: Data, Time = T2::Time, Diff: Abelian>,
102 Bu: Builder<Time = T1::Time, Output = T2::Batch> + 'static,
103 Bu::Input: Container
104 + Default
105 + ClearContainer
106 + PushInto<((KC::Owned, BatchValOwn<T2>), T2::Time, BatchDiff<T2>)>,
107 L: FnMut(
108 KC::ReadItem<'_>,
109 &[(BatchVal<'_, T1>, BatchDiff<T1>)],
110 &mut Vec<(BatchValOwn<T2>, BatchDiff<T2>)>,
111 ) + 'static,
112 Arranged<'scope, TraceAgent<T2>>: ArrangementSize,
113 {
114 let push_closure =
118 |buf: &mut Bu::Input,
119 key: KC::ReadItem<'_>,
120 updates: &mut Vec<(BatchValOwn<T2>, T2::Time, BatchDiff<T2>)>| {
121 buf.clear();
122 let key_owned = KC::into_owned(key);
123 for (val, time, diff) in updates.drain(..) {
124 buf.push_into(((key_owned.clone(), val), time, diff));
125 }
126 };
127
128 #[allow(clippy::disallowed_methods)]
131 Arranged::<_>::reduce_abelian::<_, Bu, T2, KC, _>(self, name, logic, push_closure)
132 .log_arrangement_size()
133 }
134}