1
1
//! Join functionality.
2
2
3
3
use super :: { Relation , Variable } ;
4
-
5
- pub fn join_into < Key : Ord , Val1 : Ord , Val2 : Ord , Result : Ord > (
4
+ use std:: cell:: Ref ;
5
+ use std:: ops:: Deref ;
6
+
7
+ /// Implements `join`. Note that `input1` must be a variable, but
8
+ /// `input2` can be either a variable or a relation. This is necessary
9
+ /// because relations have no "recent" tuples, so the fn would be a
10
+ /// guaranteed no-op if both arguments were relations. See also
11
+ /// `join_into_relation`.
12
+ pub ( crate ) fn join_into < ' me , Key : Ord , Val1 : Ord , Val2 : Ord , Result : Ord > (
6
13
input1 : & Variable < ( Key , Val1 ) > ,
7
- input2 : & Variable < ( Key , Val2 ) > ,
14
+ input2 : impl JoinInput < ' me , ( Key , Val2 ) > ,
8
15
output : & Variable < Result > ,
9
16
mut logic : impl FnMut ( & Key , & Val1 , & Val2 ) -> Result ,
10
17
) {
11
18
let mut results = Vec :: new ( ) ;
12
19
13
- let recent1 = input1. recent . borrow ( ) ;
14
- let recent2 = input2. recent . borrow ( ) ;
20
+ let recent1 = input1. recent ( ) ;
21
+ let recent2 = input2. recent ( ) ;
15
22
16
23
{
17
24
// scoped to let `closure` drop borrow of `results`.
18
25
19
26
let mut closure = |k : & Key , v1 : & Val1 , v2 : & Val2 | results. push ( logic ( k, v1, v2) ) ;
20
27
21
- for batch2 in input2. stable . borrow ( ) . iter ( ) {
28
+ for batch2 in input2. stable ( ) . iter ( ) {
22
29
join_helper ( & recent1, & batch2, & mut closure) ;
23
30
}
24
31
25
- for batch1 in input1. stable . borrow ( ) . iter ( ) {
32
+ for batch1 in input1. stable ( ) . iter ( ) {
26
33
join_helper ( & batch1, & recent2, & mut closure) ;
27
34
}
28
35
@@ -32,18 +39,31 @@ pub fn join_into<Key: Ord, Val1: Ord, Val2: Ord, Result: Ord>(
32
39
output. insert ( Relation :: from_vec ( results) ) ;
33
40
}
34
41
42
+ /// Join, but for two relations.
43
+ pub ( crate ) fn join_into_relation < ' me , Key : Ord , Val1 : Ord , Val2 : Ord , Result : Ord > (
44
+ input1 : & Relation < ( Key , Val1 ) > ,
45
+ input2 : & Relation < ( Key , Val2 ) > ,
46
+ mut logic : impl FnMut ( & Key , & Val1 , & Val2 ) -> Result ,
47
+ ) -> Relation < Result > {
48
+ let mut results = Vec :: new ( ) ;
49
+
50
+ join_helper ( & input1. elements , & input2. elements , |k, v1, v2| {
51
+ results. push ( logic ( k, v1, v2) ) ;
52
+ } ) ;
53
+
54
+ Relation :: from_vec ( results)
55
+ }
56
+
35
57
/// Moves all recent tuples from `input1` that are not present in `input2` into `output`.
36
- pub fn antijoin_into < Key : Ord , Val : Ord , Result : Ord > (
37
- input1 : & Variable < ( Key , Val ) > ,
58
+ pub ( crate ) fn antijoin < ' me , Key : Ord , Val : Ord , Result : Ord > (
59
+ input1 : impl JoinInput < ' me , ( Key , Val ) > ,
38
60
input2 : & Relation < Key > ,
39
- output : & Variable < Result > ,
40
61
mut logic : impl FnMut ( & Key , & Val ) -> Result ,
41
- ) {
62
+ ) -> Relation < Result > {
42
63
let mut tuples2 = & input2[ ..] ;
43
64
44
65
let results = input1
45
- . recent
46
- . borrow ( )
66
+ . recent ( )
47
67
. iter ( )
48
68
. filter ( |( ref key, _) | {
49
69
tuples2 = gallop ( tuples2, |k| k < key) ;
@@ -52,7 +72,7 @@ pub fn antijoin_into<Key: Ord, Val: Ord, Result: Ord>(
52
72
. map ( |( ref key, ref val) | logic ( key, val) )
53
73
. collect :: < Vec < _ > > ( ) ;
54
74
55
- output . insert ( Relation :: from_vec ( results) ) ;
75
+ Relation :: from_vec ( results)
56
76
}
57
77
58
78
fn join_helper < K : Ord , V1 , V2 > (
@@ -91,7 +111,7 @@ fn join_helper<K: Ord, V1, V2>(
91
111
}
92
112
}
93
113
94
- pub fn gallop < T > ( mut slice : & [ T ] , mut cmp : impl FnMut ( & T ) -> bool ) -> & [ T ] {
114
+ pub ( crate ) fn gallop < T > ( mut slice : & [ T ] , mut cmp : impl FnMut ( & T ) -> bool ) -> & [ T ] {
95
115
// if empty slice, or already >= element, return
96
116
if !slice. is_empty ( ) && cmp ( & slice[ 0 ] ) {
97
117
let mut step = 1 ;
@@ -113,3 +133,48 @@ pub fn gallop<T>(mut slice: &[T], mut cmp: impl FnMut(&T) -> bool) -> &[T] {
113
133
114
134
slice
115
135
}
136
+
137
+ /// An input that can be used with `from_join`; either a `Variable` or a `Relation`.
138
+ pub trait JoinInput < ' me , Tuple : Ord > : Copy {
139
+ /// If we are on iteration N of the loop, these are the tuples
140
+ /// added on iteration N-1. (For a `Relation`, this is always an
141
+ /// empty slice.)
142
+ type RecentTuples : Deref < Target = [ Tuple ] > ;
143
+
144
+ /// If we are on iteration N of the loop, these are the tuples
145
+ /// added on iteration N - 2 or before. (For a `Relation`, this is
146
+ /// just `self`.)
147
+ type StableTuples : Deref < Target = [ Relation < Tuple > ] > ;
148
+
149
+ /// Get the set of recent tuples.
150
+ fn recent ( self ) -> Self :: RecentTuples ;
151
+
152
+ /// Get the set of stable tuples.
153
+ fn stable ( self ) -> Self :: StableTuples ;
154
+ }
155
+
156
+ impl < ' me , Tuple : Ord > JoinInput < ' me , Tuple > for & ' me Variable < Tuple > {
157
+ type RecentTuples = Ref < ' me , [ Tuple ] > ;
158
+ type StableTuples = Ref < ' me , [ Relation < Tuple > ] > ;
159
+
160
+ fn recent ( self ) -> Self :: RecentTuples {
161
+ Ref :: map ( self . recent . borrow ( ) , |r| & r. elements [ ..] )
162
+ }
163
+
164
+ fn stable ( self ) -> Self :: StableTuples {
165
+ Ref :: map ( self . stable . borrow ( ) , |v| & v[ ..] )
166
+ }
167
+ }
168
+
169
+ impl < ' me , Tuple : Ord > JoinInput < ' me , Tuple > for & ' me Relation < Tuple > {
170
+ type RecentTuples = & ' me [ Tuple ] ;
171
+ type StableTuples = & ' me [ Relation < Tuple > ] ;
172
+
173
+ fn recent ( self ) -> Self :: RecentTuples {
174
+ & [ ]
175
+ }
176
+
177
+ fn stable ( self ) -> Self :: StableTuples {
178
+ std:: slice:: from_ref ( self )
179
+ }
180
+ }
0 commit comments