1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use rusqlite::{Connection, Row, ToSql};

use crate::entities::errors::DbResult;

pub trait IConnection {
    type Locked: IConnection;

    fn lock(&self) -> DbResult<Self::Locked>;
    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T>;
}

pub trait INewDbRepo<Connection> {
    fn create(connect: Connection) -> Self;
}

pub trait IDbRepo {
    fn as_super(&self) -> &dyn IDbRepo {
        unimplemented!()
    }
    fn init(&self) -> DbResult<()> {
        self.as_super().init()
    }
    fn recreate_tables(&self) -> DbResult<()> {
        // self.as_super().recreate_table()
        self.drop()?;
        self.init()
    }
    fn drop(&self) -> DbResult<()> {
        self.as_super().drop()
    }
    fn set_indexes(&self) -> DbResult<()> {
        self.as_super().set_indexes()
    }
    fn drop_indexes(&self) -> DbResult<()> {
        self.as_super().drop_indexes()
    }
    fn get_size(&self) -> DbResult<usize> {
        self.as_super().get_size()
    }
}

pub trait IExecutor {
    type Locked: IExecutor;

    fn lock(&self) -> DbResult<Self::Locked>;
    fn get_one<T, F: FnMut(&rusqlite::Row<'_>) -> rusqlite::Result<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<T>;
    fn get_many<T, F: FnMut(&rusqlite::Row<'_>) -> rusqlite::Result<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<Vec<T>>;
    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()>;
    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64>;
}

// ---------------------------
// ------ IMPLS --------------
// ---------------------------

impl IConnection for Connection {
    type Locked = Self;

    fn lock(&self) -> DbResult<Self::Locked> {
        panic!("Can not lock bare connection")
    }

    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
        fun(self)
    }
}

impl<Cnn: IConnection> IConnection for &Cnn {
    type Locked = Cnn::Locked;

    fn lock(&self) -> DbResult<Self::Locked> {
        (**self).lock()
    }

    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
        (**self).with(fun)
    }
}

impl<Ex: IExecutor> IExecutor for &Ex {
    type Locked = Ex::Locked;

    fn lock(&self) -> DbResult<Self::Locked> {
        (**self).lock()
    }

    fn get_one<T, F: FnMut(&Row<'_>) -> rusqlite::Result<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<T> {
        (**self).get_one(query, params, serializer)
    }

    fn get_many<T, F: FnMut(&Row<'_>) -> rusqlite::Result<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<Vec<T>> {
        (**self).get_many(query, params, serializer)
    }

    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
        (**self).execute(query, params)
    }

    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
        (**self).execute_return_id(query, params)
    }
}