sqlx_core/
raw_sql.rs

1use either::Either;
2use futures_core::future::BoxFuture;
3use futures_core::stream::BoxStream;
4
5use crate::database::Database;
6use crate::error::BoxDynError;
7use crate::executor::{Execute, Executor};
8use crate::sql_str::{SqlSafeStr, SqlStr};
9use crate::Error;
10
11// AUTHOR'S NOTE: I was just going to call this API `sql()` and `Sql`, respectively,
12// but realized that would be extremely annoying to deal with as a SQLite user
13// because IDE smart completion would always recommend the `Sql` type first.
14//
15// It doesn't really need a super convenient name anyway as it's not meant to be used very often.
16
17/// One or more raw SQL statements, separated by semicolons (`;`).
18///
19/// See [`raw_sql()`] for details.
20pub struct RawSql(SqlStr);
21
22/// Execute one or more statements as raw SQL, separated by semicolons (`;`).
23///
24/// This interface can be used to execute both DML
25/// (Data Manipulation Language: `SELECT`, `INSERT`, `UPDATE`, `DELETE` and variants)
26/// as well as DDL (Data Definition Language: `CREATE TABLE`, `ALTER TABLE`, etc).
27///
28/// This will not create or cache any prepared statements.
29///
30/// ### Note: singular DML queries, prefer `query()`
31/// This API does not use prepared statements, so usage of it is missing out on their benefits.
32///
33/// Prefer [`query()`][crate::query::query] instead if executing a single query.
34///
35/// It's also possible to combine multiple DML queries into one for use with `query()`:
36///
37/// ##### Common Table Expressions (CTEs: i.e The `WITH` Clause)
38/// Common Table Expressions effectively allow you to define aliases for queries
39/// that can be referenced like temporary tables:
40///
41/// ```sql
42/// WITH inserted_foos AS (
43///     -- Note that only Postgres allows data-modifying statements in CTEs
44///     INSERT INTO foo (bar_id) VALUES ($1)
45///     RETURNING foo_id, bar_id
46/// )
47/// SELECT foo_id, bar_id, bar
48/// FROM inserted_foos
49/// INNER JOIN bar USING (bar_id)
50/// ```
51///
52/// It's important to note that data modifying statements (`INSERT`, `UPDATE`, `DELETE`) may
53/// behave differently than expected. In Postgres, all data-modifying subqueries in a `WITH`
54/// clause execute with the same view of the data; they *cannot* see each other's modifications.
55///
56/// MySQL, MariaDB and SQLite appear to *only* allow `SELECT` statements in CTEs.
57///
58/// See the appropriate entry in your database's manual for details:
59/// * [MySQL](https://dev.mysql.com/doc/refman/8.0/en/with.html)
60///     * [MariaDB](https://mariadb.com/kb/en/with/)
61/// * [Postgres](https://www.postgresql.org/docs/current/queries-with.html)
62/// * [SQLite](https://www.sqlite.org/lang_with.html)
63///
64/// ##### `UNION`/`INTERSECT`/`EXCEPT`
65/// You can also use various set-theory operations on queries,
66/// including `UNION ALL` which simply concatenates their results.
67///
68/// See the appropriate entry in your database's manual for details:
69/// * [MySQL](https://dev.mysql.com/doc/refman/8.0/en/set-operations.html)
70///    * [MariaDB](https://mariadb.com/kb/en/joins-subqueries/)
71/// * [Postgres](https://www.postgresql.org/docs/current/queries-union.html)
72/// * [SQLite](https://www.sqlite.org/lang_select.html#compound_select_statements)
73///
74/// ### Note: query parameters are not supported.
75/// Query parameters require the use of prepared statements which this API does support.
76///
77/// If you require dynamic input data in your SQL, you can use `format!()` but **be very careful
78/// doing this with user input**. SQLx does **not** provide escaping or sanitization for inserting
79/// dynamic input into queries this way.
80///
81/// See [`query()`][crate::query::query] for details.
82///
83/// ### Note: multiple statements and autocommit.
84/// By default, when you use this API to execute a SQL string containing multiple statements
85/// separated by semicolons (`;`), the database server will treat those statements as all executing
86/// within the same transaction block, i.e. wrapped in `BEGIN` and `COMMIT`:
87///
88/// ```rust,no_run
89/// # async fn example() -> sqlx::Result<()> {
90/// let mut conn: sqlx::PgConnection = todo!("e.g. PgConnection::connect(<DATABASE URL>)");
91///
92/// sqlx::raw_sql(
93///     // Imagine we're moving data from one table to another:
94///     // Implicit `BEGIN;`
95///     "UPDATE foo SET bar = foobar.bar FROM foobar WHERE foobar.foo_id = foo.id;\
96///      DELETE FROM foobar;"
97///     // Implicit `COMMIT;`
98/// )
99///    .execute(&mut conn)
100///    .await?;
101///
102/// # Ok(())
103/// # }
104/// ```
105///
106/// If one statement triggers an error, the whole script aborts and rolls back.
107/// You can include explicit `BEGIN` and `COMMIT` statements in the SQL string
108/// to designate units that can be committed or rolled back piecemeal.
109///
110/// This also allows for a rudimentary form of pipelining as the whole SQL string is sent in one go.
111///
112/// ##### MySQL and MariaDB: DDL implicitly commits!
113/// MySQL and MariaDB do not support DDL in transactions. Instead, any active transaction is
114/// immediately and implicitly committed by the database server when executing a DDL statement.
115/// Beware of this behavior.
116///
117/// See [MySQL manual, section 13.3.3: Statements That Cause an Implicit Commit](https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html) for details.
118/// See also: [MariaDB manual: SQL statements That Cause an Implicit Commit](https://mariadb.com/kb/en/sql-statements-that-cause-an-implicit-commit/).
119pub fn raw_sql(sql: impl SqlSafeStr) -> RawSql {
120    RawSql(sql.into_sql_str())
121}
122
123impl<DB: Database> Execute<'_, DB> for RawSql {
124    fn sql(self) -> SqlStr {
125        self.0
126    }
127
128    fn statement(&self) -> Option<&<DB as Database>::Statement> {
129        None
130    }
131
132    fn take_arguments(&mut self) -> Result<Option<<DB as Database>::Arguments>, BoxDynError> {
133        Ok(None)
134    }
135
136    fn persistent(&self) -> bool {
137        false
138    }
139}
140
141impl RawSql {
142    /// Execute the SQL string and return the total number of rows affected.
143    #[inline]
144    pub async fn execute<'e, E, DB>(self, executor: E) -> crate::Result<DB::QueryResult>
145    where
146        DB: Database,
147        E: Executor<'e, Database = DB>,
148    {
149        executor.execute(self).await
150    }
151
152    /// Execute the SQL string. Returns a stream which gives the number of rows affected for each statement in the string.
153    #[inline]
154    pub fn execute_many<'e, E, DB>(
155        self,
156        executor: E,
157    ) -> BoxStream<'e, crate::Result<DB::QueryResult>>
158    where
159        DB: Database,
160        E: Executor<'e, Database = DB>,
161    {
162        executor.execute_many(self)
163    }
164
165    /// Execute the SQL string and return the generated results as a stream.
166    ///
167    /// If the string contains multiple statements, their results will be concatenated together.
168    #[inline]
169    pub fn fetch<'e, E, DB>(self, executor: E) -> BoxStream<'e, Result<DB::Row, Error>>
170    where
171        DB: Database,
172        E: Executor<'e, Database = DB>,
173    {
174        executor.fetch(self)
175    }
176
177    /// Execute the SQL string and return the generated results as a stream.
178    ///
179    /// For each query in the stream, any generated rows are returned first,
180    /// then the `QueryResult` with the number of rows affected.
181    #[inline]
182    pub fn fetch_many<'e, E, DB>(
183        self,
184        executor: E,
185    ) -> BoxStream<'e, Result<Either<DB::QueryResult, DB::Row>, Error>>
186    where
187        DB: Database,
188        E: Executor<'e, Database = DB>,
189    {
190        executor.fetch_many(self)
191    }
192
193    /// Execute the SQL string and return all the resulting rows collected into a [`Vec`].
194    ///
195    /// ### Note: beware result set size.
196    /// This will attempt to collect the full result set of the query into memory.
197    ///
198    /// To avoid exhausting available memory, ensure the result set has a known upper bound,
199    /// e.g. using `LIMIT`.
200    #[inline]
201    pub fn fetch_all<'e, E, DB>(self, executor: E) -> BoxFuture<'e, crate::Result<Vec<DB::Row>>>
202    where
203        DB: Database,
204        E: Executor<'e, Database = DB>,
205    {
206        executor.fetch_all(self)
207    }
208
209    /// Execute the SQL string, returning the first row or [`Error::RowNotFound`] otherwise.
210    ///
211    /// ### Note: for best performance, ensure the query returns at most one row.
212    /// Depending on the driver implementation, if your query can return more than one row,
213    /// it may lead to wasted CPU time and bandwidth on the database server.
214    ///
215    /// Even when the driver implementation takes this into account, ensuring the query returns
216    /// at most one row can result in a more optimal query plan.
217    ///
218    /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
219    ///
220    /// Otherwise, you might want to add `LIMIT 1` to your query.
221    #[inline]
222    pub fn fetch_one<'e, E, DB>(self, executor: E) -> BoxFuture<'e, crate::Result<DB::Row>>
223    where
224        DB: Database,
225        E: Executor<'e, Database = DB>,
226    {
227        executor.fetch_one(self)
228    }
229
230    /// Execute the SQL string, returning the first row or [`None`] otherwise.
231    ///
232    /// ### Note: for best performance, ensure the query returns at most one row.
233    /// Depending on the driver implementation, if your query can return more than one row,
234    /// it may lead to wasted CPU time and bandwidth on the database server.
235    ///
236    /// Even when the driver implementation takes this into account, ensuring the query returns
237    /// at most one row can result in a more optimal query plan.
238    ///
239    /// If your query has a `WHERE` clause filtering a unique column by a single value, you're good.
240    ///
241    /// Otherwise, you might want to add `LIMIT 1` to your query.
242    #[inline]
243    pub async fn fetch_optional<'e, E, DB>(self, executor: E) -> crate::Result<Option<DB::Row>>
244    where
245        DB: Database,
246        E: Executor<'e, Database = DB>,
247    {
248        executor.fetch_optional(self).await
249    }
250}