mysql/conn/
queryable.rs

1// Copyright (c) 2020 rust-mysql-simple contributors
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use mysql_common::row::convert::FromRowError;
10
11use std::{borrow::Cow, result::Result as StdResult};
12
13use crate::{
14    conn::query_result::{Binary, Text},
15    from_row, from_row_opt,
16    prelude::FromRow,
17    Params, QueryResult, Result, Statement,
18};
19
20/// Something, that eventually is a `Statement` in the context of a `T: Queryable`.
21pub trait AsStatement {
22    /// Make a statement out of `Self`.
23    fn as_statement<Q: Queryable>(&self, queryable: &mut Q) -> Result<Cow<'_, Statement>>;
24}
25
26/// Queryable object.
27pub trait Queryable {
28    /// Perfoms text query.
29    fn query_iter<Q: AsRef<str>>(&mut self, query: Q) -> Result<QueryResult<'_, '_, '_, Text>>;
30
31    /// Performs text query and collects the first result set.
32    fn query<T, Q>(&mut self, query: Q) -> Result<Vec<T>>
33    where
34        Q: AsRef<str>,
35        T: FromRow,
36    {
37        self.query_map(query, from_row)
38    }
39
40    /// Same as [`Queryable::query`] but useful when you not sure what your schema is.
41    fn query_opt<T, Q>(&mut self, query: Q) -> Result<Vec<StdResult<T, FromRowError>>>
42    where
43        Q: AsRef<str>,
44        T: FromRow,
45    {
46        self.query_map(query, from_row_opt)
47    }
48
49    /// Performs text query and returns the first row of the first result set.
50    fn query_first<T, Q>(&mut self, query: Q) -> Result<Option<T>>
51    where
52        Q: AsRef<str>,
53        T: FromRow,
54    {
55        self.query_iter(query)?
56            .next()
57            .map(|row| row.map(from_row))
58            .transpose()
59    }
60
61    /// Same as [`Queryable::query_first`] but useful when you not sure what your schema is.
62    fn query_first_opt<T, Q>(&mut self, query: Q) -> Result<Option<StdResult<T, FromRowError>>>
63    where
64        Q: AsRef<str>,
65        T: FromRow,
66    {
67        self.query_iter(query)?
68            .next()
69            .map(|row| row.map(from_row_opt))
70            .transpose()
71    }
72
73    /// Performs text query and maps each row of the first result set.
74    fn query_map<T, F, Q, U>(&mut self, query: Q, mut f: F) -> Result<Vec<U>>
75    where
76        Q: AsRef<str>,
77        T: FromRow,
78        F: FnMut(T) -> U,
79    {
80        self.query_fold(query, Vec::new(), |mut acc, row| {
81            acc.push(f(row));
82            acc
83        })
84    }
85
86    /// Same as [`Queryable::query_map`] but useful when you not sure what your schema is.
87    fn query_map_opt<T, F, Q, U>(&mut self, query: Q, mut f: F) -> Result<Vec<U>>
88    where
89        Q: AsRef<str>,
90        T: FromRow,
91        F: FnMut(StdResult<T, FromRowError>) -> U,
92    {
93        self.query_fold_opt(query, Vec::new(), |mut acc, row| {
94            acc.push(f(row));
95            acc
96        })
97    }
98
99    /// Performs text query and folds the first result set to a single value.
100    fn query_fold<T, F, Q, U>(&mut self, query: Q, init: U, mut f: F) -> Result<U>
101    where
102        Q: AsRef<str>,
103        T: FromRow,
104        F: FnMut(U, T) -> U,
105    {
106        self.query_iter(query)?
107            .map(|row| row.map(from_row::<T>))
108            .try_fold(init, |acc, row: Result<T>| row.map(|row| f(acc, row)))
109    }
110
111    /// Same as [`Queryable::query_fold`] but useful when you not sure what your schema is.
112    fn query_fold_opt<T, F, Q, U>(&mut self, query: Q, init: U, mut f: F) -> Result<U>
113    where
114        Q: AsRef<str>,
115        T: FromRow,
116        F: FnMut(U, StdResult<T, FromRowError>) -> U,
117    {
118        self.query_iter(query)?
119            .map(|row| row.map(from_row_opt::<T>))
120            .try_fold(init, |acc, row: Result<StdResult<T, FromRowError>>| {
121                row.map(|row| f(acc, row))
122            })
123    }
124
125    /// Performs text query and drops the query result.
126    fn query_drop<Q>(&mut self, query: Q) -> Result<()>
127    where
128        Q: AsRef<str>,
129    {
130        self.query_iter(query).map(drop)
131    }
132
133    /// Prepares the given `query` as a prepared statement.
134    fn prep<Q: AsRef<str>>(&mut self, query: Q) -> Result<crate::Statement>;
135
136    /// This function will close the given statement on the server side.
137    fn close(&mut self, stmt: Statement) -> Result<()>;
138
139    /// Executes the given `stmt` with the given `params`.
140    fn exec_iter<S, P>(&mut self, stmt: S, params: P) -> Result<QueryResult<'_, '_, '_, Binary>>
141    where
142        S: AsStatement,
143        P: Into<Params>;
144
145    /// Prepares the given statement, and executes it with each item in the given params iterator.
146    fn exec_batch<S, P, I>(&mut self, stmt: S, params: I) -> Result<()>
147    where
148        Self: Sized,
149        S: AsStatement,
150        P: Into<Params>,
151        I: IntoIterator<Item = P>,
152    {
153        let stmt = stmt.as_statement(self)?;
154        for params in params {
155            self.exec_drop(stmt.as_ref(), params)?;
156        }
157
158        Ok(())
159    }
160
161    /// Executes the given `stmt` and collects the first result set.
162    fn exec<T, S, P>(&mut self, stmt: S, params: P) -> Result<Vec<T>>
163    where
164        S: AsStatement,
165        P: Into<Params>,
166        T: FromRow,
167    {
168        self.exec_map(stmt, params, from_row)
169    }
170
171    /// Same as [`Queryable::exec`] but useful when you not sure what your schema is.
172    fn exec_opt<T, S, P>(&mut self, stmt: S, params: P) -> Result<Vec<StdResult<T, FromRowError>>>
173    where
174        S: AsStatement,
175        P: Into<Params>,
176        T: FromRow,
177    {
178        self.exec_map(stmt, params, from_row_opt)
179    }
180
181    /// Executes the given `stmt` and returns the first row of the first result set.
182    fn exec_first<T, S, P>(&mut self, stmt: S, params: P) -> Result<Option<T>>
183    where
184        S: AsStatement,
185        P: Into<Params>,
186        T: FromRow,
187    {
188        self.exec_iter(stmt, params)?
189            .next()
190            .map(|row| row.map(crate::from_row))
191            .transpose()
192    }
193
194    /// Same as [`Queryable::exec_first`] but useful when you not sure what your schema is.
195    fn exec_first_opt<T, S, P>(
196        &mut self,
197        stmt: S,
198        params: P,
199    ) -> Result<Option<StdResult<T, FromRowError>>>
200    where
201        S: AsStatement,
202        P: Into<Params>,
203        T: FromRow,
204    {
205        self.exec_iter(stmt, params)?
206            .next()
207            .map(|row| row.map(from_row_opt))
208            .transpose()
209    }
210
211    /// Executes the given `stmt` and maps each row of the first result set.
212    fn exec_map<T, S, P, F, U>(&mut self, stmt: S, params: P, mut f: F) -> Result<Vec<U>>
213    where
214        S: AsStatement,
215        P: Into<Params>,
216        T: FromRow,
217        F: FnMut(T) -> U,
218    {
219        self.exec_fold(stmt, params, Vec::new(), |mut acc, row| {
220            acc.push(f(row));
221            acc
222        })
223    }
224
225    /// Same as [`Queryable::exec_map`] but useful when you not sure what your schema is.
226    fn exec_map_opt<T, S, P, F, U>(&mut self, stmt: S, params: P, mut f: F) -> Result<Vec<U>>
227    where
228        S: AsStatement,
229        P: Into<Params>,
230        T: FromRow,
231        F: FnMut(StdResult<T, FromRowError>) -> U,
232    {
233        self.exec_fold_opt(stmt, params, Vec::new(), |mut acc, row| {
234            acc.push(f(row));
235            acc
236        })
237    }
238
239    /// Executes the given `stmt` and folds the first result set to a signel value.
240    fn exec_fold<T, S, P, U, F>(&mut self, stmt: S, params: P, init: U, mut f: F) -> Result<U>
241    where
242        S: AsStatement,
243        P: Into<Params>,
244        T: FromRow,
245        F: FnMut(U, T) -> U,
246    {
247        let mut result = self.exec_iter(stmt, params)?;
248        result.try_fold(init, |init, row| row.map(|row| f(init, from_row(row))))
249    }
250
251    /// Same as [`Queryable::exec_fold`] but useful when you not sure what your schema is.
252    fn exec_fold_opt<T, S, P, U, F>(&mut self, stmt: S, params: P, init: U, mut f: F) -> Result<U>
253    where
254        S: AsStatement,
255        P: Into<Params>,
256        T: FromRow,
257        F: FnMut(U, StdResult<T, FromRowError>) -> U,
258    {
259        let mut result = self.exec_iter(stmt, params)?;
260        result.try_fold(init, |init, row| row.map(|row| f(init, from_row_opt(row))))
261    }
262
263    /// Executes the given `stmt` and drops the result.
264    fn exec_drop<S, P>(&mut self, stmt: S, params: P) -> Result<()>
265    where
266        S: AsStatement,
267        P: Into<Params>,
268    {
269        self.exec_iter(stmt, params).map(drop)
270    }
271}