sea_orm/dynamic/
entity.rs1use 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}