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 mem,
10 pin::pin,
11};
12
13pub trait Entity {
15 type PrimaryKey<'a>;
17
18 fn table() -> &'static TableRef;
20
21 fn columns() -> &'static [ColumnDef];
23
24 fn primary_key_def() -> &'static [&'static ColumnDef];
26
27 fn primary_key(&self) -> Self::PrimaryKey<'_>;
29
30 fn unique_defs()
32 -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &'static ColumnDef>>;
33
34 fn row_filtered(&self) -> Box<[(&'static str, Value)]>;
37
38 fn row_full(&self) -> Row;
40
41 fn from_row(row: RowLabeled) -> Result<Self>
45 where
46 Self: Sized;
47
48 fn create_table(
54 executor: &mut impl Executor,
55 if_not_exists: bool,
56 create_schema: bool,
57 ) -> impl Future<Output = Result<()>> + Send
58 where
59 Self: Sized,
60 {
61 async move {
62 let mut query = String::with_capacity(2048);
63 let writer = executor.driver().sql_writer();
64 if create_schema && !Self::table().schema().is_empty() {
65 writer.write_create_schema::<Self>(&mut query, true);
66 }
67 if !executor.accepts_multiple_statements() && !query.is_empty() {
68 let mut q = Query::Raw(query);
69 executor.execute(&mut q).boxed().await?;
70 let Query::Raw(mut q) = q else {
71 return Err(Error::msg(
72 "The executor was borrowed a raw query but it did not return it",
73 ));
74 };
75 query = mem::take(&mut q);
77 query.clear();
78 }
79 writer.write_create_table::<Self>(&mut query, if_not_exists);
80 executor.execute(query).boxed().await.map(|_| ())
82 }
83 }
84
85 fn drop_table(
91 executor: &mut impl Executor,
92 if_exists: bool,
93 drop_schema: bool,
94 ) -> impl Future<Output = Result<()>> + Send
95 where
96 Self: Sized,
97 {
98 async move {
99 let mut query = String::with_capacity(256);
100 let writer = executor.driver().sql_writer();
101 writer.write_drop_table::<Self>(&mut query, if_exists);
102 if drop_schema && !Self::table().schema().is_empty() {
103 if !executor.accepts_multiple_statements() {
104 let mut q = Query::Raw(query);
105 executor.execute(&mut q).boxed().await?;
106 let Query::Raw(mut q) = q else {
107 return Err(Error::msg(
108 "The executor was borrowed a raw query but it did not return it",
109 ));
110 };
111 query = mem::take(&mut q);
113 query.clear();
114 }
115 writer.write_drop_schema::<Self>(&mut query, true);
116 }
117 executor.execute(query).boxed().await.map(|_| ())
119 }
120 }
121
122 fn insert_one(
126 executor: &mut impl Executor,
127 entity: &impl Entity,
128 ) -> impl Future<Output = Result<RowsAffected>> + Send {
129 let mut query = String::with_capacity(128);
130 executor
131 .driver()
132 .sql_writer()
133 .write_insert(&mut query, [entity], false);
134 executor.execute(query)
135 }
136
137 fn insert_many<'a, It>(
141 executor: &mut impl Executor,
142 items: It,
143 ) -> impl Future<Output = Result<RowsAffected>> + Send
144 where
145 Self: 'a + Sized,
146 It: IntoIterator<Item = &'a Self> + Send,
147 <It as IntoIterator>::IntoIter: Send,
148 {
149 executor.append(items)
150 }
151
152 fn prepare_find<Exec: Executor>(
156 executor: &mut Exec,
157 condition: &impl Expression,
158 limit: Option<u32>,
159 ) -> impl Future<Output = Result<Query<Exec::Driver>>> {
160 Self::table().prepare(executor, Self::columns(), condition, limit)
161 }
162
163 fn find_pk(
167 executor: &mut impl Executor,
168 primary_key: &Self::PrimaryKey<'_>,
169 ) -> impl Future<Output = Result<Option<Self>>> + Send
170 where
171 Self: Sized;
172
173 fn find_one(
177 executor: &mut impl Executor,
178 condition: &impl Expression,
179 ) -> impl Future<Output = Result<Option<Self>>> + Send
180 where
181 Self: Sized,
182 {
183 let stream = Self::find_many(executor, condition, Some(1));
184 async move { pin!(stream).into_future().map(|(v, _)| v).await.transpose() }
185 }
186
187 fn find_many(
192 executor: &mut impl Executor,
193 condition: impl Expression,
194 limit: Option<u32>,
195 ) -> impl Stream<Item = Result<Self>> + Send
196 where
197 Self: Sized,
198 {
199 Self::table()
200 .select(
201 executor,
202 Self::columns()
203 .iter()
204 .map(|c| &c.column_ref as &dyn Expression),
205 condition,
206 limit,
207 )
208 .map(|result| result.and_then(Self::from_row))
209 }
210
211 fn delete_one(
215 executor: &mut impl Executor,
216 primary_key: Self::PrimaryKey<'_>,
217 ) -> impl Future<Output = Result<RowsAffected>> + Send
218 where
219 Self: Sized;
220
221 fn delete_many(
225 executor: &mut impl Executor,
226 condition: &impl Expression,
227 ) -> impl Future<Output = Result<RowsAffected>> + Send
228 where
229 Self: Sized,
230 {
231 let mut query = String::with_capacity(128);
232 executor
233 .driver()
234 .sql_writer()
235 .write_delete::<Self>(&mut query, condition);
236 executor.execute(query)
237 }
238
239 fn save(&self, executor: &mut impl Executor) -> impl Future<Output = Result<()>> + Send
245 where
246 Self: Sized,
247 {
248 if Self::primary_key_def().len() == 0 {
249 let error = Error::msg(
250 "Cannot save an entity without a primary key, it would always result in an insert",
251 );
252 log::error!("{:#}", error);
253 return Either::Left(future::ready(Err(error)));
254 }
255 let mut query = String::with_capacity(512);
256 executor
257 .driver()
258 .sql_writer()
259 .write_insert(&mut query, [self], true);
260 Either::Right(executor.execute(query).map_ok(|_| ()))
261 }
262
263 fn delete(&self, executor: &mut impl Executor) -> impl Future<Output = Result<()>> + Send
270 where
271 Self: Sized,
272 {
273 if Self::primary_key_def().len() == 0 {
274 let error = Error::msg(
275 "Cannot delete an entity without a primary key, it would delete nothing",
276 );
277 log::error!("{:#}", error);
278 return Either::Left(future::ready(Err(error)));
279 }
280 Either::Right(Self::delete_one(executor, self.primary_key()).map(|v| {
281 v.and_then(|v| {
282 if let Some(affected) = v.rows_affected {
283 if affected != 1 {
284 let error = Error::msg(format!(
285 "The query deleted {affected} rows instead of the expected 1"
286 ));
287 log::log!(
288 if affected == 0 {
289 Level::Info
290 } else {
291 Level::Error
292 },
293 "{error}",
294 );
295 return Err(error);
296 }
297 }
298 Ok(())
299 })
300 }))
301 }
302}
303
304impl<E: Entity> DataSet for E {
305 fn qualified_columns() -> bool
309 where
310 Self: Sized,
311 {
312 false
313 }
314
315 fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut String) {
317 Self::table().write_query(writer, context, out);
318 }
319}