1use std::hash::Hash;
10
11use solverforge_core::score::Score;
12
13use super::bi_stream::BiConstraintStream;
14use super::collection_extract::CollectionExtract;
15use super::cross_bi_stream::{
16 Bi, BiPredicatePlan, BiUnaryPlan, ViewComparisonPlan, ViewOverlapPlan,
17};
18use super::filter::{UniBiFilter, UniFilter, UniLeftBiFilter, UniPairFilter};
19use super::joiner::plan::{CompileCondition, ExecutablePlan, IndexedPlan};
20use super::joiner::{
21 AndJoiner, EqualJoiner, GreaterThanJoiner, GreaterThanOrEqualJoiner, LessThanJoiner,
22 LessThanOrEqualJoiner, OverlappingJoiner, Symmetric,
23};
24use super::key_extract::EntityKeyAdapter;
25use super::relational::view_plan::{EntityKey, ViewEqualPlan};
26use super::relational::Leaf;
27use super::UniConstraintStream;
28
29pub trait JoinTarget<S, A, E, F, Sc: Score> {
37 type Output;
39
40 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output;
42}
43
44impl<S, A, E, F, K, KA, Sc> JoinTarget<S, A, E, F, Sc> for EqualJoiner<KA, KA, K, Symmetric>
46where
47 S: Send + Sync + 'static,
48 A: Clone + Hash + PartialEq + Send + Sync + 'static,
49 E: CollectionExtract<S, Item = A>,
50 F: UniFilter<S, A>,
51 K: Eq + Hash + Clone + Send + Sync,
52 KA: Fn(&A) -> K + Send + Sync,
53 Sc: Score + 'static,
54{
55 type Output = BiConstraintStream<S, A, K, E, EntityKeyAdapter<KA>, UniBiFilter<F, A>, Sc>;
56
57 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
58 let (key_fn, _) = self.into_keys();
59 let key_extractor = EntityKeyAdapter::new(key_fn);
60 let bi_filter = UniBiFilter::new(filter_a);
61 BiConstraintStream::new_self_join_with_filter(extractor_a, key_extractor, bi_filter)
62 }
63}
64
65impl<S, A, B, E, F, EB, K, KA, KB, Mode, Sc> JoinTarget<S, A, E, F, Sc>
67 for (EB, EqualJoiner<KA, KB, K, Mode>)
68where
69 S: Send + Sync + 'static,
70 A: Clone + Send + Sync + 'static,
71 B: Clone + Send + Sync + 'static,
72 E: CollectionExtract<S, Item = A>,
73 F: UniFilter<S, A>,
74 EB: CollectionExtract<S, Item = B>,
75 K: Eq + Hash + Clone + Send + Sync,
76 KA: Fn(&A) -> K + Send + Sync,
77 KB: Fn(&B) -> K + Send + Sync,
78 Sc: Score + 'static,
79{
80 type Output = Bi<
81 S,
82 A,
83 B,
84 BiUnaryPlan<K, KA, KB>,
85 super::collection_extract::FilteredExtract<E, F>,
86 EB,
87 super::filter::TrueFilter,
88 Sc,
89 >;
90
91 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
92 let (extractor_b, joiner) = self;
93 let (key_a, key_b) = joiner.into_keys();
94 Bi::from_condition(
95 super::collection_extract::FilteredExtract::new(extractor_a, filter_a),
96 extractor_b,
97 BiUnaryPlan::new(key_a, key_b),
98 super::filter::TrueFilter,
99 )
100 }
101}
102
103macro_rules! impl_comparison_join_target {
104 ($joiner:ident, $less:expr, $inclusive:expr) => {
105 impl<S, A, B, E, F, EB, K, KA, KB, Sc> JoinTarget<S, A, E, F, Sc>
106 for (EB, $joiner<KA, KB, K>)
107 where
108 S: Send + Sync + 'static,
109 A: Clone + Send + Sync + 'static,
110 B: Clone + Send + Sync + 'static,
111 E: CollectionExtract<S, Item = A>,
112 F: UniFilter<S, A>,
113 EB: CollectionExtract<S, Item = B>,
114 K: Ord + Clone + Send + Sync + 'static,
115 KA: Fn(&A) -> K + Send + Sync + 'static,
116 KB: Fn(&B) -> K + Send + Sync + 'static,
117 Sc: Score + 'static,
118 {
119 type Output = Bi<
120 S,
121 A,
122 B,
123 ViewComparisonPlan<K, KA, KB, $less, $inclusive>,
124 E,
125 EB,
126 UniLeftBiFilter<F, B>,
127 Sc,
128 >;
129
130 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
131 let (extractor_b, joiner) = self;
132 let (key_a, key_b) = joiner.into_keys();
133 let bi_filter = UniLeftBiFilter::new(filter_a);
134 Bi::from_condition(
135 extractor_a,
136 extractor_b,
137 ViewComparisonPlan::<K, KA, KB, $less, $inclusive>::new(key_a, key_b),
138 bi_filter,
139 )
140 }
141 }
142 };
143}
144
145impl_comparison_join_target!(LessThanJoiner, true, false);
148impl_comparison_join_target!(LessThanOrEqualJoiner, true, true);
149impl_comparison_join_target!(GreaterThanJoiner, false, false);
150impl_comparison_join_target!(GreaterThanOrEqualJoiner, false, true);
151
152impl<S, A, B, E, F, EB, K, SA, EA, SB, EBd, Sc> JoinTarget<S, A, E, F, Sc>
154 for (EB, OverlappingJoiner<SA, EA, SB, EBd, K>)
155where
156 S: Send + Sync + 'static,
157 A: Clone + Send + Sync + 'static,
158 B: Clone + Send + Sync + 'static,
159 E: CollectionExtract<S, Item = A>,
160 F: UniFilter<S, A>,
161 EB: CollectionExtract<S, Item = B>,
162 K: Ord + Clone + Send + Sync + 'static,
163 SA: Fn(&A) -> K + Send + Sync + 'static,
164 EA: Fn(&A) -> K + Send + Sync + 'static,
165 SB: Fn(&B) -> K + Send + Sync + 'static,
166 EBd: Fn(&B) -> K + Send + Sync + 'static,
167 Sc: Score + 'static,
168{
169 type Output =
170 Bi<S, A, B, ViewOverlapPlan<K, SA, EA, SB, EBd>, E, EB, UniLeftBiFilter<F, B>, Sc>;
171
172 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
173 let (extractor_b, joiner) = self;
174 let (start_a, end_a, start_b, end_b) = joiner.into_bounds();
175 let bi_filter = UniLeftBiFilter::new(filter_a);
176 Bi::from_condition(
177 extractor_a,
178 extractor_b,
179 ViewOverlapPlan::new(start_a, end_a, start_b, end_b),
180 bi_filter,
181 )
182 }
183}
184
185impl<S, A, B, E, F, EB, J1, J2, Sc> JoinTarget<S, A, E, F, Sc> for (EB, AndJoiner<J1, J2>)
188where
189 S: Send + Sync + 'static,
190 A: Clone + Send + Sync + 'static,
191 B: Clone + Send + Sync + 'static,
192 E: CollectionExtract<S, Item = A>,
193 F: UniFilter<S, A>,
194 EB: CollectionExtract<S, Item = B>,
195 J1: ToViewPlan<A, B> + 'static,
196 J2: ToViewPlan<A, B> + 'static,
197 AndJoiner<J1::ViewPlan, J2::ViewPlan>: CompileCondition<Plan: IndexedPlan> + 'static,
198 for<'a> <AndJoiner<J1::ViewPlan, J2::ViewPlan> as CompileCondition>::Plan:
199 ExecutablePlan<Leaf<'a, A>, Leaf<'a, B>>,
200 Sc: Score + 'static,
201{
202 type Output = Bi<
203 S,
204 A,
205 B,
206 <AndJoiner<J1::ViewPlan, J2::ViewPlan> as CompileCondition>::Plan,
207 E,
208 EB,
209 UniLeftBiFilter<F, B>,
210 Sc,
211 >;
212
213 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
214 let (extractor_b, joiner) = self;
215 let (first, second) = joiner.into_parts();
216 let composed = AndJoiner::new(first.into_view_plan(), second.into_view_plan());
217 let bi_filter = UniLeftBiFilter::new(filter_a);
218 Bi::from_condition(extractor_a, extractor_b, composed.compile(), bi_filter)
219 }
220}
221
222impl<S, A, B, E, F, EB, FB, P, Sc> JoinTarget<S, A, E, F, Sc>
227 for (UniConstraintStream<S, B, EB, FB, Sc>, P)
228where
229 S: Send + Sync + 'static,
230 A: Clone + Send + Sync + 'static,
231 B: Clone + Send + Sync + 'static,
232 E: CollectionExtract<S, Item = A>,
233 F: UniFilter<S, A>,
234 EB: CollectionExtract<S, Item = B>,
235 FB: UniFilter<S, B>,
236 P: Fn(&A, &B) -> bool + Send + Sync + 'static,
237 Sc: Score + 'static,
238{
239 type Output = Bi<S, A, B, BiPredicatePlan<P>, E, EB, UniPairFilter<F, FB>, Sc>;
240
241 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
242 let (other_stream, predicate) = self;
243 let (extractor_b, filter_b) = other_stream.into_parts();
244 let combined_filter = UniPairFilter::new(filter_a, filter_b);
245 Bi::from_condition(
246 extractor_a,
247 extractor_b,
248 BiPredicatePlan::new(predicate),
249 combined_filter,
250 )
251 }
252}
253
254pub trait ToViewPlan<A, B> {
259 type ViewPlan;
260 fn into_view_plan(self) -> Self::ViewPlan;
261}
262
263impl<A, B, K, KA, KB, Mode> ToViewPlan<A, B> for EqualJoiner<KA, KB, K, Mode>
264where
265 K: Eq + Hash + Clone,
266 KA: Fn(&A) -> K + Send + Sync,
267 KB: Fn(&B) -> K + Send + Sync,
268{
269 type ViewPlan = ViewEqualPlan<K, EntityKey<KA>, EntityKey<KB>>;
270 fn into_view_plan(self) -> Self::ViewPlan {
271 let (key_a, key_b) = self.into_keys();
272 ViewEqualPlan::new(EntityKey::new(key_a), EntityKey::new(key_b))
273 }
274}
275
276macro_rules! impl_to_view_plan_comparison {
277 ($joiner:ident, $less:expr, $inclusive:expr) => {
278 impl<A, B, K, KA, KB> ToViewPlan<A, B> for $joiner<KA, KB, K>
279 where
280 K: Ord + Clone,
281 KA: Fn(&A) -> K + Send + Sync,
282 KB: Fn(&B) -> K + Send + Sync,
283 {
284 type ViewPlan = ViewComparisonPlan<K, KA, KB, $less, $inclusive>;
285 fn into_view_plan(self) -> Self::ViewPlan {
286 let (key_a, key_b) = self.into_keys();
287 ViewComparisonPlan::new(key_a, key_b)
288 }
289 }
290 };
291}
292impl_to_view_plan_comparison!(LessThanJoiner, true, false);
293impl_to_view_plan_comparison!(LessThanOrEqualJoiner, true, true);
294impl_to_view_plan_comparison!(GreaterThanJoiner, false, false);
295impl_to_view_plan_comparison!(GreaterThanOrEqualJoiner, false, true);
296
297impl<A, B, K, SA, EA, SB, EBd> ToViewPlan<A, B> for OverlappingJoiner<SA, EA, SB, EBd, K>
298where
299 K: Ord + Clone,
300 SA: Fn(&A) -> K + Send + Sync,
301 EA: Fn(&A) -> K + Send + Sync,
302 SB: Fn(&B) -> K + Send + Sync,
303 EBd: Fn(&B) -> K + Send + Sync,
304{
305 type ViewPlan = ViewOverlapPlan<K, SA, EA, SB, EBd>;
306 fn into_view_plan(self) -> Self::ViewPlan {
307 let (start_a, end_a, start_b, end_b) = self.into_bounds();
308 ViewOverlapPlan::new(start_a, end_a, start_b, end_b)
309 }
310}
311
312impl<A, B, J1, J2> ToViewPlan<A, B> for AndJoiner<J1, J2>
313where
314 J1: ToViewPlan<A, B>,
315 J2: ToViewPlan<A, B>,
316{
317 type ViewPlan = AndJoiner<J1::ViewPlan, J2::ViewPlan>;
318 fn into_view_plan(self) -> Self::ViewPlan {
319 let (first, second) = self.into_parts();
320 AndJoiner::new(first.into_view_plan(), second.into_view_plan())
321 }
322}