sea_orm/dynamic/
entity.rs

1use super::{FieldType, ModelType};
2use crate::{ColumnDef, ColumnTrait, DbBackend, EntityTrait, Iterable, ModelTrait, Value};
3use sea_query::{
4    ArrayType, BinOper, DynIden, Expr, ExprTrait, IntoColumnRef, IntoIden, IntoLikeExpr,
5    IntoTableRef, SelectStatement, SimpleExpr, TableRef,
6};
7use std::sync::Arc;
8
9#[derive(Debug)]
10pub struct Entity {
11    schema_name: Option<Arc<str>>,
12    table_name: Arc<str>,
13    columns: Vec<Column>,
14}
15
16#[derive(Debug)]
17pub struct Column {
18    table_name: Arc<str>,
19    column_name: Arc<str>,
20    column_def: ColumnDef,
21    value_type: ArrayType,
22    enum_type_name: Option<Arc<str>>,
23}
24
25impl Entity {
26    pub fn schema_name(&self) -> Option<&str> {
27        self.schema_name.as_deref()
28    }
29
30    pub fn table_name(&self) -> &str {
31        &self.table_name
32    }
33
34    pub fn table_ref(&self) -> TableRef {
35        match self.schema_name() {
36            Some(schema) => (schema.to_owned(), self.table_name().to_owned()).into_table_ref(),
37            None => self.table_name().to_owned().into_table_ref(),
38        }
39    }
40
41    pub fn iter_columns(&self) -> impl Iterator<Item = &Column> {
42        self.columns.iter()
43    }
44}
45
46impl Entity {
47    pub fn from_entity<E: EntityTrait>(entity: E) -> Self {
48        Self {
49            schema_name: entity.schema_name().map(Arc::from),
50            table_name: Arc::from(entity.table_name()),
51            columns: <E::Column as Iterable>::iter()
52                .map(|c| {
53                    let (tbl, col) = c.as_column_ref();
54                    Column {
55                        table_name: Arc::from(tbl.inner()),
56                        column_name: Arc::from(col.inner()),
57                        column_def: c.def(),
58                        value_type: <E::Model as ModelTrait>::get_value_type(c),
59                        enum_type_name: c.enum_type_name().map(Arc::from),
60                    }
61                })
62                .collect(),
63        }
64    }
65
66    pub fn to_model_type(&self) -> ModelType {
67        ModelType {
68            fields: self
69                .columns
70                .iter()
71                .map(|c| FieldType {
72                    field: c.column_name.clone(),
73                    type_: c.value_type.clone(),
74                })
75                .collect(),
76        }
77    }
78}
79
80impl Column {
81    pub fn def(&self) -> ColumnDef {
82        self.column_def.clone()
83    }
84
85    pub fn column_name(&self) -> &str {
86        &self.column_name
87    }
88
89    pub fn enum_type_name(&self) -> Option<&str> {
90        self.enum_type_name.as_deref()
91    }
92
93    pub fn entity_name(&self) -> DynIden {
94        self.table_name.to_string().into_iden()
95    }
96
97    pub fn as_column_ref(&self) -> (DynIden, DynIden) {
98        (
99            self.entity_name(),
100            self.column_name().to_owned().into_iden(),
101        )
102    }
103
104    crate::entity::column::macros::bind_oper!(pub eq, Equal);
105    crate::entity::column::macros::bind_oper!(pub ne, NotEqual);
106    crate::entity::column::macros::bind_oper!(pub gt, GreaterThan);
107    crate::entity::column::macros::bind_oper!(pub gte, GreaterThanOrEqual);
108    crate::entity::column::macros::bind_oper!(pub lt, SmallerThan);
109    crate::entity::column::macros::bind_oper!(pub lte, SmallerThanOrEqual);
110
111    pub fn between<V>(&self, a: V, b: V) -> SimpleExpr
112    where
113        V: Into<Value>,
114    {
115        Expr::col(self.as_column_ref()).between(a, b)
116    }
117
118    pub fn not_between<V>(&self, a: V, b: V) -> SimpleExpr
119    where
120        V: Into<Value>,
121    {
122        Expr::col(self.as_column_ref()).not_between(a, b)
123    }
124
125    pub fn like<T>(&self, s: T) -> SimpleExpr
126    where
127        T: IntoLikeExpr,
128    {
129        Expr::col(self.as_column_ref()).like(s)
130    }
131
132    pub fn not_like<T>(&self, s: T) -> SimpleExpr
133    where
134        T: IntoLikeExpr,
135    {
136        Expr::col(self.as_column_ref()).not_like(s)
137    }
138
139    pub fn starts_with<T>(&self, s: T) -> SimpleExpr
140    where
141        T: Into<String>,
142    {
143        let pattern = format!("{}%", s.into());
144        Expr::col(self.as_column_ref()).like(pattern)
145    }
146
147    pub fn ends_with<T>(&self, s: T) -> SimpleExpr
148    where
149        T: Into<String>,
150    {
151        let pattern = format!("%{}", s.into());
152        Expr::col(self.as_column_ref()).like(pattern)
153    }
154
155    pub fn contains<T>(&self, s: T) -> SimpleExpr
156    where
157        T: Into<String>,
158    {
159        let pattern = format!("%{}%", s.into());
160        Expr::col(self.as_column_ref()).like(pattern)
161    }
162
163    crate::entity::column::macros::bind_func_no_params!(pub max);
164    crate::entity::column::macros::bind_func_no_params!(pub min);
165    crate::entity::column::macros::bind_func_no_params!(pub sum);
166    crate::entity::column::macros::bind_func_no_params!(pub count);
167    crate::entity::column::macros::bind_func_no_params!(pub is_null);
168    crate::entity::column::macros::bind_func_no_params!(pub is_not_null);
169
170    pub fn if_null<V>(&self, v: V) -> SimpleExpr
171    where
172        V: Into<Value>,
173    {
174        Expr::col(self.as_column_ref()).if_null(v)
175    }
176
177    crate::entity::column::macros::bind_vec_func!(pub is_in);
178    crate::entity::column::macros::bind_vec_func!(pub is_not_in);
179
180    crate::entity::column::macros::bind_subquery_func!(pub in_subquery);
181    crate::entity::column::macros::bind_subquery_func!(pub not_in_subquery);
182
183    pub fn into_expr(self) -> Expr {
184        SimpleExpr::Column(self.as_column_ref().into_column_ref())
185    }
186
187    #[allow(clippy::match_single_binding)]
188    pub fn into_returning_expr(self, db_backend: DbBackend) -> Expr {
189        match db_backend {
190            _ => Expr::col(self.column_name().to_owned()),
191        }
192    }
193
194    pub fn select_as(&self, expr: Expr) -> SimpleExpr {
195        crate::entity::column::cast_enum_as(
196            expr,
197            &self.def(),
198            crate::entity::column::select_enum_as,
199        )
200    }
201
202    pub fn save_as(&self, val: Expr) -> SimpleExpr {
203        crate::entity::column::cast_enum_as(val, &self.def(), crate::entity::column::save_enum_as)
204    }
205}