sqlx_build_trust_core/query.rs
1use std::marker::PhantomData;
2
3use either::Either;
4use futures_core::stream::BoxStream;
5use futures_util::{future, StreamExt, TryFutureExt, TryStreamExt};
6
7use crate::arguments::{Arguments, IntoArguments};
8use crate::database::{Database, HasArguments, HasStatement, HasStatementCache};
9use crate::encode::Encode;
10use crate::error::Error;
11use crate::executor::{Execute, Executor};
12use crate::statement::Statement;
13use crate::types::Type;
14
15/// A single SQL query as a prepared statement. Returned by [`query()`].
16#[must_use = "query must be executed to affect database"]
17pub struct Query<'q, DB: Database, A> {
18 pub(crate) statement: Either<&'q str, &'q <DB as HasStatement<'q>>::Statement>,
19 pub(crate) arguments: Option<A>,
20 pub(crate) database: PhantomData<DB>,
21 pub(crate) persistent: bool,
22}
23
24/// A single SQL query that will map its results to an owned Rust type.
25///
26/// Executes as a prepared statement.
27///
28/// Returned by [`Query::try_map`], `query!()`, etc. Has most of the same methods as [`Query`] but
29/// the return types are changed to reflect the mapping. However, there is no equivalent of
30/// [`Query::execute`] as it doesn't make sense to map the result type and then ignore it.
31///
32/// [`Query::bind`] is also omitted; stylistically we recommend placing your `.bind()` calls
33/// before `.try_map()`. This is also to prevent adding superfluous binds to the result of
34/// `query!()` et al.
35#[must_use = "query must be executed to affect database"]
36pub struct Map<'q, DB: Database, F, A> {
37 inner: Query<'q, DB, A>,
38 mapper: F,
39}
40
41impl<'q, DB, A> Execute<'q, DB> for Query<'q, DB, A>
42where
43 DB: Database,
44 A: Send + IntoArguments<'q, DB>,
45{
46 #[inline]
47 fn sql(&self) -> &'q str {
48 match self.statement {
49 Either::Right(ref statement) => statement.sql(),
50 Either::Left(sql) => sql,
51 }
52 }
53
54 fn statement(&self) -> Option<&<DB as HasStatement<'q>>::Statement> {
55 match self.statement {
56 Either::Right(ref statement) => Some(&statement),
57 Either::Left(_) => None,
58 }
59 }
60
61 #[inline]
62 fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments> {
63 self.arguments.take().map(IntoArguments::into_arguments)
64 }
65
66 #[inline]
67 fn persistent(&self) -> bool {
68 self.persistent
69 }
70}
71
72impl<'q, DB: Database> Query<'q, DB, <DB as HasArguments<'q>>::Arguments> {
73 /// Bind a value for use with this SQL query.
74 ///
75 /// If the number of times this is called does not match the number of bind parameters that
76 /// appear in the query (`?` for most SQL flavors, `$1 .. $N` for Postgres) then an error
77 /// will be returned when this query is executed.
78 ///
79 /// There is no validation that the value is of the type expected by the query. Most SQL
80 /// flavors will perform type coercion (Postgres will return a database error).
81 pub fn bind<T: 'q + Send + Encode<'q, DB> + Type<DB>>(mut self, value: T) -> Self {
82 if let Some(arguments) = &mut self.arguments {
83 arguments.add(value);
84 }
85
86 self
87 }
88}
89
90impl<'q, DB, A> Query<'q, DB, A>
91where
92 DB: Database + HasStatementCache,
93{
94 /// If `true`, the statement will get prepared once and cached to the
95 /// connection's statement cache.
96 ///
97 /// If queried once with the flag set to `true`, all subsequent queries
98 /// matching the one with the flag will use the cached statement until the
99 /// cache is cleared.
100 ///
101 /// If `false`, the prepared statement will be closed after execution.
102 ///
103 /// Default: `true`.
104 pub fn persistent(mut self, value: bool) -> Self {
105 self.persistent = value;
106 self
107 }
108}
109
110impl<'q, DB, A: Send> Query<'q, DB, A>
111where
112 DB: Database,
113 A: 'q + IntoArguments<'q, DB>,
114{
115 /// Map each row in the result to another type.
116 ///
117 /// See [`try_map`](Query::try_map) for a fallible version of this method.
118 ///
119 /// The [`query_as`](super::query_as::query_as) method will construct a mapped query using
120 /// a [`FromRow`](super::from_row::FromRow) implementation.
121 #[inline]
122 pub fn map<F, O>(
123 self,
124 mut f: F,
125 ) -> Map<'q, DB, impl FnMut(DB::Row) -> Result<O, Error> + Send, A>
126 where
127 F: FnMut(DB::Row) -> O + Send,
128 O: Unpin,
129 {
130 self.try_map(move |row| Ok(f(row)))
131 }
132
133 /// Map each row in the result to another type.
134 ///
135 /// The [`query_as`](super::query_as::query_as) method will construct a mapped query using
136 /// a [`FromRow`](super::from_row::FromRow) implementation.
137 #[inline]
138 pub fn try_map<F, O>(self, f: F) -> Map<'q, DB, F, A>
139 where
140 F: FnMut(DB::Row) -> Result<O, Error> + Send,
141 O: Unpin,
142 {
143 Map {
144 inner: self,
145 mapper: f,
146 }
147 }
148
149 /// Execute the query and return the total number of rows affected.
150 #[inline]
151 pub async fn execute<'e, 'c: 'e, E>(self, executor: E) -> Result<DB::QueryResult, Error>
152 where
153 'q: 'e,
154 A: 'e,
155 E: Executor<'c, Database = DB>,
156 {
157 executor.execute(self).await
158 }
159
160 /// Execute multiple queries and return the rows affected from each query, in a stream.
161 #[inline]
162 #[deprecated = "Only the SQLite driver supports multiple statements in one prepared statement and that behavior is deprecated. Use `sqlx::raw_sql()` instead. See https://github.com/launchbadge/sqlx/issues/3108 for discussion."]
163 pub async fn execute_many<'e, 'c: 'e, E>(
164 self,
165 executor: E,
166 ) -> BoxStream<'e, Result<DB::QueryResult, Error>>
167 where
168 'q: 'e,
169 A: 'e,
170 E: Executor<'c, Database = DB>,
171 {
172 executor.execute_many(self)
173 }
174
175 /// Execute the query and return the generated results as a stream.
176 #[inline]
177 pub fn fetch<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<DB::Row, Error>>
178 where
179 'q: 'e,
180 A: 'e,
181 E: Executor<'c, Database = DB>,
182 {
183 executor.fetch(self)
184 }
185
186 /// Execute multiple queries and return the generated results as a stream.
187 ///
188 /// For each query in the stream, any generated rows are returned first,
189 /// then the `QueryResult` with the number of rows affected.
190 #[inline]
191 #[deprecated = "Only the SQLite driver supports multiple statements in one prepared statement and that behavior is deprecated. Use `sqlx::raw_sql()` instead. See https://github.com/launchbadge/sqlx/issues/3108 for discussion."]
192 // TODO: we'll probably still want a way to get the `DB::QueryResult` at the end of a `fetch()` stream.
193 pub fn fetch_many<'e, 'c: 'e, E>(
194 self,
195 executor: E,
196 ) -> BoxStream<'e, Result<Either<DB::QueryResult, DB::Row>, Error>>
197 where
198 'q: 'e,
199 A: 'e,
200 E: Executor<'c, Database = DB>,
201 {
202 executor.fetch_many(self)
203 }
204
205 /// Execute the query and return all the resulting rows collected into a [`Vec`].
206 ///
207 /// ### Note: beware result set size.
208 /// This will attempt to collect the full result set of the query into memory.
209 ///
210 /// To avoid exhausting available memory, ensure the result set has a known upper bound,
211 /// e.g. using `LIMIT`.
212 #[inline]
213 pub async fn fetch_all<'e, 'c: 'e, E>(self, executor: E) -> Result<Vec<DB::Row>, Error>
214 where
215 'q: 'e,
216 A: 'e,
217 E: Executor<'c, Database = DB>,
218 {
219 executor.fetch_all(self).await
220 }
221
222 /// Execute the query, returning the first row or [`Error::RowNotFound`] otherwise.
223 ///
224 /// ### Note: for best performance, ensure the query returns at most one row.
225 /// Depending on the driver implementation, if your query can return more than one row,
226 /// it may lead to wasted CPU time and bandwidth on the database server.
227 ///
228 /// Even when the driver implementation takes this into account, ensuring the query returns at most one row
229 /// can result in a more optimal query plan.
230 ///
231 /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
232 ///
233 /// Otherwise, you might want to add `LIMIT 1` to your query.
234 #[inline]
235 pub async fn fetch_one<'e, 'c: 'e, E>(self, executor: E) -> Result<DB::Row, Error>
236 where
237 'q: 'e,
238 A: 'e,
239 E: Executor<'c, Database = DB>,
240 {
241 executor.fetch_one(self).await
242 }
243
244 /// Execute the query, returning the first row or `None` otherwise.
245 ///
246 /// ### Note: for best performance, ensure the query returns at most one row.
247 /// Depending on the driver implementation, if your query can return more than one row,
248 /// it may lead to wasted CPU time and bandwidth on the database server.
249 ///
250 /// Even when the driver implementation takes this into account, ensuring the query returns at most one row
251 /// can result in a more optimal query plan.
252 ///
253 /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
254 ///
255 /// Otherwise, you might want to add `LIMIT 1` to your query.
256 #[inline]
257 pub async fn fetch_optional<'e, 'c: 'e, E>(self, executor: E) -> Result<Option<DB::Row>, Error>
258 where
259 'q: 'e,
260 A: 'e,
261 E: Executor<'c, Database = DB>,
262 {
263 executor.fetch_optional(self).await
264 }
265}
266
267impl<'q, DB, F: Send, A: Send> Execute<'q, DB> for Map<'q, DB, F, A>
268where
269 DB: Database,
270 A: IntoArguments<'q, DB>,
271{
272 #[inline]
273 fn sql(&self) -> &'q str {
274 self.inner.sql()
275 }
276
277 #[inline]
278 fn statement(&self) -> Option<&<DB as HasStatement<'q>>::Statement> {
279 self.inner.statement()
280 }
281
282 #[inline]
283 fn take_arguments(&mut self) -> Option<<DB as HasArguments<'q>>::Arguments> {
284 self.inner.take_arguments()
285 }
286
287 #[inline]
288 fn persistent(&self) -> bool {
289 self.inner.arguments.is_some()
290 }
291}
292
293impl<'q, DB, F, O, A> Map<'q, DB, F, A>
294where
295 DB: Database,
296 F: FnMut(DB::Row) -> Result<O, Error> + Send,
297 O: Send + Unpin,
298 A: 'q + Send + IntoArguments<'q, DB>,
299{
300 /// Map each row in the result to another type.
301 ///
302 /// See [`try_map`](Map::try_map) for a fallible version of this method.
303 ///
304 /// The [`query_as`](super::query_as::query_as) method will construct a mapped query using
305 /// a [`FromRow`](super::from_row::FromRow) implementation.
306 #[inline]
307 pub fn map<G, P>(
308 self,
309 mut g: G,
310 ) -> Map<'q, DB, impl FnMut(DB::Row) -> Result<P, Error> + Send, A>
311 where
312 G: FnMut(O) -> P + Send,
313 P: Unpin,
314 {
315 self.try_map(move |data| Ok(g(data)))
316 }
317
318 /// Map each row in the result to another type.
319 ///
320 /// The [`query_as`](super::query_as::query_as) method will construct a mapped query using
321 /// a [`FromRow`](super::from_row::FromRow) implementation.
322 #[inline]
323 pub fn try_map<G, P>(
324 self,
325 mut g: G,
326 ) -> Map<'q, DB, impl FnMut(DB::Row) -> Result<P, Error> + Send, A>
327 where
328 G: FnMut(O) -> Result<P, Error> + Send,
329 P: Unpin,
330 {
331 let mut f = self.mapper;
332 Map {
333 inner: self.inner,
334 mapper: move |row| f(row).and_then(|o| g(o)),
335 }
336 }
337
338 /// Execute the query and return the generated results as a stream.
339 pub fn fetch<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<O, Error>>
340 where
341 'q: 'e,
342 E: 'e + Executor<'c, Database = DB>,
343 DB: 'e,
344 F: 'e,
345 O: 'e,
346 {
347 // FIXME: this should have used `executor.fetch()` but that's a breaking change
348 // because this technically allows multiple statements in one query string.
349 #[allow(deprecated)]
350 self.fetch_many(executor)
351 .try_filter_map(|step| async move {
352 Ok(match step {
353 Either::Left(_) => None,
354 Either::Right(o) => Some(o),
355 })
356 })
357 .boxed()
358 }
359
360 /// Execute multiple queries and return the generated results as a stream
361 /// from each query, in a stream.
362 #[deprecated = "Only the SQLite driver supports multiple statements in one prepared statement and that behavior is deprecated. Use `sqlx::raw_sql()` instead."]
363 pub fn fetch_many<'e, 'c: 'e, E>(
364 mut self,
365 executor: E,
366 ) -> BoxStream<'e, Result<Either<DB::QueryResult, O>, Error>>
367 where
368 'q: 'e,
369 E: 'e + Executor<'c, Database = DB>,
370 DB: 'e,
371 F: 'e,
372 O: 'e,
373 {
374 Box::pin(try_stream! {
375 let mut s = executor.fetch_many(self.inner);
376
377 while let Some(v) = s.try_next().await? {
378 r#yield!(match v {
379 Either::Left(v) => Either::Left(v),
380 Either::Right(row) => {
381 Either::Right((self.mapper)(row)?)
382 }
383 });
384 }
385
386 Ok(())
387 })
388 }
389
390 /// Execute the query and return all the resulting rows collected into a [`Vec`].
391 ///
392 /// ### Note: beware result set size.
393 /// This will attempt to collect the full result set of the query into memory.
394 ///
395 /// To avoid exhausting available memory, ensure the result set has a known upper bound,
396 /// e.g. using `LIMIT`.
397 pub async fn fetch_all<'e, 'c: 'e, E>(self, executor: E) -> Result<Vec<O>, Error>
398 where
399 'q: 'e,
400 E: 'e + Executor<'c, Database = DB>,
401 DB: 'e,
402 F: 'e,
403 O: 'e,
404 {
405 self.fetch(executor).try_collect().await
406 }
407
408 /// Execute the query, returning the first row or [`Error::RowNotFound`] otherwise.
409 ///
410 /// ### Note: for best performance, ensure the query returns at most one row.
411 /// Depending on the driver implementation, if your query can return more than one row,
412 /// it may lead to wasted CPU time and bandwidth on the database server.
413 ///
414 /// Even when the driver implementation takes this into account, ensuring the query returns at most one row
415 /// can result in a more optimal query plan.
416 ///
417 /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
418 ///
419 /// Otherwise, you might want to add `LIMIT 1` to your query.
420 pub async fn fetch_one<'e, 'c: 'e, E>(self, executor: E) -> Result<O, Error>
421 where
422 'q: 'e,
423 E: 'e + Executor<'c, Database = DB>,
424 DB: 'e,
425 F: 'e,
426 O: 'e,
427 {
428 self.fetch_optional(executor)
429 .and_then(|row| match row {
430 Some(row) => future::ok(row),
431 None => future::err(Error::RowNotFound),
432 })
433 .await
434 }
435
436 /// Execute the query, returning the first row or `None` otherwise.
437 ///
438 /// ### Note: for best performance, ensure the query returns at most one row.
439 /// Depending on the driver implementation, if your query can return more than one row,
440 /// it may lead to wasted CPU time and bandwidth on the database server.
441 ///
442 /// Even when the driver implementation takes this into account, ensuring the query returns at most one row
443 /// can result in a more optimal query plan.
444 ///
445 /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
446 ///
447 /// Otherwise, you might want to add `LIMIT 1` to your query.
448 pub async fn fetch_optional<'e, 'c: 'e, E>(mut self, executor: E) -> Result<Option<O>, Error>
449 where
450 'q: 'e,
451 E: 'e + Executor<'c, Database = DB>,
452 DB: 'e,
453 F: 'e,
454 O: 'e,
455 {
456 let row = executor.fetch_optional(self.inner).await?;
457
458 if let Some(row) = row {
459 (self.mapper)(row).map(Some)
460 } else {
461 Ok(None)
462 }
463 }
464}
465
466/// Execute a single SQL query as a prepared statement (explicitly created).
467pub fn query_statement<'q, DB>(
468 statement: &'q <DB as HasStatement<'q>>::Statement,
469) -> Query<'q, DB, <DB as HasArguments<'_>>::Arguments>
470where
471 DB: Database,
472{
473 Query {
474 database: PhantomData,
475 arguments: Some(Default::default()),
476 statement: Either::Right(statement),
477 persistent: true,
478 }
479}
480
481/// Execute a single SQL query as a prepared statement (explicitly created), with the given arguments.
482pub fn query_statement_with<'q, DB, A>(
483 statement: &'q <DB as HasStatement<'q>>::Statement,
484 arguments: A,
485) -> Query<'q, DB, A>
486where
487 DB: Database,
488 A: IntoArguments<'q, DB>,
489{
490 Query {
491 database: PhantomData,
492 arguments: Some(arguments),
493 statement: Either::Right(statement),
494 persistent: true,
495 }
496}
497
498/// Execute a single SQL query as a prepared statement (transparently cached).
499///
500/// The query string may only contain a single DML statement: `SELECT`, `INSERT`, `UPDATE`, `DELETE` and variants.
501/// The SQLite driver does not currently follow this restriction, but that behavior is deprecated.
502///
503/// The connection will transparently prepare and cache the statement, which means it only needs to be parsed once
504/// in the connection's lifetime, and any generated query plans can be retained.
505/// Thus, the overhead of executing the statement is amortized.
506///
507/// Some third-party databases that speak a supported protocol, e.g. CockroachDB or PGBouncer that speak Postgres,
508/// may have issues with the transparent caching of prepared statements. If you are having trouble,
509/// try setting [`.persistent(false)`][Query::persistent].
510///
511/// See the [`Query`] type for the methods you may call.
512///
513/// ### Dynamic Input: Use Query Parameters (Prevents SQL Injection)
514/// At some point, you'll likely want to include some form of dynamic input in your query, possibly from the user.
515///
516/// Your first instinct might be to do something like this:
517/// ```rust,no_run
518/// # async fn example() -> sqlx::Result<()> {
519/// # let mut conn: sqlx::PgConnection = unimplemented!();
520/// // Imagine this is input from the user, e.g. a search form on a website.
521/// let user_input = "possibly untrustworthy input!";
522///
523/// // DO NOT DO THIS unless you're ABSOLUTELY CERTAIN it's what you need!
524/// let query = format!("SELECT * FROM articles WHERE content LIKE '%{user_input}%'");
525/// // where `conn` is `PgConnection` or `MySqlConnection`
526/// // or some other type that implements `Executor`.
527/// let results = sqlx::query(&query).fetch_all(&mut conn).await?;
528/// # }
529/// ```
530///
531/// The example above showcases a **SQL injection vulnerability**, because it's trivial for a malicious user to craft
532/// an input that can "break out" of the string literal.
533///
534/// For example, if they send the input `foo'; DELETE FROM articles; --`
535/// then your application would send the following to the database server (line breaks added for clarity):
536///
537/// ```sql
538/// SELECT * FROM articles WHERE content LIKE '%foo';
539/// DELETE FROM articles;
540/// --%'
541/// ```
542///
543/// In this case, because this interface *always* uses prepared statements, you would likely be fine because prepared
544/// statements _generally_ (see above) are only allowed to contain a single query. This would simply return an error.
545///
546/// However, it would also break on legitimate user input.
547/// What if someone wanted to search for the string `Alice's Apples`? It would also return an error because
548/// the database would receive a query with a broken string literal (line breaks added for clarity):
549///
550/// ```sql
551/// SELECT * FROM articles WHERE content LIKE '%Alice'
552/// s Apples%'
553/// ```
554///
555/// Of course, it's possible to make this syntactically valid by escaping the apostrophe, but there's a better way.
556///
557/// ##### You should always prefer query parameters for dynamic input.
558///
559/// When using query parameters, you add placeholders to your query where a value
560/// should be substituted at execution time, then call [`.bind()`][Query::bind] with that value.
561///
562/// The syntax for placeholders is unfortunately not standardized and depends on the database:
563///
564/// * Postgres and SQLite: use `$1`, `$2`, `$3`, etc.
565/// * The number is the Nth bound value, starting from one.
566/// * The same placeholder can be used arbitrarily many times to refer to the same bound value.
567/// * SQLite technically supports MySQL's syntax as well as others, but we recommend using this syntax
568/// as SQLx's SQLite driver is written with it in mind.
569/// * MySQL and MariaDB: use `?`.
570/// * Placeholders are purely positional, similar to `println!("{}, {}", foo, bar)`.
571/// * The order of bindings must match the order of placeholders in the query.
572/// * To use a value in multiple places, you must bind it multiple times.
573///
574/// In both cases, the placeholder syntax acts as a variable expression representing the bound value:
575///
576/// ```rust,no_run
577/// # async fn example2() -> sqlx::Result<()> {
578/// # let mut conn: sqlx::PgConnection = unimplemented!();
579/// let user_input = "Alice's Apples";
580///
581/// // Postgres and SQLite
582/// let results = sqlx::query(
583/// // Notice how we only have to bind the argument once and we can use it multiple times:
584/// "SELECT * FROM articles
585/// WHERE title LIKE '%' || $1 || '%'
586/// OR content LIKE '%' || $1 || '%'"
587/// )
588/// .bind(user_input)
589/// .fetch_all(&mut conn)
590/// .await?;
591///
592/// // MySQL and MariaDB
593/// let results = sqlx::query(
594/// "SELECT * FROM articles
595/// WHERE title LIKE CONCAT('%', ?, '%')
596/// OR content LIKE CONCAT('%', ?, '%')"
597/// )
598/// // If we want to reference the same value multiple times, we have to bind it multiple times:
599/// .bind(user_input)
600/// .bind(user_input)
601/// .fetch_all(&mut conn)
602/// .await?;
603/// # Ok(())
604/// # }
605/// ```
606/// ##### The value bound to a query parameter is entirely separate from the query and does not affect its syntax.
607/// Thus, SQL injection is impossible (barring shenanigans like calling a SQL function that lets you execute a string
608/// as a statement) and *all* strings are valid.
609///
610/// This also means you cannot use query parameters to add conditional SQL fragments.
611///
612/// **SQLx does not substitute placeholders on the client side**. It is done by the database server itself.
613///
614/// ##### SQLx supports many different types for parameter binding, not just strings.
615/// Any type that implements [`Encode<DB>`][Encode] and [`Type<DB>`] can be bound as a parameter.
616///
617/// See [the `types` module][crate::types] (links to `sqlx_core::types` but you should use `sqlx::types`) for details.
618///
619/// As an additional benefit, query parameters are usually sent in a compact binary encoding instead of a human-readable
620/// text encoding, which saves bandwidth.
621pub fn query<DB>(sql: &str) -> Query<'_, DB, <DB as HasArguments<'_>>::Arguments>
622where
623 DB: Database,
624{
625 Query {
626 database: PhantomData,
627 arguments: Some(Default::default()),
628 statement: Either::Left(sql),
629 persistent: true,
630 }
631}
632
633/// Execute a SQL query as a prepared statement (transparently cached), with the given arguments.
634///
635/// See [`query()`][query] for details, such as supported syntax.
636pub fn query_with<'q, DB, A>(sql: &'q str, arguments: A) -> Query<'q, DB, A>
637where
638 DB: Database,
639 A: IntoArguments<'q, DB>,
640{
641 Query {
642 database: PhantomData,
643 arguments: Some(arguments),
644 statement: Either::Left(sql),
645 persistent: true,
646 }
647}