sqlx_core/
query_scalar.rs

1use either::Either;
2use futures_core::stream::BoxStream;
3use futures_util::{StreamExt, TryFutureExt, TryStreamExt};
4
5use crate::arguments::IntoArguments;
6use crate::database::{Database, HasStatementCache};
7use crate::encode::Encode;
8use crate::error::{BoxDynError, Error};
9use crate::executor::{Execute, Executor};
10use crate::from_row::FromRow;
11use crate::query_as::{
12    query_as, query_as_with_result, query_statement_as, query_statement_as_with, QueryAs,
13};
14use crate::sql_str::{SqlSafeStr, SqlStr};
15use crate::types::Type;
16
17/// A single SQL query as a prepared statement which extracts only the first column of each row.
18/// Returned by [`query_scalar()`].
19#[must_use = "query must be executed to affect database"]
20pub struct QueryScalar<'q, DB: Database, O, A> {
21    pub(crate) inner: QueryAs<'q, DB, (O,), A>,
22}
23
24impl<'q, DB: Database, O: Send, A: Send> Execute<'q, DB> for QueryScalar<'q, DB, O, A>
25where
26    A: 'q + IntoArguments<DB>,
27{
28    #[inline]
29    fn sql(self) -> SqlStr {
30        self.inner.sql()
31    }
32
33    fn statement(&self) -> Option<&DB::Statement> {
34        self.inner.statement()
35    }
36
37    #[inline]
38    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError> {
39        self.inner.take_arguments()
40    }
41
42    #[inline]
43    fn persistent(&self) -> bool {
44        Execute::persistent(&self.inner)
45    }
46}
47
48impl<'q, DB: Database, O> QueryScalar<'q, DB, O, <DB as Database>::Arguments> {
49    /// Bind a value for use with this SQL query.
50    ///
51    /// See [`Query::bind`](crate::query::Query::bind).
52    pub fn bind<T: 'q + Encode<'q, DB> + Type<DB>>(mut self, value: T) -> Self {
53        self.inner = self.inner.bind(value);
54        self
55    }
56}
57
58impl<DB, O, A> QueryScalar<'_, DB, O, A>
59where
60    DB: Database + HasStatementCache,
61{
62    /// If `true`, the statement will get prepared once and cached to the
63    /// connection's statement cache.
64    ///
65    /// If queried once with the flag set to `true`, all subsequent queries
66    /// matching the one with the flag will use the cached statement until the
67    /// cache is cleared.
68    ///
69    /// If `false`, the prepared statement will be closed after execution.
70    ///
71    /// Default: `true`.
72    pub fn persistent(mut self, value: bool) -> Self {
73        self.inner = self.inner.persistent(value);
74        self
75    }
76}
77
78// FIXME: This is very close, nearly 1:1 with `Map`
79// noinspection DuplicatedCode
80impl<'q, DB, O, A> QueryScalar<'q, DB, O, A>
81where
82    DB: Database,
83    O: Send + Unpin,
84    A: 'q + IntoArguments<DB>,
85    (O,): Send + Unpin + for<'r> FromRow<'r, DB::Row>,
86{
87    /// Execute the query and return the generated results as a stream.
88    #[inline]
89    pub fn fetch<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<O, Error>>
90    where
91        'q: 'e,
92        E: 'e + Executor<'c, Database = DB>,
93        DB: 'e,
94        A: 'e,
95        O: 'e,
96    {
97        self.inner.fetch(executor).map_ok(|it| it.0).boxed()
98    }
99
100    /// Execute multiple queries and return the generated results as a stream
101    /// from each query, in a stream.
102    #[inline]
103    #[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."]
104    pub fn fetch_many<'e, 'c: 'e, E>(
105        self,
106        executor: E,
107    ) -> BoxStream<'e, Result<Either<DB::QueryResult, O>, Error>>
108    where
109        'q: 'e,
110        E: 'e + Executor<'c, Database = DB>,
111        DB: 'e,
112        A: 'e,
113        O: 'e,
114    {
115        #[allow(deprecated)]
116        self.inner
117            .fetch_many(executor)
118            .map_ok(|v| v.map_right(|it| it.0))
119            .boxed()
120    }
121
122    /// Execute the query and return all the resulting rows collected into a [`Vec`].
123    ///
124    /// ### Note: beware result set size.
125    /// This will attempt to collect the full result set of the query into memory.
126    ///
127    /// To avoid exhausting available memory, ensure the result set has a known upper bound,
128    /// e.g. using `LIMIT`.
129    #[inline]
130    pub async fn fetch_all<'e, 'c: 'e, E>(self, executor: E) -> Result<Vec<O>, Error>
131    where
132        'q: 'e,
133        E: 'e + Executor<'c, Database = DB>,
134        DB: 'e,
135        (O,): 'e,
136        A: 'e,
137    {
138        self.inner
139            .fetch(executor)
140            .map_ok(|it| it.0)
141            .try_collect()
142            .await
143    }
144
145    /// Execute the query, returning the first row or [`Error::RowNotFound`] otherwise.
146    ///
147    /// ### Note: for best performance, ensure the query returns at most one row.
148    /// Depending on the driver implementation, if your query can return more than one row,
149    /// it may lead to wasted CPU time and bandwidth on the database server.
150    ///
151    /// Even when the driver implementation takes this into account, ensuring the query returns at most one row
152    /// can result in a more optimal query plan.
153    ///
154    /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
155    ///
156    /// Otherwise, you might want to add `LIMIT 1` to your query.
157    #[inline]
158    pub async fn fetch_one<'e, 'c: 'e, E>(self, executor: E) -> Result<O, Error>
159    where
160        'q: 'e,
161        E: 'e + Executor<'c, Database = DB>,
162        DB: 'e,
163        O: 'e,
164        A: 'e,
165    {
166        self.inner.fetch_one(executor).map_ok(|it| it.0).await
167    }
168
169    /// Execute the query, returning the first row or `None` otherwise.
170    ///
171    /// ### Note: for best performance, ensure the query returns at most one row.
172    /// Depending on the driver implementation, if your query can return more than one row,
173    /// it may lead to wasted CPU time and bandwidth on the database server.
174    ///
175    /// Even when the driver implementation takes this into account, ensuring the query returns at most one row
176    /// can result in a more optimal query plan.
177    ///
178    /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
179    ///
180    /// Otherwise, you might want to add `LIMIT 1` to your query.
181    #[inline]
182    pub async fn fetch_optional<'e, 'c: 'e, E>(self, executor: E) -> Result<Option<O>, Error>
183    where
184        'q: 'e,
185        E: 'e + Executor<'c, Database = DB>,
186        DB: 'e,
187        O: 'e,
188        A: 'e,
189    {
190        Ok(self.inner.fetch_optional(executor).await?.map(|it| it.0))
191    }
192}
193
194/// Execute a single SQL query as a prepared statement (transparently cached) and extract the first
195/// column of each row.
196///
197/// Extracts the first column of each row. Additional columns are ignored.
198/// Any type that implements `Type<DB> + Decode<DB>` may be used.
199///
200/// For details about prepared statements and allowed SQL syntax, see [`query()`][crate::query::query].
201///
202/// ### Example: Simple Lookup
203/// If you just want to look up a single value with little fanfare, this API is perfect for you:
204///
205/// ```rust,no_run
206/// # async fn example_lookup() -> Result<(), Box<dyn std::error::Error>> {
207/// # let mut conn: sqlx::PgConnection = unimplemented!();
208/// use uuid::Uuid;
209///
210/// // MySQL and MariaDB: use `?`
211/// let user_id: Option<Uuid> = sqlx::query_scalar("SELECT user_id FROM users WHERE username = $1")
212///     .bind("alice")
213///     // Use `&mut` where `conn` is a connection or a transaction, or use `&` for a `Pool`.
214///     .fetch_optional(&mut conn)
215///     .await?;
216///
217/// let user_id = user_id.ok_or("unknown user")?;
218///
219/// # Ok(())
220/// # }
221/// ```
222///
223/// Note how we're using `.fetch_optional()` because the lookup may return no results,
224/// in which case we need to be able to handle an empty result set.
225/// Any rows after the first are ignored.
226///
227/// ### Example: `COUNT`
228/// This API is the easiest way to invoke an aggregate query like `SELECT COUNT(*)`, because you
229/// can conveniently extract the result:
230///
231/// ```rust,no_run
232/// # async fn example_count() -> sqlx::Result<()> {
233/// # let mut conn: sqlx::PgConnection = unimplemented!();
234/// // Note that `usize` is not used here because unsigned integers are generally not supported,
235/// // and `usize` doesn't even make sense as a mapping because the database server may have
236/// // a completely different architecture.
237/// //
238/// // `i64` is generally a safe choice for `COUNT`.
239/// let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM users WHERE accepted_tos IS TRUE")
240///     // Use `&mut` where `conn` is a connection or a transaction, or use `&` for a `Pool`.
241///     .fetch_one(&mut conn)
242///     .await?;
243///
244/// // The above is functionally equivalent to the following:
245/// // Note the trailing comma, required for the compiler to recognize a 1-element tuple.
246/// let (count,): (i64,) = sqlx::query_as("SELECT COUNT(*) FROM users WHERE accepted_tos IS TRUE")
247///     .fetch_one(&mut conn)
248///     .await?;
249/// # Ok(())
250/// # }
251/// ```
252///
253/// ### Example: `EXISTS`
254/// To test if a row exists or not, use `SELECT EXISTS(<query>)`:
255///
256/// ```rust,no_run
257/// # async fn example_exists() -> sqlx::Result<()> {
258/// # let mut conn: sqlx::PgConnection = unimplemented!();
259/// // MySQL and MariaDB: use `?`
260/// let username_taken: bool = sqlx::query_scalar(
261///     "SELECT EXISTS(SELECT 1 FROM users WHERE username = $1)"
262/// )
263///     .bind("alice")
264///     // Use `&mut` where `conn` is a connection or a transaction, or use `&` for a `Pool`.
265///     .fetch_one(&mut conn)
266///     .await?;
267/// # Ok(())
268/// # }
269/// ```
270///
271/// ### Example: Other Aggregates
272/// Be aware that most other aggregate functions return `NULL` if the query yields an empty set:
273///
274/// ```rust,no_run
275/// # async fn example_aggregate() -> sqlx::Result<()> {
276/// # let mut conn: sqlx::PgConnection = unimplemented!();
277/// let max_upvotes: Option<i64> = sqlx::query_scalar("SELECT MAX(upvotes) FROM posts")
278///     // Use `&mut` where `conn` is a connection or a transaction, or use `&` for a `Pool`.
279///     .fetch_one(&mut conn)
280///     .await?;
281/// # Ok(())
282/// # }
283/// ```
284///
285/// Note how we're using `Option<i64>` with `.fetch_one()`, because we're always expecting one row
286/// but the column value may be `NULL`. If no rows are returned, this will error.
287///
288/// This is in contrast to using `.fetch_optional()` with `Option<i64>`, which implies that
289/// we're expecting _either_ a row with a `i64` (`BIGINT`), _or_ no rows at all.
290///
291/// Either way, any rows after the first are ignored.
292///
293/// ### Example: `Vec` of Scalars
294/// If you want to collect a single column from a query into a vector,
295/// try `.fetch_all()`:
296///
297/// ```rust,no_run
298/// # async fn example_vec() -> sqlx::Result<()> {
299/// # let mut conn: sqlx::PgConnection = unimplemented!();
300/// let top_users: Vec<String> = sqlx::query_scalar(
301///     // Note the `LIMIT` to ensure that this doesn't return *all* users:
302///     "SELECT username
303///      FROM (
304///          SELECT SUM(upvotes) total, user_id
305///          FROM posts
306///          GROUP BY user_id
307///      ) top_users
308///      INNER JOIN users USING (user_id)
309///      ORDER BY total DESC
310///      LIMIT 10"
311/// )
312///     // Use `&mut` where `conn` is a connection or a transaction, or use `&` for a `Pool`.
313///     .fetch_all(&mut conn)
314///     .await?;
315///
316/// // `top_users` could be empty, too.
317/// assert!(top_users.len() <= 10);
318/// # Ok(())
319/// # }
320/// ```
321#[inline]
322pub fn query_scalar<'q, DB, O>(
323    sql: impl SqlSafeStr,
324) -> QueryScalar<'q, DB, O, <DB as Database>::Arguments>
325where
326    DB: Database,
327    (O,): for<'r> FromRow<'r, DB::Row>,
328{
329    QueryScalar {
330        inner: query_as(sql),
331    }
332}
333
334/// Execute a SQL query as a prepared statement (transparently cached), with the given arguments,
335/// and extract the first column of each row.
336///
337/// See [`query_scalar()`] for details.
338///
339/// For details about prepared statements and allowed SQL syntax, see [`query()`][crate::query::query].
340#[inline]
341pub fn query_scalar_with<'q, DB, O, A>(
342    sql: impl SqlSafeStr,
343    arguments: A,
344) -> QueryScalar<'q, DB, O, A>
345where
346    DB: Database,
347    A: IntoArguments<DB>,
348    (O,): for<'r> FromRow<'r, DB::Row>,
349{
350    query_scalar_with_result(sql, Ok(arguments))
351}
352
353/// Same as [`query_scalar_with`] but takes arguments as Result
354#[inline]
355pub fn query_scalar_with_result<'q, DB, O, A>(
356    sql: impl SqlSafeStr,
357    arguments: Result<A, BoxDynError>,
358) -> QueryScalar<'q, DB, O, A>
359where
360    DB: Database,
361    A: IntoArguments<DB>,
362    (O,): for<'r> FromRow<'r, DB::Row>,
363{
364    QueryScalar {
365        inner: query_as_with_result(sql, arguments),
366    }
367}
368
369// Make a SQL query from a statement, that is mapped to a concrete value.
370pub fn query_statement_scalar<DB, O>(
371    statement: &DB::Statement,
372) -> QueryScalar<'_, DB, O, <DB as Database>::Arguments>
373where
374    DB: Database,
375    (O,): for<'r> FromRow<'r, DB::Row>,
376{
377    QueryScalar {
378        inner: query_statement_as(statement),
379    }
380}
381
382// Make a SQL query from a statement, with the given arguments, that is mapped to a concrete value.
383pub fn query_statement_scalar_with<'q, DB, O, A>(
384    statement: &'q DB::Statement,
385    arguments: A,
386) -> QueryScalar<'q, DB, O, A>
387where
388    DB: Database,
389    A: IntoArguments<DB>,
390    (O,): for<'r> FromRow<'r, DB::Row>,
391{
392    QueryScalar {
393        inner: query_statement_as_with(statement, arguments),
394    }
395}