1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
use expression::AsExpression; use expression::helper_types::{Eq, EqAny}; use expression::array_comparison::AsInExpression; use helper_types::{FindBy, Filter}; use prelude::*; use super::{Identifiable, HasTable}; use std::borrow::Borrow; use std::hash::Hash; pub trait BelongsTo<Parent> { type ForeignKey: Hash + ::std::cmp::Eq; type ForeignKeyColumn: Column; fn foreign_key(&self) -> Option<&Self::ForeignKey>; fn foreign_key_column() -> Self::ForeignKeyColumn; } pub trait GroupedBy<'a, Parent>: IntoIterator + Sized { fn grouped_by(self, parents: &'a [Parent]) -> Vec<Vec<Self::Item>>; } type Id<T> = <T as Identifiable>::Id; impl<'a, Parent: 'a, Child, Iter> GroupedBy<'a, Parent> for Iter where Iter: IntoIterator<Item=Child>, Child: BelongsTo<Parent>, &'a Parent: Identifiable, Id<&'a Parent>: Borrow<Child::ForeignKey>, { fn grouped_by(self, parents: &'a [Parent]) -> Vec<Vec<Child>> { use std::collections::HashMap; let id_indices: HashMap<_, _> = parents.iter().enumerate().map(|(i, u)| (u.id(), i)).collect(); let mut result = parents.iter().map(|_| Vec::new()).collect::<Vec<_>>(); for child in self { if let Some(index) = child.foreign_key().map(|i| id_indices[i]) { result[index].push(child); } } result } } impl<'a, Parent, Child> BelongingToDsl<&'a Parent> for Child where &'a Parent: Identifiable, Child: HasTable + BelongsTo<Parent>, Id<&'a Parent>: AsExpression<<Child::ForeignKeyColumn as Expression>::SqlType>, <Child as HasTable>::Table: FilterDsl<Eq<Child::ForeignKeyColumn, Id<&'a Parent>>>, { type Output = FindBy< Child::Table, Child::ForeignKeyColumn, Id<&'a Parent>, >; fn belonging_to(parent: &'a Parent) -> Self::Output { Child::table().filter(Child::foreign_key_column().eq(parent.id())) } } impl<'a, Parent, Child> BelongingToDsl<&'a [Parent]> for Child where &'a Parent: Identifiable, Child: HasTable + BelongsTo<Parent>, Vec<Id<&'a Parent>>: AsInExpression<<Child::ForeignKeyColumn as Expression>::SqlType>, <Child as HasTable>::Table: FilterDsl<EqAny<Child::ForeignKeyColumn, Vec<Id<&'a Parent>>>>, { type Output = Filter< Child::Table, EqAny< Child::ForeignKeyColumn, Vec<Id<&'a Parent>>, >, >; fn belonging_to(parents: &'a [Parent]) -> Self::Output { let ids = parents.iter().map(Identifiable::id).collect::<Vec<_>>(); Child::table().filter(Child::foreign_key_column().eq_any(ids)) } } impl<'a, Parent, Child> BelongingToDsl<&'a Vec<Parent>> for Child where Child: BelongingToDsl<&'a [Parent]>, { type Output = Child::Output; fn belonging_to(parents: &'a Vec<Parent>) -> Self::Output { Self::belonging_to(&**parents) } }