tank_core/
entity.rs

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