1use crate::{
2 ColumnDef, Context, DataSet, Driver, Error, Executor, Expression, Query, Result, Row,
3 RowLabeled, RowsAffected, TableRef, Value, future::Either, stream::Stream, writer::SqlWriter,
4};
5use futures::{FutureExt, StreamExt, TryFutureExt};
6use log::Level;
7use std::{
8 future::{self, Future},
9 pin::pin,
10};
11
12pub trait Entity {
19 type PrimaryKey<'a>;
21
22 fn table() -> &'static TableRef;
24
25 fn columns() -> &'static [ColumnDef];
27
28 fn primary_key_def() -> impl ExactSizeIterator<Item = &'static ColumnDef>;
30
31 fn primary_key(&self) -> Self::PrimaryKey<'_>;
33
34 fn unique_defs()
36 -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &'static ColumnDef>>;
37
38 fn row_filtered(&self) -> Box<[(&'static str, Value)]>;
41
42 fn row_full(&self) -> Row;
44
45 fn from_row(row: RowLabeled) -> Result<Self>
49 where
50 Self: Sized;
51
52 fn create_table(
58 executor: &mut impl Executor,
59 if_not_exists: bool,
60 create_schema: bool,
61 ) -> impl Future<Output = Result<()>> + Send;
62
63 fn drop_table(
69 executor: &mut impl Executor,
70 if_exists: bool,
71 drop_schema: bool,
72 ) -> impl Future<Output = Result<()>> + Send;
73
74 fn insert_one(
78 executor: &mut impl Executor,
79 entity: &impl Entity,
80 ) -> impl Future<Output = Result<RowsAffected>> + Send;
81
82 fn insert_many<'a, It>(
86 executor: &mut impl Executor,
87 items: It,
88 ) -> impl Future<Output = Result<RowsAffected>> + Send
89 where
90 Self: 'a,
91 It: IntoIterator<Item = &'a Self> + Send;
92
93 fn prepare_find<Exec: Executor>(
97 executor: &mut Exec,
98 condition: &impl Expression,
99 limit: Option<u32>,
100 ) -> impl Future<Output = Result<Query<Exec::Driver>>> {
101 Self::table().prepare(executor, Self::columns(), condition, limit)
102 }
103
104 fn find_pk(
108 executor: &mut impl Executor,
109 primary_key: &Self::PrimaryKey<'_>,
110 ) -> impl Future<Output = Result<Option<Self>>> + Send
111 where
112 Self: Sized;
113
114 fn find_one(
118 executor: &mut impl Executor,
119 condition: &impl Expression,
120 ) -> impl Future<Output = Result<Option<Self>>> + Send
121 where
122 Self: Sized,
123 {
124 let stream = Self::find_many(executor, condition, Some(1));
125 async move { pin!(stream).into_future().map(|(v, _)| v).await.transpose() }
126 }
127
128 fn find_many(
133 executor: &mut impl Executor,
134 condition: &impl Expression,
135 limit: Option<u32>,
136 ) -> impl Stream<Item = Result<Self>> + Send
137 where
138 Self: Sized;
139
140 fn delete_one(
144 executor: &mut impl Executor,
145 primary_key: Self::PrimaryKey<'_>,
146 ) -> impl Future<Output = Result<RowsAffected>> + Send
147 where
148 Self: Sized;
149
150 fn delete_many(
154 executor: &mut impl Executor,
155 condition: &impl Expression,
156 ) -> impl Future<Output = Result<RowsAffected>> + Send
157 where
158 Self: Sized;
159
160 fn save(&self, executor: &mut impl Executor) -> impl Future<Output = Result<()>> + Send
166 where
167 Self: Sized,
168 {
169 if Self::primary_key_def().len() == 0 {
170 let error = Error::msg(
171 "Cannot save a entity without a primary key, it would always result in a insert",
172 );
173 log::error!("{:#}", error);
174 return Either::Left(future::ready(Err(error)));
175 }
176 let mut query = String::with_capacity(512);
177 executor
178 .driver()
179 .sql_writer()
180 .write_insert(&mut query, [self], true);
181 Either::Right(executor.execute(query).map_ok(|_| ()))
182 }
183
184 fn delete(&self, executor: &mut impl Executor) -> impl Future<Output = Result<()>> + Send
191 where
192 Self: Sized,
193 {
194 if Self::primary_key_def().len() == 0 {
195 let error =
196 Error::msg("Cannot delete a entity without a primary key, it would delete nothing");
197 log::error!("{:#}", error);
198 return Either::Left(future::ready(Err(error)));
199 }
200 Either::Right(Self::delete_one(executor, self.primary_key()).map(|v| {
201 v.and_then(|v| {
202 if v.rows_affected == 1 {
203 Ok(())
204 } else {
205 let error = Error::msg(format!(
206 "The query deleted {} rows instead of the expected 1",
207 v.rows_affected
208 ));
209 log::log!(
210 if v.rows_affected == 0 {
211 Level::Info
212 } else {
213 Level::Error
214 },
215 "{}",
216 error
217 );
218 Err(error)
219 }
220 })
221 }))
222 }
223}
224
225impl<E: Entity> DataSet for E {
226 fn qualified_columns() -> bool
230 where
231 Self: Sized,
232 {
233 false
234 }
235
236 fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut String) {
238 Self::table().write_query(writer, context, out);
239 }
240}