tank_core/
entity.rs

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}