Skip to content

Commit 1118b29

Browse files
committed
introduce a "leapjoin trait" for the array
1 parent 1fb106f commit 1118b29

File tree

1 file changed

+40
-15
lines changed

1 file changed

+40
-15
lines changed

src/treefrog.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::Relation;
55
/// Performs treefrog leapjoin using a list of leapers.
66
pub(crate) fn leapjoin<'a, Tuple: Ord, Val: Ord + 'a, Result: Ord>(
77
source: &[Tuple],
8-
leapers: &mut [&mut dyn Leaper<'a, Tuple, Val>],
8+
mut leapers: &mut [&mut dyn Leaper<'a, Tuple, Val>],
99
mut logic: impl FnMut(&Tuple, &Val) -> Result,
1010
) -> Relation<Result> {
1111
let mut result = Vec::new(); // temp output storage.
@@ -15,30 +15,26 @@ pub(crate) fn leapjoin<'a, Tuple: Ord, Val: Ord + 'a, Result: Ord>(
1515
// Determine which leaper would propose the fewest values.
1616
let mut min_index = usize::max_value();
1717
let mut min_count = usize::max_value();
18-
for index in 0..leapers.len() {
19-
let count = leapers[index].count(tuple);
18+
leapers.for_each_count(tuple, |index, count| {
2019
if min_count > count {
2120
min_count = count;
2221
min_index = index;
2322
}
24-
}
23+
});
2524

2625
// We had best have at least one relation restricting values.
2726
assert!(min_count < usize::max_value());
2827

29-
// If there are values to propose ..
28+
// If there are values to propose:
3029
if min_count > 0 {
31-
// Propose them, ..
32-
leapers[min_index].propose(tuple, &mut values);
33-
34-
// Intersect them, ..
35-
for index in 0..leapers.len() {
36-
if index != min_index {
37-
leapers[index].intersect(tuple, &mut values);
38-
}
39-
}
30+
// Push the values that `min_index` "proposes" into `values`.
31+
leapers.propose(tuple, min_index, &mut values);
32+
33+
// Give other leapers a chance to remove values from
34+
// anti-joins or filters.
35+
leapers.intersect(tuple, min_index, &mut values);
4036

41-
// Respond to each of them.
37+
// Push remaining items into result.
4238
for val in values.drain(..) {
4339
result.push(logic(tuple, val));
4440
}
@@ -48,6 +44,35 @@ pub(crate) fn leapjoin<'a, Tuple: Ord, Val: Ord + 'a, Result: Ord>(
4844
Relation::from_vec(result)
4945
}
5046

47+
pub trait Leapers<'a, Tuple, Val> {
48+
fn for_each_count(&mut self, tuple: &Tuple, op: impl FnMut(usize, usize));
49+
50+
fn propose(&mut self, tuple: &Tuple, min_index: usize, values: &mut Vec<&'a Val>);
51+
52+
fn intersect(&mut self, tuple: &Tuple, min_index: usize, values: &mut Vec<&'a Val>);
53+
}
54+
55+
impl<'a, Tuple, Val> Leapers<'a, Tuple, Val> for &mut [&mut dyn Leaper<'a, Tuple, Val>] {
56+
fn for_each_count(&mut self, tuple: &Tuple, mut op: impl FnMut(usize, usize)) {
57+
for (index, leaper) in self.iter_mut().enumerate() {
58+
let count = leaper.count(tuple);
59+
op(index, count);
60+
}
61+
}
62+
63+
fn propose(&mut self, tuple: &Tuple, min_index: usize, values: &mut Vec<&'a Val>) {
64+
self[min_index].propose(tuple, values);
65+
}
66+
67+
fn intersect(&mut self, tuple: &Tuple, min_index: usize, values: &mut Vec<&'a Val>) {
68+
for (index, leaper) in self.iter_mut().enumerate() {
69+
if index != min_index {
70+
leaper.intersect(tuple, values);
71+
}
72+
}
73+
}
74+
}
75+
5176
/// Methods to support treefrog leapjoin.
5277
pub trait Leaper<'a, Tuple, Val> {
5378
/// Estimates the number of proposed values.

0 commit comments

Comments
 (0)