1
+ //! Join functionality.
2
+
3
+ use super :: { Variable , Relation } ;
4
+
5
+ /// Performs leapfrog join using a list of leapers.
6
+ pub fn leapfrog_into < ' a , Tuple : Ord , Val : Ord +' a , Result : Ord > (
7
+ source : & Variable < Tuple > ,
8
+ leapers : & mut [ & mut LeapFrog < ' a , Tuple , Val > ] ,
9
+ output : & Variable < Result > ,
10
+ mut logic : impl FnMut ( & Tuple , & Val ) ->Result ) {
11
+
12
+ let mut result = Vec :: new ( ) ;
13
+
14
+ for tuple in source. recent . borrow ( ) . iter ( ) {
15
+
16
+ for leaper in leapers. iter_mut ( ) {
17
+ leaper. seek_prefix ( tuple) ;
18
+ }
19
+
20
+ while !leapers. iter ( ) . any ( |l| l. is_empty ( ) ) {
21
+ // for leaper in leapers.iter() { println!("{:?}, {:?}", leaper.peek_val().is_some(), leaper.is_empty()); }
22
+ let val = leapers. iter_mut ( ) . flat_map ( |l| l. peek_val ( ) ) . max ( ) . expect ( "No maximum found" ) ;
23
+ let mut present = true ;
24
+ for leaper in leapers. iter_mut ( ) {
25
+ if !leaper. seek_val ( & val) { present = false ; }
26
+ }
27
+ if present {
28
+ result. push ( logic ( & tuple, & val) ) ;
29
+ }
30
+ }
31
+
32
+ }
33
+
34
+ output. insert ( result. into ( ) ) ;
35
+ }
36
+
37
+ /// Methods to support leapfrog navigation.
38
+ pub trait LeapFrog < ' a , Tuple , Val > {
39
+ /// Sets the cursor for a specific key.
40
+ fn seek_prefix ( & mut self , prefix : & Tuple ) ;
41
+ /// Seeks a specific key and value pair.
42
+ ///
43
+ /// This method positions the cursor just after `val`,
44
+ /// under the assumption that we will not seek for the
45
+ /// same value immediately afterwards.
46
+ fn seek_val ( & mut self , val : & Val ) -> bool ;
47
+ /// Proposes a next value.
48
+ ///
49
+ /// It is not mandatory that this method return a value,
50
+ /// but we will only observe extensions in the union of
51
+ /// peeked values. This allows antijoin implementations
52
+ /// to implement this interface, as long as at least one
53
+ /// normal join participates.
54
+ fn peek_val ( & self ) -> Option < & ' a Val > ;
55
+ /// Indicates no further values available.
56
+ fn is_empty ( & self ) -> bool ;
57
+ }
58
+
59
+ /// Extension method for relations.
60
+ pub trait Leaper < Key : Ord , Val : Ord > {
61
+ /// Extend with `Val` using the elements of the relation.
62
+ fn extend_with < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ( & ' a self , key_func : Func ) -> extend_with:: ExtendWith < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a ;
63
+ /// Extend with `Val` using the complement of the relation.
64
+ fn extend_anti < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ( & ' a self , key_func : Func ) -> extend_anti:: ExtendAnti < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a ;
65
+ /// Extend with any value if tuple is present in relation.
66
+ fn filter_with < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > ( & ' a self , key_func : Func ) -> filter_with:: FilterWith < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a ;
67
+ /// Extend with any value if tuple is absent from relation.
68
+ fn filter_anti < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > ( & ' a self , key_func : Func ) -> filter_anti:: FilterAnti < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a ;
69
+ }
70
+
71
+ impl < Key : Ord , Val : Ord > Leaper < Key , Val > for Relation < ( Key , Val ) > {
72
+ fn extend_with < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ( & ' a self , key_func : Func ) -> extend_with:: ExtendWith < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a {
73
+ extend_with:: ExtendWith :: from ( self , key_func)
74
+ }
75
+ fn extend_anti < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ( & ' a self , key_func : Func ) -> extend_anti:: ExtendAnti < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a {
76
+ extend_anti:: ExtendAnti :: from ( self , key_func)
77
+ }
78
+ fn filter_with < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > ( & ' a self , key_func : Func ) -> filter_with:: FilterWith < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a {
79
+ filter_with:: FilterWith :: from ( self , key_func)
80
+ }
81
+ fn filter_anti < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > ( & ' a self , key_func : Func ) -> filter_anti:: FilterAnti < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a {
82
+ filter_anti:: FilterAnti :: from ( self , key_func)
83
+ }
84
+ }
85
+
86
+ mod extend_with {
87
+
88
+ use super :: { Relation , LeapFrog , gallop} ;
89
+
90
+ /// Wraps a Relation<Tuple> as a leaper.
91
+ pub struct ExtendWith < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > {
92
+ relation : & ' a Relation < ( Key , Val ) > ,
93
+ start : usize ,
94
+ end : usize ,
95
+ key_func : Func ,
96
+ phantom : :: std:: marker:: PhantomData < Tuple > ,
97
+ }
98
+
99
+ impl < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ExtendWith < ' a , Key , Val , Tuple , Func > {
100
+ /// Constructs a ExtendWith from a relation and key and value function.
101
+ pub fn from ( relation : & ' a Relation < ( Key , Val ) > , key_func : Func ) -> Self {
102
+ ExtendWith {
103
+ relation,
104
+ start : 0 ,
105
+ end : 0 ,
106
+ key_func,
107
+ phantom : :: std:: marker:: PhantomData ,
108
+ }
109
+ }
110
+ }
111
+
112
+ impl < ' a , Key : Ord , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > LeapFrog < ' a , Tuple , Val > for ExtendWith < ' a , Key , Val , Tuple , Func > {
113
+ fn seek_prefix ( & mut self , tuple : & Tuple ) {
114
+ let key = ( self . key_func ) ( tuple) ;
115
+ let slice1 = gallop ( & self . relation [ ..] , |x| & x. 0 < & key) ;
116
+ let slice2 = gallop ( slice1, |x| & x. 0 <= & key) ;
117
+ self . start = self . relation . len ( ) - slice1. len ( ) ;
118
+ self . end = self . relation . len ( ) - slice2. len ( ) ;
119
+ assert ! ( self . start <= self . end) ;
120
+ }
121
+ fn seek_val ( & mut self , val : & Val ) -> bool {
122
+ assert ! ( self . start <= self . end) ;
123
+ // Attempt to position the cursor at (key, val).
124
+ if !self . is_empty ( ) {
125
+ let slice = gallop ( & self . relation [ self . start .. self . end ] , |x| & x. 1 < val) ;
126
+ self . start = self . end - slice. len ( ) ;
127
+ }
128
+ // If the cursor is positioned at something that yields `val`, then success.
129
+ if self . peek_val ( ) == Some ( val) {
130
+ self . start += 1 ;
131
+ true
132
+ }
133
+ else {
134
+ false
135
+ }
136
+ }
137
+ fn peek_val ( & self ) -> Option < & ' a Val > {
138
+ assert ! ( self . start <= self . end) ;
139
+ if self . start < self . end {
140
+ Some ( & self . relation [ self . start ] . 1 )
141
+ }
142
+ else {
143
+ None
144
+ }
145
+ }
146
+ fn is_empty ( & self ) -> bool {
147
+ assert ! ( self . start <= self . end) ;
148
+ self . start == self . end
149
+ }
150
+ }
151
+ }
152
+
153
+ mod extend_anti {
154
+
155
+ use super :: { Relation , LeapFrog , gallop} ;
156
+
157
+ /// Wraps a Relation<Tuple> as a leaper.
158
+ pub struct ExtendAnti < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > {
159
+ relation : & ' a Relation < ( Key , Val ) > ,
160
+ start : usize ,
161
+ end : usize ,
162
+ key_func : Func ,
163
+ phantom : :: std:: marker:: PhantomData < Tuple > ,
164
+ }
165
+
166
+ impl < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ExtendAnti < ' a , Key , Val , Tuple , Func > {
167
+ /// Constructs a ExtendWith from a relation and key and value function.
168
+ pub fn from ( relation : & ' a Relation < ( Key , Val ) > , key_func : Func ) -> Self {
169
+ ExtendAnti {
170
+ relation,
171
+ start : 0 ,
172
+ end : 0 ,
173
+ key_func,
174
+ phantom : :: std:: marker:: PhantomData ,
175
+ }
176
+ }
177
+ }
178
+
179
+ impl < ' a , Key : Ord , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > LeapFrog < ' a , Tuple , Val > for ExtendAnti < ' a , Key , Val , Tuple , Func > {
180
+ fn seek_prefix ( & mut self , tuple : & Tuple ) {
181
+ let key = ( self . key_func ) ( tuple) ;
182
+ let slice1 = gallop ( & self . relation [ ..] , |x| & x. 0 < & key) ;
183
+ let slice2 = gallop ( slice1, |x| & x. 0 <= & key) ;
184
+ self . start = self . relation . len ( ) - slice1. len ( ) ;
185
+ self . end = self . relation . len ( ) - slice2. len ( ) ;
186
+ assert ! ( self . start <= self . end) ;
187
+ }
188
+ fn seek_val ( & mut self , val : & Val ) -> bool {
189
+ assert ! ( self . start <= self . end) ;
190
+ // Attempt to position the cursor at (key, val).
191
+ if !self . is_empty ( ) {
192
+ let slice = gallop ( & self . relation [ self . start .. self . end ] , |x| & x. 1 < val) ;
193
+ self . start = self . end - slice. len ( ) ;
194
+ }
195
+ // If the cursor is positioned at something that yields `val`, then success.
196
+ if self . start < self . end && & self . relation [ self . start ] . 1 == val {
197
+ self . start += 1 ;
198
+ false
199
+ }
200
+ else {
201
+ true
202
+ }
203
+ }
204
+ fn peek_val ( & self ) -> Option < & ' a Val > {
205
+ None
206
+ }
207
+ fn is_empty ( & self ) -> bool {
208
+ false
209
+ }
210
+ }
211
+ }
212
+
213
+ mod filter_with {
214
+
215
+ use super :: { Relation , LeapFrog } ;
216
+
217
+ /// Wraps a Relation<Tuple> as a leaper.
218
+ pub struct FilterWith < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > {
219
+ relation : & ' a Relation < ( Key , Val ) > ,
220
+ key_func : Func ,
221
+ found : bool ,
222
+ phantom : :: std:: marker:: PhantomData < Tuple > ,
223
+ }
224
+
225
+ impl < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > FilterWith < ' a , Key , Val , Tuple , Func > {
226
+ /// Constructs a ExtendWith from a relation and key and value function.
227
+ pub fn from ( relation : & ' a Relation < ( Key , Val ) > , key_func : Func ) -> Self {
228
+ FilterWith {
229
+ relation,
230
+ key_func,
231
+ found : false ,
232
+ phantom : :: std:: marker:: PhantomData ,
233
+ }
234
+ }
235
+ }
236
+
237
+ impl < ' a , Key : Ord , Val : Ord +' a , Val2 , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > LeapFrog < ' a , Tuple , Val2 > for FilterWith < ' a , Key , Val , Tuple , Func > {
238
+ fn seek_prefix ( & mut self , tuple : & Tuple ) {
239
+ let key_val = ( self . key_func ) ( tuple) ;
240
+ self . found = self . relation . binary_search ( & key_val) . is_ok ( ) ;
241
+ }
242
+ fn seek_val ( & mut self , _val : & Val2 ) -> bool {
243
+ self . found
244
+ }
245
+ fn peek_val ( & self ) -> Option < & ' a Val2 > {
246
+ None
247
+ }
248
+ fn is_empty ( & self ) -> bool {
249
+ !self . found
250
+ }
251
+ }
252
+ }
253
+
254
+ mod filter_anti {
255
+
256
+ use super :: { Relation , LeapFrog } ;
257
+
258
+ /// Wraps a Relation<Tuple> as a leaper.
259
+ pub struct FilterAnti < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > {
260
+ relation : & ' a Relation < ( Key , Val ) > ,
261
+ key_func : Func ,
262
+ found : bool ,
263
+ phantom : :: std:: marker:: PhantomData < Tuple > ,
264
+ }
265
+
266
+ impl < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > FilterAnti < ' a , Key , Val , Tuple , Func > {
267
+ /// Constructs a ExtendWith from a relation and key and value function.
268
+ pub fn from ( relation : & ' a Relation < ( Key , Val ) > , key_func : Func ) -> Self {
269
+ FilterAnti {
270
+ relation,
271
+ key_func,
272
+ found : false ,
273
+ phantom : :: std:: marker:: PhantomData ,
274
+ }
275
+ }
276
+ }
277
+
278
+ impl < ' a , Key : Ord , Val : Ord +' a , Val2 , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > LeapFrog < ' a , Tuple , Val2 > for FilterAnti < ' a , Key , Val , Tuple , Func > {
279
+ fn seek_prefix ( & mut self , tuple : & Tuple ) {
280
+ let key_val = ( self . key_func ) ( tuple) ;
281
+ self . found = self . relation . binary_search ( & key_val) . is_ok ( ) ;
282
+ }
283
+ fn seek_val ( & mut self , _val : & Val2 ) -> bool {
284
+ !self . found
285
+ }
286
+ fn peek_val ( & self ) -> Option < & ' a Val2 > {
287
+ None
288
+ }
289
+ fn is_empty ( & self ) -> bool {
290
+ self . found
291
+ }
292
+ }
293
+ }
294
+
295
+
296
+ fn gallop < T > ( mut slice : & [ T ] , mut cmp : impl FnMut ( & T ) ->bool ) -> & [ T ] {
297
+ // if empty slice, or already >= element, return
298
+ if slice. len ( ) > 0 && cmp ( & slice[ 0 ] ) {
299
+ let mut step = 1 ;
300
+ while step < slice. len ( ) && cmp ( & slice[ step] ) {
301
+ slice = & slice[ step..] ;
302
+ step = step << 1 ;
303
+ }
304
+
305
+ step = step >> 1 ;
306
+ while step > 0 {
307
+ if step < slice. len ( ) && cmp ( & slice[ step] ) {
308
+ slice = & slice[ step..] ;
309
+ }
310
+ step = step >> 1 ;
311
+ }
312
+
313
+ slice = & slice[ 1 ..] ; // advance one, as we always stayed < value
314
+ }
315
+
316
+ return slice;
317
+ }
0 commit comments