1use crate::{
2 ColumnDef, Context, DataSet, Driver, Error, Executor, Expression, Result, Row, RowLabeled,
3 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 {
13 type PrimaryKey<'a>;
14
15 fn table() -> &'static TableRef;
16 fn columns() -> &'static [ColumnDef];
17 fn primary_key_def() -> impl ExactSizeIterator<Item = &'static ColumnDef>;
18 fn primary_key(&self) -> Self::PrimaryKey<'_>;
19 fn unique_defs()
20 -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &'static ColumnDef>>;
21 fn row_filtered(&self) -> Box<[(&'static str, Value)]>;
22 fn row_full(&self) -> Row;
23 fn from_row(row: RowLabeled) -> Result<Self>
24 where
25 Self: Sized;
26
27 fn create_table<Exec: Executor>(
28 executor: &mut Exec,
29 if_not_exists: bool,
30 create_schema: bool,
31 ) -> impl Future<Output = Result<()>> + Send;
32
33 fn drop_table<Exec: Executor>(
34 executor: &mut Exec,
35 if_exists: bool,
36 drop_schema: bool,
37 ) -> impl Future<Output = Result<()>> + Send;
38
39 fn insert_one<Exec: Executor, E: Entity>(
40 executor: &mut Exec,
41 entity: &E,
42 ) -> impl Future<Output = Result<RowsAffected>> + Send;
43
44 fn insert_many<'a, Exec, It>(
45 executor: &mut Exec,
46 items: It,
47 ) -> impl Future<Output = Result<RowsAffected>> + Send
48 where
49 Self: 'a,
50 Exec: Executor,
51 It: IntoIterator<Item = &'a Self> + Send;
52
53 fn find_pk<Exec: Executor>(
54 executor: &mut Exec,
55 primary_key: &Self::PrimaryKey<'_>,
56 ) -> impl Future<Output = Result<Option<Self>>> + Send
57 where
58 Self: Sized;
59
60 fn find_one<Exec: Executor, Expr: Expression>(
61 executor: &mut Exec,
62 condition: &Expr,
63 ) -> impl Future<Output = Result<Option<Self>>> + Send
64 where
65 Self: Sized,
66 {
67 let stream = Self::find_many(executor, condition, Some(1));
68 async move { pin!(stream).into_future().map(|(v, _)| v).await.transpose() }
69 }
70
71 fn find_many<Exec: Executor, Expr: Expression>(
72 executor: &mut Exec,
73 condition: &Expr,
74 limit: Option<u32>,
75 ) -> impl Stream<Item = Result<Self>> + Send
76 where
77 Self: Sized;
78
79 fn delete_one<Exec: Executor>(
80 executor: &mut Exec,
81 primary_key: Self::PrimaryKey<'_>,
82 ) -> impl Future<Output = Result<RowsAffected>> + Send
83 where
84 Self: Sized;
85
86 fn delete_many<Exec: Executor, Expr: Expression>(
87 executor: &mut Exec,
88 condition: &Expr,
89 ) -> impl Future<Output = Result<RowsAffected>> + Send
90 where
91 Self: Sized;
92
93 fn save<Exec: Executor>(&self, executor: &mut Exec) -> impl Future<Output = Result<()>> + Send
94 where
95 Self: Sized,
96 {
97 if Self::primary_key_def().len() == 0 {
98 let error = Error::msg(
99 "Cannot save a entity without a primary key, it would always result in a insert",
100 );
101 log::error!("{}", error);
102 return Either::Left(future::ready(Err(error)));
103 }
104 let mut query = String::with_capacity(512);
105 executor
106 .driver()
107 .sql_writer()
108 .write_insert(&mut query, [self], true);
109 Either::Right(executor.execute(query.into()).map_ok(|_| ()))
110 }
111
112 fn delete<Exec: Executor>(&self, executor: &mut Exec) -> impl Future<Output = Result<()>> + Send
113 where
114 Self: Sized,
115 {
116 if Self::primary_key_def().len() == 0 {
117 let error =
118 Error::msg("Cannot delete a entity without a primary key, it would delete nothing");
119 log::error!("{}", error);
120 return Either::Left(future::ready(Err(error)));
121 }
122 Either::Right(Self::delete_one(executor, self.primary_key()).map(|v| {
123 v.and_then(|v| {
124 if v.rows_affected == 1 {
125 Ok(())
126 } else {
127 let error = Error::msg(format!(
128 "The query deleted {} rows instead of the expected 1",
129 v.rows_affected
130 ));
131 log::log!(
132 if v.rows_affected == 0 {
133 Level::Info
134 } else {
135 Level::Error
136 },
137 "{}",
138 error
139 );
140 Err(error)
141 }
142 })
143 }))
144 }
145}
146
147impl<E: Entity> DataSet for E {
148 fn qualified_columns() -> bool
149 where
150 Self: Sized,
151 {
152 false
153 }
154 fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, buff: &mut String) {
155 Self::table().write_query(writer, context, buff);
156 }
157}