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