11//! Join functionality.
22
33use 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 > (
613 input1 : & Variable < ( Key , Val1 ) > ,
7- input2 : & Variable < ( Key , Val2 ) > ,
14+ input2 : impl JoinInput < ' me , ( Key , Val2 ) > ,
815 output : & Variable < Result > ,
916 mut logic : impl FnMut ( & Key , & Val1 , & Val2 ) -> Result ,
1017) {
1118 let mut results = Vec :: new ( ) ;
1219
13- let recent1 = input1. recent . borrow ( ) ;
14- let recent2 = input2. recent . borrow ( ) ;
20+ let recent1 = input1. recent ( ) ;
21+ let recent2 = input2. recent ( ) ;
1522
1623 {
1724 // scoped to let `closure` drop borrow of `results`.
1825
1926 let mut closure = |k : & Key , v1 : & Val1 , v2 : & Val2 | results. push ( logic ( k, v1, v2) ) ;
2027
21- for batch2 in input2. stable . borrow ( ) . iter ( ) {
28+ for batch2 in input2. stable ( ) . iter ( ) {
2229 join_helper ( & recent1, & batch2, & mut closure) ;
2330 }
2431
25- for batch1 in input1. stable . borrow ( ) . iter ( ) {
32+ for batch1 in input1. stable ( ) . iter ( ) {
2633 join_helper ( & batch1, & recent2, & mut closure) ;
2734 }
2835
@@ -32,18 +39,31 @@ pub fn join_into<Key: Ord, Val1: Ord, Val2: Ord, Result: Ord>(
3239 output. insert ( Relation :: from_vec ( results) ) ;
3340}
3441
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+
3557/// 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 ) > ,
3860 input2 : & Relation < Key > ,
39- output : & Variable < Result > ,
4061 mut logic : impl FnMut ( & Key , & Val ) -> Result ,
41- ) {
62+ ) -> Relation < Result > {
4263 let mut tuples2 = & input2[ ..] ;
4364
4465 let results = input1
45- . recent
46- . borrow ( )
66+ . recent ( )
4767 . iter ( )
4868 . filter ( |( ref key, _) | {
4969 tuples2 = gallop ( tuples2, |k| k < key) ;
@@ -52,7 +72,7 @@ pub fn antijoin_into<Key: Ord, Val: Ord, Result: Ord>(
5272 . map ( |( ref key, ref val) | logic ( key, val) )
5373 . collect :: < Vec < _ > > ( ) ;
5474
55- output . insert ( Relation :: from_vec ( results) ) ;
75+ Relation :: from_vec ( results)
5676}
5777
5878fn join_helper < K : Ord , V1 , V2 > (
@@ -91,7 +111,7 @@ fn join_helper<K: Ord, V1, V2>(
91111 }
92112}
93113
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 ] {
95115 // if empty slice, or already >= element, return
96116 if !slice. is_empty ( ) && cmp ( & slice[ 0 ] ) {
97117 let mut step = 1 ;
@@ -113,3 +133,48 @@ pub fn gallop<T>(mut slice: &[T], mut cmp: impl FnMut(&T) -> bool) -> &[T] {
113133
114134 slice
115135}
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