sea_orm/entity/model.rs
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
use crate::{
ActiveModelBehavior, ActiveModelTrait, ConnectionTrait, DbErr, DeleteResult, EntityTrait,
IntoActiveModel, Linked, QueryFilter, QueryResult, Related, Select, SelectModel, SelectorRaw,
Statement,
};
use async_trait::async_trait;
pub use sea_query::Value;
use std::fmt::Debug;
/// A Trait for a Model
#[async_trait]
pub trait ModelTrait: Clone + Send + Debug {
#[allow(missing_docs)]
type Entity: EntityTrait;
/// Get the [Value] of a column from an Entity
fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> Value;
/// Set the [Value] of a column in an Entity
fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
/// Find related Models
fn find_related<R>(&self, _: R) -> Select<R>
where
R: EntityTrait,
Self::Entity: Related<R>,
{
<Self::Entity as Related<R>>::find_related().belongs_to(self)
}
/// Find linked Models
fn find_linked<L>(&self, l: L) -> Select<L::ToEntity>
where
L: Linked<FromEntity = Self::Entity>,
{
let tbl_alias = &format!("r{}", l.link().len() - 1);
l.find_linked().belongs_to_tbl_alias(self, tbl_alias)
}
/// Delete a model
async fn delete<'a, A, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
where
Self: IntoActiveModel<A>,
C: ConnectionTrait,
A: ActiveModelTrait<Entity = Self::Entity> + ActiveModelBehavior + Send + 'a,
{
self.into_active_model().delete(db).await
}
}
/// A Trait for implementing a [QueryResult]
pub trait FromQueryResult: Sized {
/// Instantiate a Model from a [QueryResult]
fn from_query_result(res: &QueryResult, pre: &str) -> Result<Self, DbErr>;
/// Transform the error from instantiating a Model from a [QueryResult]
/// and converting it to an [Option]
fn from_query_result_optional(res: &QueryResult, pre: &str) -> Result<Option<Self>, DbErr> {
Ok(Self::from_query_result(res, pre).ok())
}
/// ```
/// # use sea_orm::{error::*, tests_cfg::*, *};
/// #
/// # #[smol_potat::main]
/// # #[cfg(feature = "mock")]
/// # pub async fn main() -> Result<(), DbErr> {
/// #
/// # let db = MockDatabase::new(DbBackend::Postgres)
/// # .append_query_results([[
/// # maplit::btreemap! {
/// # "name" => Into::<Value>::into("Chocolate Forest"),
/// # "num_of_cakes" => Into::<Value>::into(2),
/// # },
/// # ]])
/// # .into_connection();
/// #
/// use sea_orm::{query::*, FromQueryResult};
///
/// #[derive(Debug, PartialEq, FromQueryResult)]
/// struct SelectResult {
/// name: String,
/// num_of_cakes: i32,
/// }
///
/// let res: Vec<SelectResult> = SelectResult::find_by_statement(Statement::from_sql_and_values(
/// DbBackend::Postgres,
/// r#"SELECT "name", COUNT(*) AS "num_of_cakes" FROM "cake" GROUP BY("name")"#,
/// [],
/// ))
/// .all(&db)
/// .await?;
///
/// assert_eq!(
/// res,
/// [SelectResult {
/// name: "Chocolate Forest".to_owned(),
/// num_of_cakes: 2,
/// },]
/// );
/// #
/// # assert_eq!(
/// # db.into_transaction_log(),
/// # [Transaction::from_sql_and_values(
/// # DbBackend::Postgres,
/// # r#"SELECT "name", COUNT(*) AS "num_of_cakes" FROM "cake" GROUP BY("name")"#,
/// # []
/// # ),]
/// # );
/// #
/// # Ok(())
/// # }
/// ```
fn find_by_statement(stmt: Statement) -> SelectorRaw<SelectModel<Self>> {
SelectorRaw::<SelectModel<Self>>::from_statement(stmt)
}
}
/// A Trait for any type that can be converted into an Model
pub trait TryIntoModel<M>
where
M: ModelTrait,
{
/// Method to call to perform the conversion
fn try_into_model(self) -> Result<M, DbErr>;
}
impl<M> TryIntoModel<M> for M
where
M: ModelTrait,
{
fn try_into_model(self) -> Result<M, DbErr> {
Ok(self)
}
}