sqlx_utils/macros/
mod.rs

1mod db;
2mod repository;
3
4/// Creates a new database repository, either just creates a basic new type and statics to interact
5/// with the main database pool.
6///
7/// If a database model is provided it will also try to implement the [`crate::traits::Repository`] trait.
8///
9/// For non ZST repositories it will implement `Deref`, `Borrow`, and `AsRef` to get the inner pool.
10///
11/// # Examples
12///
13/// ```
14/// use sqlx_utils::repository;
15/// use sqlx_utils::traits::Model;
16///
17///
18/// struct Person {
19///     id: String,
20///     name: String
21/// }
22///
23/// impl Model for Person {
24///     type Id = String;
25///
26///     fn get_id(&self) -> Option<Self::Id> {
27///         Some(self.id.clone())
28///     }
29/// }
30///
31/// repository!{
32///     PersonRepository<Person>;
33/// }
34/// ```
35///
36/// # Zero Sized Type Repository
37///
38/// It is possible to make a repository that is zero sized by never storing the reference to the database pool,
39/// this will add a slight cost however, whenever we want to use the [`pool()`](crate::traits::Repository::pool)
40/// method we now need to access the [DB_POOL](crate::pool::DB_POOL) static via the [`get_db_pool()`](crate::pool::get_db_pool).
41/// This cost however is tiny and in most cases not an issue as it will be overshadowed by the actual database request.
42///
43/// # Example of a ZST Repository
44///
45/// ```
46/// # use sqlx_utils::repository;
47/// # use sqlx_utils::traits::Model;
48///
49///
50/// # struct Person {
51/// #     id: String,
52/// #     name: String
53/// # }
54///
55/// # impl Model for Person {
56/// #     type Id = String;
57/// #
58/// #     fn get_id(&self) -> Option<Self::Id> {
59/// #         Some(self.id.clone())
60/// #     }
61/// # }
62/// #
63/// repository!{
64///     !zst
65///     PersonRepository<Person>; // The generated type `PersonRepository` will now have size of 0
66/// }
67/// ```
68#[macro_export]
69macro_rules! repository {
70    {
71        $( #[$meta:meta] )*
72        $vis:vis $ident:ident;
73    } => {
74        $(#[$meta])*
75        #[derive(Clone, Copy, Debug)]
76        $vis struct $ident {
77            /// Static Reference to the global database pool [`DB_POOL`](::sqlx_utils::pool::DB_POOL)
78            pool: &'static $crate::types::Pool,
79        }
80
81        impl ::core::ops::Deref for $ident {
82            type Target = $crate::types::Pool;
83
84            fn deref(&self) -> &Self::Target {
85                &self.pool
86            }
87        }
88
89        impl ::core::borrow::Borrow<$crate::types::Pool> for $ident {
90            fn borrow(&self) -> &$crate::types::Pool {
91                &self.pool
92            }
93        }
94
95        impl ::core::convert::AsRef<$crate::types::Pool> for $ident {
96            fn as_ref(&self) -> &$crate::types::Pool {
97                &self.pool
98            }
99        }
100
101        $crate::static_repo!($vis $ident;);
102
103        impl $ident {
104            #[inline(always)]
105            $vis fn new() -> Self {
106                let pool = $crate::pool::get_db_pool();
107
108                Self {
109                    pool
110                }
111            }
112        }
113    };
114
115    {
116        $( #[$meta:meta] )*
117        $vis:vis $ident:ident<$model:ty>;
118    } => {
119        $crate::repository!(
120            !inner
121            $(#[$meta])*
122            $vis $ident<$model>;
123        );
124    };
125
126    {
127        $( #[$meta:meta] )*
128        $vis:vis $ident:ident<$model:ty>;
129
130        $($tokens:tt)*
131    } => {
132        $crate::repository!(!inner $(#[$meta])* $vis $ident<$model>; $($tokens)*);
133    };
134
135    {
136        !inner
137        $( #[$meta:meta] )*
138        $vis:vis $ident:ident<$model:ty>;
139
140        $($tokens:tt)*
141    } => {
142        $crate::repository!($(#[$meta])* $vis $ident;);
143
144        impl $crate::traits::Repository<$model> for $ident {
145            #[inline]
146            fn pool(&self) -> & $crate::types::Pool {
147                self.pool
148            }
149            $($tokens)*
150        }
151    };
152
153    {
154        !zst
155        $( #[$meta:meta] )*
156        $vis:vis $ident:ident;
157    } => {
158        $(#[$meta])*
159        #[derive(Clone, Copy, Debug)]
160        $vis struct $ident;
161
162        $crate::static_repo!(!zst $vis $ident;);
163
164        impl $ident {
165            #[inline(always)]
166            $vis const fn new() -> Self {
167                Self
168            }
169        }
170    };
171
172    {
173        !zst
174        $( #[$meta:meta] )*
175        $vis:vis $ident:ident<$model:ty>;
176    } => {
177        $crate::repository!(
178            !zst
179            !inner
180            $(#[$meta])*
181            $vis $ident<$model>;
182        );
183    };
184
185    {
186        !zst
187        $( #[$meta:meta] )*
188        $vis:vis $ident:ident<$model:ty>;
189
190        $($tokens:tt)*
191    } => {
192        $crate::repository!(!zst !inner $(#[$meta])* $vis $ident<$model>; $($tokens)*);
193    };
194
195    {
196        !zst !inner
197        $( #[$meta:meta] )*
198        $vis:vis $ident:ident<$model:ty>;
199
200        $($tokens:tt)*
201    } => {
202        $crate::repository!(!zst $(#[$meta])* $vis $ident;);
203
204        impl $crate::traits::Repository<$model> for $ident {
205            #[inline]
206            fn pool(&self) -> & $crate::types::Pool {
207                $crate::pool::get_db_pool()
208            }
209            $($tokens)*
210        }
211    };
212}