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}