sea_orm/dynamic/
execute.rs

1use crate::{
2    ConnectionTrait, DbBackend, DbErr, EntityTrait, FromQueryResult, QueryResult, Select,
3    Statement, dynamic,
4};
5use itertools::Itertools;
6use sea_query::{DynIden, Expr, IntoIden, SelectStatement};
7use std::marker::PhantomData;
8
9#[derive(Debug)]
10pub struct SelectModelAndDynModel<M>
11where
12    M: FromQueryResult,
13{
14    model: PhantomData<M>,
15    dyn_model: dynamic::ModelType,
16}
17
18#[derive(Clone, Debug)]
19pub struct DynSelector<S>
20where
21    S: DynSelectorTrait,
22{
23    pub(crate) query: SelectStatement,
24    selector: S,
25}
26
27pub trait DynSelectorTrait {
28    type Item: Sized;
29
30    #[allow(clippy::wrong_self_convention)]
31    fn from_raw_query_result(&self, res: QueryResult) -> Result<Self::Item, DbErr>;
32}
33
34impl<M> DynSelectorTrait for SelectModelAndDynModel<M>
35where
36    M: FromQueryResult + Sized,
37{
38    type Item = (M, dynamic::Model);
39
40    fn from_raw_query_result(&self, res: QueryResult) -> Result<Self::Item, DbErr> {
41        Ok((
42            M::from_query_result(&res, "")?,
43            self.dyn_model.from_query_result(&res, "")?,
44        ))
45    }
46}
47
48impl<E> Select<E>
49where
50    E: EntityTrait,
51{
52    pub fn select_also_dyn_model(
53        mut self,
54        table: DynIden,
55        dyn_model: dynamic::ModelType,
56    ) -> DynSelector<SelectModelAndDynModel<E::Model>> {
57        for field in dyn_model.fields.iter() {
58            self.query.expr(Expr::col((
59                table.clone(),
60                field.field().to_owned().into_iden(),
61            )));
62        }
63        DynSelector {
64            query: self.query,
65            selector: SelectModelAndDynModel {
66                model: PhantomData,
67                dyn_model,
68            },
69        }
70    }
71}
72
73impl<S> DynSelector<S>
74where
75    S: DynSelectorTrait,
76{
77    /// Get the SQL statement
78    pub fn into_statement(self, builder: DbBackend) -> Statement {
79        builder.build(&self.query)
80    }
81
82    /// Get an item from the Select query
83    pub fn one<C>(mut self, db: &C) -> Result<Option<S::Item>, DbErr>
84    where
85        C: ConnectionTrait,
86    {
87        self.query.limit(1);
88        let row = db.query_one(&self.query)?;
89        match row {
90            Some(row) => Ok(Some(self.selector.from_raw_query_result(row)?)),
91            None => Ok(None),
92        }
93    }
94
95    /// Get all items from the Select query
96    pub fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
97    where
98        C: ConnectionTrait,
99    {
100        db.query_all(&self.query)?
101            .into_iter()
102            .map(|row| self.selector.from_raw_query_result(row))
103            .try_collect()
104    }
105}