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