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