sea_orm/entity/
model.rs

1use crate::{
2    ActiveModelBehavior, ActiveModelTrait, ConnectionTrait, DbErr, DeleteResult, EntityTrait,
3    IntoActiveModel, Linked, QueryFilter, QueryResult, Related, Select, SelectModel, SelectorRaw,
4    Statement,
5};
6use async_trait::async_trait;
7pub use sea_query::Value;
8use std::fmt::Debug;
9
10/// A Trait for a Model
11#[async_trait]
12pub trait ModelTrait: Clone + Send + Debug {
13    #[allow(missing_docs)]
14    type Entity: EntityTrait;
15
16    /// Get the [Value] of a column from an Entity
17    fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> Value;
18
19    /// Set the [Value] of a column in an Entity
20    fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
21
22    /// Find related Models
23    fn find_related<R>(&self, _: R) -> Select<R>
24    where
25        R: EntityTrait,
26        Self::Entity: Related<R>,
27    {
28        <Self::Entity as Related<R>>::find_related().belongs_to(self)
29    }
30
31    /// Find linked Models
32    fn find_linked<L>(&self, l: L) -> Select<L::ToEntity>
33    where
34        L: Linked<FromEntity = Self::Entity>,
35    {
36        let tbl_alias = &format!("r{}", l.link().len() - 1);
37        l.find_linked().belongs_to_tbl_alias(self, tbl_alias)
38    }
39
40    /// Delete a model
41    async fn delete<'a, A, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
42    where
43        Self: IntoActiveModel<A>,
44        C: ConnectionTrait,
45        A: ActiveModelTrait<Entity = Self::Entity> + ActiveModelBehavior + Send + 'a,
46    {
47        self.into_active_model().delete(db).await
48    }
49}
50
51/// A Trait for implementing a [QueryResult]
52pub trait FromQueryResult: Sized {
53    /// Instantiate a Model from a [QueryResult]
54    fn from_query_result(res: &QueryResult, pre: &str) -> Result<Self, DbErr>;
55
56    /// Transform the error from instantiating a Model from a [QueryResult]
57    /// and converting it to an [Option]
58    fn from_query_result_optional(res: &QueryResult, pre: &str) -> Result<Option<Self>, DbErr> {
59        Ok(Self::from_query_result(res, pre).ok())
60    }
61
62    /// ```
63    /// # use sea_orm::{error::*, tests_cfg::*, *};
64    /// #
65    /// # #[smol_potat::main]
66    /// # #[cfg(feature = "mock")]
67    /// # pub async fn main() -> Result<(), DbErr> {
68    /// #
69    /// # let db = MockDatabase::new(DbBackend::Postgres)
70    /// #     .append_query_results([[
71    /// #         maplit::btreemap! {
72    /// #             "name" => Into::<Value>::into("Chocolate Forest"),
73    /// #             "num_of_cakes" => Into::<Value>::into(2),
74    /// #         },
75    /// #     ]])
76    /// #     .into_connection();
77    /// #
78    /// use sea_orm::{query::*, FromQueryResult};
79    ///
80    /// #[derive(Debug, PartialEq, FromQueryResult)]
81    /// struct SelectResult {
82    ///     name: String,
83    ///     num_of_cakes: i32,
84    /// }
85    ///
86    /// let res: Vec<SelectResult> = SelectResult::find_by_statement(Statement::from_sql_and_values(
87    ///     DbBackend::Postgres,
88    ///     r#"SELECT "name", COUNT(*) AS "num_of_cakes" FROM "cake" GROUP BY("name")"#,
89    ///     [],
90    /// ))
91    /// .all(&db)
92    /// .await?;
93    ///
94    /// assert_eq!(
95    ///     res,
96    ///     [SelectResult {
97    ///         name: "Chocolate Forest".to_owned(),
98    ///         num_of_cakes: 2,
99    ///     },]
100    /// );
101    /// #
102    /// # assert_eq!(
103    /// #     db.into_transaction_log(),
104    /// #     [Transaction::from_sql_and_values(
105    /// #         DbBackend::Postgres,
106    /// #         r#"SELECT "name", COUNT(*) AS "num_of_cakes" FROM "cake" GROUP BY("name")"#,
107    /// #         []
108    /// #     ),]
109    /// # );
110    /// #
111    /// # Ok(())
112    /// # }
113    /// ```
114    fn find_by_statement(stmt: Statement) -> SelectorRaw<SelectModel<Self>> {
115        SelectorRaw::<SelectModel<Self>>::from_statement(stmt)
116    }
117}
118
119/// A Trait for any type that can be converted into an Model
120pub trait TryIntoModel<M>
121where
122    M: ModelTrait,
123{
124    /// Method to call to perform the conversion
125    fn try_into_model(self) -> Result<M, DbErr>;
126}
127
128impl<M> TryIntoModel<M> for M
129where
130    M: ModelTrait,
131{
132    fn try_into_model(self) -> Result<M, DbErr> {
133        Ok(self)
134    }
135}