sea_orm/entity/
compound.rs

1#![allow(missing_docs)]
2use super::{ColumnTrait, EntityTrait, PrimaryKeyToColumn, PrimaryKeyTrait};
3use crate::{IntoSimpleExpr, Iterable, QueryFilter, QueryOrder, Related};
4use sea_query::{IntoValueTuple, Order, TableRef};
5
6pub trait EntityLoaderTrait<E: EntityTrait>: QueryFilter + QueryOrder {
7    /// Find a model by primary key
8    fn filter_by_id<T>(mut self, values: T) -> Self
9    where
10        T: Into<<E::PrimaryKey as PrimaryKeyTrait>::ValueType>,
11    {
12        let mut keys = E::PrimaryKey::iter();
13        for v in values.into().into_value_tuple() {
14            if let Some(key) = keys.next() {
15                let col = key.into_column();
16                self.filter_mut(col.eq(v));
17            } else {
18                unreachable!("primary key arity mismatch");
19            }
20        }
21        self
22    }
23
24    /// Apply order by primary key to the query statement
25    fn order_by_id_asc(self) -> Self {
26        self.order_by_id(Order::Asc)
27    }
28
29    /// Apply order by primary key to the query statement
30    fn order_by_id_desc(self) -> Self {
31        self.order_by_id(Order::Desc)
32    }
33
34    /// Apply order by primary key to the query statement
35    fn order_by_id(mut self, order: Order) -> Self {
36        for key in E::PrimaryKey::iter() {
37            let col = key.into_column();
38            <Self as QueryOrder>::query(&mut self)
39                .order_by_expr(col.into_simple_expr(), order.clone());
40        }
41        self
42    }
43}
44
45#[derive(Debug, Clone, PartialEq)]
46pub enum LoadTarget {
47    TableRef(TableRef),
48    Relation(String),
49}
50
51pub trait EntityLoaderWithParam<E: EntityTrait> {
52    fn into_with_param(self) -> (LoadTarget, Option<LoadTarget>);
53}
54
55pub type HasOne<E> = Option<Box<<E as EntityTrait>::ModelEx>>;
56pub type HasMany<E> = Vec<<E as EntityTrait>::ModelEx>;
57
58impl<E, R> EntityLoaderWithParam<E> for R
59where
60    E: EntityTrait,
61    R: EntityTrait,
62    E: Related<R>,
63{
64    fn into_with_param(self) -> (LoadTarget, Option<LoadTarget>) {
65        (LoadTarget::TableRef(self.table_ref()), None)
66    }
67}
68
69impl<E, R, S> EntityLoaderWithParam<E> for (R, S)
70where
71    E: EntityTrait,
72    R: EntityTrait,
73    E: Related<R>,
74    S: EntityTrait,
75    R: Related<S>,
76{
77    fn into_with_param(self) -> (LoadTarget, Option<LoadTarget>) {
78        (
79            LoadTarget::TableRef(self.0.table_ref()),
80            Some(LoadTarget::TableRef(self.1.table_ref())),
81        )
82    }
83}
84
85#[cfg(test)]
86mod test {
87    use crate::ModelTrait;
88    use crate::tests_cfg::cake;
89
90    #[test]
91    fn test_model_ex_convert() {
92        let cake = cake::Model {
93            id: 12,
94            name: "hello".into(),
95        };
96        let cake_ex: cake::ModelEx = cake.clone().into();
97
98        assert_eq!(cake, cake_ex);
99        assert_eq!(cake_ex, cake);
100        assert_eq!(cake.id, cake_ex.id);
101        assert_eq!(cake.name, cake_ex.name);
102
103        assert_eq!(cake_ex.get(cake::Column::Id), 12i32.into());
104        assert_eq!(cake_ex.get(cake::Column::Name), "hello".into());
105
106        assert_eq!(cake::Model::from(cake_ex), cake);
107    }
108}