parsql_deadpool_postgres/
transaction_extensions.rs1use std::fmt::Debug;
2use std::sync::OnceLock;
3use tokio_postgres::Error;
4use deadpool_postgres::Transaction;
5
6use crate::{SqlQuery, SqlParams, FromRow, UpdateParams};
7
8#[async_trait::async_trait]
11pub trait TransactionOps {
12 async fn insert<T>(&self, entity: T) -> Result<u64, Error>
54 where
55 T: SqlQuery + SqlParams + Debug + Send + 'static;
56
57 async fn update<T>(&self, entity: T) -> Result<u64, Error>
62 where
63 T: SqlQuery + UpdateParams + SqlParams + Debug + Send + 'static;
64
65 async fn delete<T>(&self, entity: T) -> Result<u64, Error>
70 where
71 T: SqlQuery + SqlParams + Debug + Send + 'static;
72
73 async fn get<T>(&self, params: &T) -> Result<T, Error>
78 where
79 T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static;
80
81 async fn get_all<T>(&self, params: &T) -> Result<Vec<T>, Error>
86 where
87 T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static;
88
89 async fn select<T, R, F>(&self, entity: T, to_model: F) -> Result<R, Error>
95 where
96 T: SqlQuery + SqlParams + Debug + Send + 'static,
97 F: FnOnce(&tokio_postgres::Row) -> Result<R, Error> + Send + Sync + 'static,
98 R: Send + 'static;
99
100 async fn select_all<T, R, F>(&self, entity: T, to_model: F) -> Result<Vec<R>, Error>
106 where
107 T: SqlQuery + SqlParams + Debug + Send + 'static,
108 F: Fn(&tokio_postgres::Row) -> R + Send + Sync + 'static,
109 R: Send + 'static;
110}
111
112#[async_trait::async_trait]
113impl TransactionOps for Transaction<'_> {
114 async fn insert<T>(&self, entity: T) -> Result<u64, Error>
115 where
116 T: SqlQuery + SqlParams + Debug + Send + 'static,
117 {
118 let sql = T::query();
119
120 if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
121 if trace == "1" {
122 println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
123 }
124 }
125
126 let params = SqlParams::params(&entity);
127 self.execute(&sql, ¶ms[..]).await
128 }
129
130 async fn update<T>(&self, entity: T) -> Result<u64, Error>
131 where
132 T: SqlQuery + UpdateParams + SqlParams + Debug + Send + 'static,
133 {
134 let sql = T::query();
135
136 if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
137 if trace == "1" {
138 println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
139 }
140 }
141
142 let params = SqlParams::params(&entity);
143 self.execute(&sql, ¶ms[..]).await
144 }
145
146 async fn delete<T>(&self, entity: T) -> Result<u64, Error>
147 where
148 T: SqlQuery + SqlParams + Debug + Send + 'static,
149 {
150 let sql = T::query();
151
152 if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
153 if trace == "1" {
154 println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
155 }
156 }
157
158 let params = SqlParams::params(&entity);
159 self.execute(&sql, ¶ms[..]).await
160 }
161
162 async fn get<T>(&self, params: &T) -> Result<T, Error>
163 where
164 T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static,
165 {
166 let sql = T::query();
167
168 static TRACE_ENABLED: OnceLock<bool> = OnceLock::new();
169 let is_trace_enabled = *TRACE_ENABLED.get_or_init(|| {
170 std::env::var_os("PARSQL_TRACE").map_or(false, |v| v == "1")
171 });
172
173 if is_trace_enabled {
174 println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
175 }
176
177 let params_owned = params.clone();
178 let query_params = SqlParams::params(¶ms_owned);
179 let row = self.query_one(&sql, &query_params[..]).await?;
180
181 T::from_row(&row)
182 }
183
184 async fn get_all<T>(&self, params: &T) -> Result<Vec<T>, Error>
185 where
186 T: SqlQuery + FromRow + SqlParams + Debug + Send + Sync + Clone + 'static,
187 {
188 let sql = T::query();
189
190 if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
191 if trace == "1" {
192 println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
193 }
194 }
195
196 let params_owned = params.clone();
197 let query_params = SqlParams::params(¶ms_owned);
198 let rows = self.query(&sql, &query_params[..]).await?;
199
200 let mut results = Vec::with_capacity(rows.len());
201 for row in rows {
202 results.push(T::from_row(&row)?);
203 }
204
205 Ok(results)
206 }
207
208 async fn select<T, R, F>(&self, entity: T, to_model: F) -> Result<R, Error>
209 where
210 T: SqlQuery + SqlParams + Debug + Send + 'static,
211 F: FnOnce(&tokio_postgres::Row) -> Result<R, Error> + Send + Sync + 'static,
212 R: Send + 'static,
213 {
214 let sql = T::query();
215
216 if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
217 if trace == "1" {
218 println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
219 }
220 }
221
222 let params = SqlParams::params(&entity);
223 let row = self.query_one(&sql, ¶ms[..]).await?;
224 to_model(&row)
225 }
226
227 async fn select_all<T, R, F>(&self, entity: T, to_model: F) -> Result<Vec<R>, Error>
228 where
229 T: SqlQuery + SqlParams + Debug + Send + 'static,
230 F: Fn(&tokio_postgres::Row) -> R + Send + Sync + 'static,
231 R: Send + 'static,
232 {
233 let sql = T::query();
234
235 if let Some(trace) = std::env::var_os("PARSQL_TRACE") {
236 if trace == "1" {
237 println!("[PARSQL-DEADPOOL-POSTGRES-TX] Execute SQL: {}", sql);
238 }
239 }
240
241 let params = SqlParams::params(&entity);
242 let rows = self.query(&sql, ¶ms[..]).await?;
243
244 let mut results = Vec::with_capacity(rows.len());
245 for row in rows {
246 results.push(to_model(&row));
247 }
248
249 Ok(results)
250 }
251}