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}