sqlx_core_oldapi/
executor.rs

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