1use mysql_common::row::convert::FromRowError;
10
11use std::{convert::TryInto, result::Result as StdResult};
12
13use crate::{
14 conn::{queryable::AsStatement, ConnMut},
15 from_row, from_row_opt,
16 prelude::FromRow,
17 Binary, Error, Params, QueryResult, Result, Text,
18};
19
20pub trait TextQuery: Sized {
39 fn run<'a, 'b, 'c, C>(self, conn: C) -> Result<QueryResult<'a, 'b, 'c, Text>>
41 where
42 C: TryInto<ConnMut<'a, 'b, 'c>>,
43 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>;
44
45 fn first<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Option<T>>
47 where
48 C: TryInto<ConnMut<'a, 'b, 'c>>,
49 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
50 T: FromRow,
51 {
52 self.run(conn)?
53 .next()
54 .map(|row| row.map(from_row))
55 .transpose()
56 }
57
58 fn first_opt<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Option<StdResult<T, FromRowError>>>
60 where
61 C: TryInto<ConnMut<'a, 'b, 'c>>,
62 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
63 T: FromRow,
64 {
65 self.run(conn)?
66 .next()
67 .map(|row| row.map(from_row_opt))
68 .transpose()
69 }
70
71 fn fetch<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Vec<T>>
73 where
74 C: TryInto<ConnMut<'a, 'b, 'c>>,
75 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
76 T: FromRow,
77 {
78 self.run(conn)?.map(|rrow| rrow.map(from_row)).collect()
79 }
80
81 fn fetch_opt<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Vec<StdResult<T, FromRowError>>>
83 where
84 C: TryInto<ConnMut<'a, 'b, 'c>>,
85 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
86 T: FromRow,
87 {
88 self.run(conn)?.map(|rrow| rrow.map(from_row_opt)).collect()
89 }
90
91 fn fold<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut init: U, mut next: F) -> Result<U>
93 where
94 C: TryInto<ConnMut<'a, 'b, 'c>>,
95 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
96 T: FromRow,
97 F: FnMut(U, T) -> U,
98 {
99 for row in self.run(conn)? {
100 init = next(init, from_row(row?));
101 }
102
103 Ok(init)
104 }
105
106 fn fold_opt<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut init: U, mut next: F) -> Result<U>
108 where
109 C: TryInto<ConnMut<'a, 'b, 'c>>,
110 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
111 T: FromRow,
112 F: FnMut(U, StdResult<T, FromRowError>) -> U,
113 {
114 for row in self.run(conn)? {
115 init = next(init, from_row_opt(row?));
116 }
117
118 Ok(init)
119 }
120
121 fn map<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut map: F) -> Result<Vec<U>>
123 where
124 C: TryInto<ConnMut<'a, 'b, 'c>>,
125 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
126 T: FromRow,
127 F: FnMut(T) -> U,
128 {
129 self.fold(conn, Vec::new(), |mut acc, row: T| {
130 acc.push(map(row));
131 acc
132 })
133 }
134
135 fn map_opt<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut map: F) -> Result<Vec<U>>
137 where
138 C: TryInto<ConnMut<'a, 'b, 'c>>,
139 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
140 T: FromRow,
141 F: FnMut(StdResult<T, FromRowError>) -> U,
142 {
143 self.fold_opt(
144 conn,
145 Vec::new(),
146 |mut acc, row: StdResult<T, FromRowError>| {
147 acc.push(map(row));
148 acc
149 },
150 )
151 }
152}
153
154impl<Q: AsRef<str>> TextQuery for Q {
155 fn run<'a, 'b, 'c, C>(self, conn: C) -> Result<QueryResult<'a, 'b, 'c, Text>>
156 where
157 C: TryInto<ConnMut<'a, 'b, 'c>>,
158 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
159 {
160 let mut conn = conn.try_into()?;
161 let meta = conn._query(self.as_ref())?;
162 Ok(QueryResult::new(conn, meta))
163 }
164}
165
166#[derive(Debug, Clone, PartialEq, Eq)]
170pub struct QueryWithParams<Q, P> {
171 pub query: Q,
172 pub params: P,
173}
174
175pub trait WithParams: Sized {
177 fn with<P>(self, params: P) -> QueryWithParams<Self, P>;
178}
179
180impl<T: AsRef<str>> WithParams for T {
181 fn with<P>(self, params: P) -> QueryWithParams<Self, P> {
182 QueryWithParams {
183 query: self,
184 params,
185 }
186 }
187}
188
189pub trait BinQuery: Sized {
210 fn run<'a, 'b, 'c, C>(self, conn: C) -> Result<QueryResult<'a, 'b, 'c, Binary>>
212 where
213 C: TryInto<ConnMut<'a, 'b, 'c>>,
214 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>;
215
216 fn first<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Option<T>>
218 where
219 C: TryInto<ConnMut<'a, 'b, 'c>>,
220 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
221 T: FromRow,
222 {
223 self.run(conn)?
224 .next()
225 .map(|row| row.map(from_row))
226 .transpose()
227 }
228
229 fn first_opt<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Option<StdResult<T, FromRowError>>>
231 where
232 C: TryInto<ConnMut<'a, 'b, 'c>>,
233 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
234 T: FromRow,
235 {
236 self.run(conn)?
237 .next()
238 .map(|row| row.map(from_row_opt))
239 .transpose()
240 }
241
242 fn fetch<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Vec<T>>
244 where
245 C: TryInto<ConnMut<'a, 'b, 'c>>,
246 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
247 T: FromRow,
248 {
249 self.run(conn)?.map(|rrow| rrow.map(from_row)).collect()
250 }
251
252 fn fetch_opt<'a, 'b, 'c: 'b, T, C>(self, conn: C) -> Result<Vec<StdResult<T, FromRowError>>>
254 where
255 C: TryInto<ConnMut<'a, 'b, 'c>>,
256 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
257 T: FromRow,
258 {
259 self.run(conn)?.map(|rrow| rrow.map(from_row_opt)).collect()
260 }
261
262 fn fold<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut init: U, mut next: F) -> Result<U>
264 where
265 C: TryInto<ConnMut<'a, 'b, 'c>>,
266 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
267 T: FromRow,
268 F: FnMut(U, T) -> U,
269 {
270 for row in self.run(conn)? {
271 init = next(init, from_row(row?));
272 }
273
274 Ok(init)
275 }
276
277 fn fold_opt<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut init: U, mut next: F) -> Result<U>
279 where
280 C: TryInto<ConnMut<'a, 'b, 'c>>,
281 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
282 T: FromRow,
283 F: FnMut(U, StdResult<T, FromRowError>) -> U,
284 {
285 for row in self.run(conn)? {
286 init = next(init, from_row_opt(row?));
287 }
288
289 Ok(init)
290 }
291
292 fn map<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut map: F) -> Result<Vec<U>>
294 where
295 C: TryInto<ConnMut<'a, 'b, 'c>>,
296 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
297 T: FromRow,
298 F: FnMut(T) -> U,
299 {
300 self.fold(conn, Vec::new(), |mut acc, row: T| {
301 acc.push(map(row));
302 acc
303 })
304 }
305
306 fn map_opt<'a, 'b, 'c: 'b, T, U, F, C>(self, conn: C, mut map: F) -> Result<Vec<U>>
308 where
309 C: TryInto<ConnMut<'a, 'b, 'c>>,
310 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
311 T: FromRow,
312 F: FnMut(StdResult<T, FromRowError>) -> U,
313 {
314 self.fold_opt(
315 conn,
316 Vec::new(),
317 |mut acc, row: StdResult<T, FromRowError>| {
318 acc.push(map(row));
319 acc
320 },
321 )
322 }
323}
324
325impl<Q, P> BinQuery for QueryWithParams<Q, P>
326where
327 Q: AsStatement,
328 P: Into<Params>,
329{
330 fn run<'a, 'b, 'c, C>(self, conn: C) -> Result<QueryResult<'a, 'b, 'c, Binary>>
331 where
332 C: TryInto<ConnMut<'a, 'b, 'c>>,
333 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
334 {
335 let mut conn = conn.try_into()?;
336 let statement = self.query.as_statement(&mut *conn)?;
337 let meta = conn._execute(&*statement, self.params.into())?;
338 Ok(QueryResult::new(conn, meta))
339 }
340}
341
342pub trait BatchQuery {
362 fn batch<'a, 'b, 'c: 'b, C>(self, conn: C) -> Result<()>
363 where
364 C: TryInto<ConnMut<'a, 'b, 'c>>,
365 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>;
366}
367
368impl<Q, I, P> BatchQuery for QueryWithParams<Q, I>
369where
370 Q: AsStatement,
371 I: IntoIterator<Item = P>,
372 P: Into<Params>,
373{
374 fn batch<'a, 'b, 'c: 'b, C>(self, conn: C) -> Result<()>
376 where
377 C: TryInto<ConnMut<'a, 'b, 'c>>,
378 Error: From<<C as TryInto<ConnMut<'a, 'b, 'c>>>::Error>,
379 {
380 let mut conn = conn.try_into()?;
381 let statement = self.query.as_statement(&mut *conn)?;
382
383 for params in self.params {
384 let params = params.into();
385 let meta = conn._execute(&*statement, params)?;
386 let mut query_result = QueryResult::<Binary>::new((&mut *conn).into(), meta);
387 while let Some(result_set) = query_result.iter() {
388 for row in result_set {
389 row?;
390 }
391 }
392 }
393
394 Ok(())
395 }
396}