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///
33/// # Note: Methods Not for General Use
34/// This is a building-block trait that is exposed mainly for use as a trait bound.
35///
36/// Instead of calling the methods of this trait, use the free functions in the `sqlx` crate root:
37/// * [`sqlx::query()`]: use for DML queries (`SELECT`, `INSERT`, `UPDATE`, `DELETE`, etc.)
38///     * uses and caches prepared statements internally per-connection
39///     * may use argument placeholders (MySQL/MariaDB: `?`, Postgres/SQLite: `$1`, `$2`, etc.)
40///     * one query per string
41/// * [`sqlx::query_as()`], [`sqlx::query_scalar()`]: preferred for DML queries with type mapping
42/// * [`sqlx::raw_sql()`]: for DDL (`CREATE`, `ALTER`, etc.), batch queries and administration functions
43///     * accepts multiple queries separated by semicolons (`;`) in the same string
44///     * never uses prepared statements
45///
46/// Consider also the `query!()` family of macros, which offer queries and type mapping checked
47/// at compile-time.
48///
49/// [`sqlx::query()`]: crate::query::query
50/// [`sqlx::query_as()`]: crate::query_as::query_as
51/// [`sqlx::query_scalar()`]: crate::query_scalar::query_scalar
52/// [`sqlx::raw_sql()`]: crate::raw_sql::raw_sql
53pub trait Executor<'c>: Send + Debug + Sized {
54    type Database: Database;
55
56    /// Execute the query and return the total number of rows affected.
57    fn execute<'e, 'q: 'e, E>(
58        self,
59        query: E,
60    ) -> BoxFuture<'e, Result<<Self::Database as Database>::QueryResult, Error>>
61    where
62        'c: 'e,
63        E: 'q + Execute<'q, Self::Database>,
64    {
65        self.execute_many(query).try_collect().boxed()
66    }
67
68    /// Execute multiple queries and return the rows affected from each query, in a stream.
69    fn execute_many<'e, 'q: 'e, E>(
70        self,
71        query: E,
72    ) -> BoxStream<'e, Result<<Self::Database as Database>::QueryResult, 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(rows) => Some(rows),
81                    Either::Right(_) => None,
82                })
83            })
84            .boxed()
85    }
86
87    /// Execute the query and return the generated results as a stream.
88    fn fetch<'e, 'q: 'e, E>(
89        self,
90        query: E,
91    ) -> BoxStream<'e, Result<<Self::Database as Database>::Row, Error>>
92    where
93        'c: 'e,
94        E: 'q + Execute<'q, Self::Database>,
95    {
96        self.fetch_many(query)
97            .try_filter_map(|step| async move {
98                Ok(match step {
99                    Either::Left(_) => None,
100                    Either::Right(row) => Some(row),
101                })
102            })
103            .boxed()
104    }
105
106    /// Execute multiple queries and return the generated results as a stream
107    /// from each query, in a stream.
108    fn fetch_many<'e, 'q: 'e, E>(
109        self,
110        query: E,
111    ) -> BoxStream<
112        'e,
113        Result<
114            Either<<Self::Database as Database>::QueryResult, <Self::Database as Database>::Row>,
115            Error,
116        >,
117    >
118    where
119        'c: 'e,
120        E: 'q + Execute<'q, Self::Database>;
121
122    /// Execute the query and return all the generated results, collected into a [`Vec`].
123    fn fetch_all<'e, 'q: 'e, E>(
124        self,
125        query: E,
126    ) -> BoxFuture<'e, Result<Vec<<Self::Database as Database>::Row>, Error>>
127    where
128        'c: 'e,
129        E: 'q + Execute<'q, Self::Database>,
130    {
131        self.fetch(query).try_collect().boxed()
132    }
133
134    /// Execute the query and returns exactly one row.
135    fn fetch_one<'e, 'q: 'e, E>(
136        self,
137        query: E,
138    ) -> BoxFuture<'e, Result<<Self::Database as Database>::Row, Error>>
139    where
140        'c: 'e,
141        E: 'q + Execute<'q, Self::Database>,
142    {
143        self.fetch_optional(query)
144            .and_then(|row| {
145                future::ready(match row {
146                    Some(row) => Ok(row),
147                    None => Err(Error::RowNotFound),
148                })
149            })
150            .boxed()
151    }
152
153    /// Execute the query and returns at most one row.
154    fn fetch_optional<'e, 'q: 'e, E>(
155        self,
156        query: E,
157    ) -> BoxFuture<'e, Result<Option<<Self::Database as Database>::Row>, Error>>
158    where
159        'c: 'e,
160        E: 'q + Execute<'q, Self::Database>;
161
162    /// Prepare the SQL query to inspect the type information of its parameters
163    /// and results.
164    ///
165    /// Be advised that when using the `query`, `query_as`, or `query_scalar` functions, the query
166    /// is transparently prepared and executed.
167    ///
168    /// This explicit API is provided to allow access to the statement metadata available after
169    /// it prepared but before the first row is returned.
170    #[inline]
171    fn prepare<'e>(
172        self,
173        query: SqlStr,
174    ) -> BoxFuture<'e, Result<<Self::Database as Database>::Statement, Error>>
175    where
176        'c: 'e,
177    {
178        self.prepare_with(query, &[])
179    }
180
181    /// Prepare the SQL query, with parameter type information, to inspect the
182    /// type information about its parameters and results.
183    ///
184    /// Only some database drivers (PostgreSQL, MSSQL) can take advantage of
185    /// this extra information to influence parameter type inference.
186    fn prepare_with<'e>(
187        self,
188        sql: SqlStr,
189        parameters: &'e [<Self::Database as Database>::TypeInfo],
190    ) -> BoxFuture<'e, Result<<Self::Database as Database>::Statement, Error>>
191    where
192        'c: 'e;
193
194    /// Describe the SQL query and return type information about its parameters
195    /// and results.
196    ///
197    /// This is used by compile-time verification in the query macros to
198    /// power their type inference.
199    #[doc(hidden)]
200    #[cfg(feature = "offline")]
201    fn describe<'e>(
202        self,
203        sql: SqlStr,
204    ) -> BoxFuture<'e, Result<crate::describe::Describe<Self::Database>, Error>>
205    where
206        'c: 'e;
207}
208
209/// A type that may be executed against a database connection.
210///
211/// Implemented for the following:
212///
213///  * [`&str`](std::str)
214///  * [`Query`](super::query::Query)
215///
216pub trait Execute<'q, DB: Database>: Send + Sized {
217    /// Gets the SQL that will be executed.
218    fn sql(self) -> SqlStr;
219
220    /// Gets the previously cached statement, if available.
221    fn statement(&self) -> Option<&DB::Statement>;
222
223    /// Returns the arguments to be bound against the query string.
224    ///
225    /// Returning `Ok(None)` for `Arguments` indicates to use a "simple" query protocol and to not
226    /// prepare the query. Returning `Ok(Some(Default::default()))` is an empty arguments object that
227    /// will be prepared (and cached) before execution.
228    ///
229    /// Returns `Err` if encoding any of the arguments failed.
230    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError>;
231
232    /// Returns `true` if the statement should be cached.
233    fn persistent(&self) -> bool;
234}
235
236impl<DB: Database, T> Execute<'_, DB> for T
237where
238    T: SqlSafeStr + Send,
239{
240    #[inline]
241    fn sql(self) -> SqlStr {
242        self.into_sql_str()
243    }
244
245    #[inline]
246    fn statement(&self) -> Option<&DB::Statement> {
247        None
248    }
249
250    #[inline]
251    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError> {
252        Ok(None)
253    }
254
255    #[inline]
256    fn persistent(&self) -> bool {
257        true
258    }
259}
260
261impl<DB: Database, T> Execute<'_, DB> for (T, Option<<DB as Database>::Arguments>)
262where
263    T: SqlSafeStr + Send,
264{
265    #[inline]
266    fn sql(self) -> SqlStr {
267        self.0.into_sql_str()
268    }
269
270    #[inline]
271    fn statement(&self) -> Option<&DB::Statement> {
272        None
273    }
274
275    #[inline]
276    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError> {
277        Ok(self.1.take())
278    }
279
280    #[inline]
281    fn persistent(&self) -> bool {
282        true
283    }
284}