Skip to main content

sqlx_core/
executor.rs

1use crate::database::Database;
2use crate::error::{BoxDynError, Error};
3use crate::sql_str::{SqlSafeStr, SqlStr};
4
5use either::Either;
6use futures_core::future::BoxFuture;
7use futures_core::stream::BoxStream;
8use futures_util::{FutureExt, StreamExt, TryFutureExt, TryStreamExt};
9use std::{fmt::Debug, future};
10
11/// A type that contains or can provide a database
12/// connection to use for executing queries against the database.
13///
14/// No guarantees are provided that successive queries run on the same
15/// physical database connection.
16///
17/// A [`Connection`](crate::connection::Connection) is an `Executor` that guarantees that
18/// successive queries are ran on the same physical database connection.
19///
20/// Implemented for the following:
21///
22///  * [`&Pool`](super::pool::Pool)
23///  * [`&mut Connection`](super::connection::Connection)
24///
25/// The [`Executor`] impls for [`Transaction`](crate::transaction::Transaction)
26/// and [`PoolConnection`](crate::pool::PoolConnection) have been deleted because they
27/// cannot exist in the new crate architecture without rewriting the Executor trait entirely.
28/// To fix this breakage, simply add a dereference where an impl [`Executor`] is expected, as
29/// they both dereference to the inner connection type which will still implement it:
30/// * `&mut transaction` -> `&mut *transaction`
31/// * `&mut connection` -> `&mut *connection`
32///
33pub trait Executor<'c>: Send + Debug + Sized {
34    type Database: Database;
35
36    /// Execute the query and return the total number of rows affected.
37    fn execute<'e, 'q: 'e, E>(
38        self,
39        query: E,
40    ) -> BoxFuture<'e, Result<<Self::Database as Database>::QueryResult, Error>>
41    where
42        'c: 'e,
43        E: 'q + Execute<'q, Self::Database>,
44    {
45        self.execute_many(query).try_collect().boxed()
46    }
47
48    /// Execute multiple queries and return the rows affected from each query, in a stream.
49    fn execute_many<'e, 'q: 'e, E>(
50        self,
51        query: E,
52    ) -> BoxStream<'e, Result<<Self::Database as Database>::QueryResult, Error>>
53    where
54        'c: 'e,
55        E: 'q + Execute<'q, Self::Database>,
56    {
57        self.fetch_many(query)
58            .try_filter_map(|step| async move {
59                Ok(match step {
60                    Either::Left(rows) => Some(rows),
61                    Either::Right(_) => None,
62                })
63            })
64            .boxed()
65    }
66
67    /// Execute the query and return the generated results as a stream.
68    fn fetch<'e, 'q: 'e, E>(
69        self,
70        query: E,
71    ) -> BoxStream<'e, Result<<Self::Database as Database>::Row, Error>>
72    where
73        'c: 'e,
74        E: 'q + Execute<'q, Self::Database>,
75    {
76        self.fetch_many(query)
77            .try_filter_map(|step| async move {
78                Ok(match step {
79                    Either::Left(_) => None,
80                    Either::Right(row) => Some(row),
81                })
82            })
83            .boxed()
84    }
85
86    /// Execute multiple queries and return the generated results as a stream
87    /// from each query, in a stream.
88    fn fetch_many<'e, 'q: 'e, E>(
89        self,
90        query: E,
91    ) -> BoxStream<
92        'e,
93        Result<
94            Either<<Self::Database as Database>::QueryResult, <Self::Database as Database>::Row>,
95            Error,
96        >,
97    >
98    where
99        'c: 'e,
100        E: 'q + Execute<'q, Self::Database>;
101
102    /// Execute the query and return all the generated results, collected into a [`Vec`].
103    fn fetch_all<'e, 'q: 'e, E>(
104        self,
105        query: E,
106    ) -> BoxFuture<'e, Result<Vec<<Self::Database as Database>::Row>, Error>>
107    where
108        'c: 'e,
109        E: 'q + Execute<'q, Self::Database>,
110    {
111        self.fetch(query).try_collect().boxed()
112    }
113
114    /// Execute the query and returns exactly one row.
115    fn fetch_one<'e, 'q: 'e, E>(
116        self,
117        query: E,
118    ) -> BoxFuture<'e, Result<<Self::Database as Database>::Row, Error>>
119    where
120        'c: 'e,
121        E: 'q + Execute<'q, Self::Database>,
122    {
123        self.fetch_optional(query)
124            .and_then(|row| {
125                future::ready(match row {
126                    Some(row) => Ok(row),
127                    None => Err(Error::RowNotFound),
128                })
129            })
130            .boxed()
131    }
132
133    /// Execute the query and returns at most one row.
134    fn fetch_optional<'e, 'q: 'e, E>(
135        self,
136        query: E,
137    ) -> BoxFuture<'e, Result<Option<<Self::Database as Database>::Row>, Error>>
138    where
139        'c: 'e,
140        E: 'q + Execute<'q, Self::Database>;
141
142    /// Prepare the SQL query to inspect the type information of its parameters
143    /// and results.
144    ///
145    /// Be advised that when using the `query`, `query_as`, or `query_scalar` functions, the query
146    /// is transparently prepared and executed.
147    ///
148    /// This explicit API is provided to allow access to the statement metadata available after
149    /// it prepared but before the first row is returned.
150    #[inline]
151    fn prepare<'e>(
152        self,
153        query: SqlStr,
154    ) -> BoxFuture<'e, Result<<Self::Database as Database>::Statement, Error>>
155    where
156        'c: 'e,
157    {
158        self.prepare_with(query, &[])
159    }
160
161    /// Prepare the SQL query, with parameter type information, to inspect the
162    /// type information about its parameters and results.
163    ///
164    /// Only some database drivers (PostgreSQL, MSSQL) can take advantage of
165    /// this extra information to influence parameter type inference.
166    fn prepare_with<'e>(
167        self,
168        sql: SqlStr,
169        parameters: &'e [<Self::Database as Database>::TypeInfo],
170    ) -> BoxFuture<'e, Result<<Self::Database as Database>::Statement, Error>>
171    where
172        'c: 'e;
173
174    /// Describe the SQL query and return type information about its parameters
175    /// and results.
176    ///
177    /// This is used by compile-time verification in the query macros to
178    /// power their type inference.
179    #[doc(hidden)]
180    #[cfg(feature = "offline")]
181    fn describe<'e>(
182        self,
183        sql: SqlStr,
184    ) -> BoxFuture<'e, Result<crate::describe::Describe<Self::Database>, Error>>
185    where
186        'c: 'e;
187}
188
189/// A type that may be executed against a database connection.
190///
191/// Implemented for the following:
192///
193///  * [`&str`](std::str)
194///  * [`Query`](super::query::Query)
195///
196pub trait Execute<'q, DB: Database>: Send + Sized {
197    /// Gets the SQL that will be executed.
198    fn sql(self) -> SqlStr;
199
200    /// Gets the previously cached statement, if available.
201    fn statement(&self) -> Option<&DB::Statement>;
202
203    /// Returns the arguments to be bound against the query string.
204    ///
205    /// Returning `Ok(None)` for `Arguments` indicates to use a "simple" query protocol and to not
206    /// prepare the query. Returning `Ok(Some(Default::default()))` is an empty arguments object that
207    /// will be prepared (and cached) before execution.
208    ///
209    /// Returns `Err` if encoding any of the arguments failed.
210    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError>;
211
212    /// Returns `true` if the statement should be cached.
213    fn persistent(&self) -> bool;
214}
215
216impl<DB: Database, T> Execute<'_, DB> for T
217where
218    T: SqlSafeStr + Send,
219{
220    #[inline]
221    fn sql(self) -> SqlStr {
222        self.into_sql_str()
223    }
224
225    #[inline]
226    fn statement(&self) -> Option<&DB::Statement> {
227        None
228    }
229
230    #[inline]
231    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError> {
232        Ok(None)
233    }
234
235    #[inline]
236    fn persistent(&self) -> bool {
237        true
238    }
239}
240
241impl<DB: Database, T> Execute<'_, DB> for (T, Option<<DB as Database>::Arguments>)
242where
243    T: SqlSafeStr + Send,
244{
245    #[inline]
246    fn sql(self) -> SqlStr {
247        self.0.into_sql_str()
248    }
249
250    #[inline]
251    fn statement(&self) -> Option<&DB::Statement> {
252        None
253    }
254
255    #[inline]
256    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError> {
257        Ok(self.1.take())
258    }
259
260    #[inline]
261    fn persistent(&self) -> bool {
262        true
263    }
264}