Skip to content

Commit 7f72829

Browse files
authored
fix: RawSql lifetime issues (#3613)
* chore(raw_sql): create regression test * fix: `RawSql` lifetime issues * chore(raw_sql): try not adding another lifetime param
1 parent 8602d94 commit 7f72829

File tree

2 files changed

+45
-39
lines changed

2 files changed

+45
-39
lines changed

sqlx-core/src/raw_sql.rs

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use either::Either;
2+
use futures_core::future::BoxFuture;
23
use futures_core::stream::BoxStream;
34

45
use crate::database::Database;
@@ -139,26 +140,25 @@ impl<'q, DB: Database> Execute<'q, DB> for RawSql<'q> {
139140
impl<'q> RawSql<'q> {
140141
/// Execute the SQL string and return the total number of rows affected.
141142
#[inline]
142-
pub async fn execute<'e, E>(
143-
self,
144-
executor: E,
145-
) -> crate::Result<<E::Database as Database>::QueryResult>
143+
pub async fn execute<'e, E, DB>(self, executor: E) -> crate::Result<DB::QueryResult>
146144
where
147145
'q: 'e,
148-
E: Executor<'e>,
146+
DB: Database,
147+
E: Executor<'e, Database = DB>,
149148
{
150149
executor.execute(self).await
151150
}
152151

153152
/// Execute the SQL string. Returns a stream which gives the number of rows affected for each statement in the string.
154153
#[inline]
155-
pub fn execute_many<'e, E>(
154+
pub fn execute_many<'e, E, DB>(
156155
self,
157156
executor: E,
158-
) -> BoxStream<'e, crate::Result<<E::Database as Database>::QueryResult>>
157+
) -> BoxStream<'e, crate::Result<DB::QueryResult>>
159158
where
160159
'q: 'e,
161-
E: Executor<'e>,
160+
DB: Database,
161+
E: Executor<'e, Database = DB>,
162162
{
163163
executor.execute_many(self)
164164
}
@@ -167,13 +167,11 @@ impl<'q> RawSql<'q> {
167167
///
168168
/// If the string contains multiple statements, their results will be concatenated together.
169169
#[inline]
170-
pub fn fetch<'e, E>(
171-
self,
172-
executor: E,
173-
) -> BoxStream<'e, Result<<E::Database as Database>::Row, Error>>
170+
pub fn fetch<'e, E, DB>(self, executor: E) -> BoxStream<'e, Result<DB::Row, Error>>
174171
where
175172
'q: 'e,
176-
E: Executor<'e>,
173+
DB: Database,
174+
E: Executor<'e, Database = DB>,
177175
{
178176
executor.fetch(self)
179177
}
@@ -183,19 +181,14 @@ impl<'q> RawSql<'q> {
183181
/// For each query in the stream, any generated rows are returned first,
184182
/// then the `QueryResult` with the number of rows affected.
185183
#[inline]
186-
pub fn fetch_many<'e, E>(
184+
pub fn fetch_many<'e, E, DB>(
187185
self,
188186
executor: E,
189-
) -> BoxStream<
190-
'e,
191-
Result<
192-
Either<<E::Database as Database>::QueryResult, <E::Database as Database>::Row>,
193-
Error,
194-
>,
195-
>
187+
) -> BoxStream<'e, Result<Either<DB::QueryResult, DB::Row>, Error>>
196188
where
197189
'q: 'e,
198-
E: Executor<'e>,
190+
DB: Database,
191+
E: Executor<'e, Database = DB>,
199192
{
200193
executor.fetch_many(self)
201194
}
@@ -208,15 +201,13 @@ impl<'q> RawSql<'q> {
208201
/// To avoid exhausting available memory, ensure the result set has a known upper bound,
209202
/// e.g. using `LIMIT`.
210203
#[inline]
211-
pub async fn fetch_all<'e, E>(
212-
self,
213-
executor: E,
214-
) -> crate::Result<Vec<<E::Database as Database>::Row>>
204+
pub fn fetch_all<'e, E, DB>(self, executor: E) -> BoxFuture<'e, crate::Result<Vec<DB::Row>>>
215205
where
216206
'q: 'e,
217-
E: Executor<'e>,
207+
DB: Database,
208+
E: Executor<'e, Database = DB>,
218209
{
219-
executor.fetch_all(self).await
210+
executor.fetch_all(self)
220211
}
221212

222213
/// Execute the SQL string, returning the first row or [`Error::RowNotFound`] otherwise.
@@ -232,15 +223,13 @@ impl<'q> RawSql<'q> {
232223
///
233224
/// Otherwise, you might want to add `LIMIT 1` to your query.
234225
#[inline]
235-
pub async fn fetch_one<'e, E>(
236-
self,
237-
executor: E,
238-
) -> crate::Result<<E::Database as Database>::Row>
226+
pub fn fetch_one<'e, E, DB>(self, executor: E) -> BoxFuture<'e, crate::Result<DB::Row>>
239227
where
240228
'q: 'e,
241-
E: Executor<'e>,
229+
DB: Database,
230+
E: Executor<'e, Database = DB>,
242231
{
243-
executor.fetch_one(self).await
232+
executor.fetch_one(self)
244233
}
245234

246235
/// Execute the SQL string, returning the first row or [`None`] otherwise.
@@ -256,13 +245,11 @@ impl<'q> RawSql<'q> {
256245
///
257246
/// Otherwise, you might want to add `LIMIT 1` to your query.
258247
#[inline]
259-
pub async fn fetch_optional<'e, E>(
260-
self,
261-
executor: E,
262-
) -> crate::Result<<E::Database as Database>::Row>
248+
pub async fn fetch_optional<'e, E, DB>(self, executor: E) -> crate::Result<DB::Row>
263249
where
264250
'q: 'e,
265-
E: Executor<'e>,
251+
DB: Database,
252+
E: Executor<'e, Database = DB>,
266253
{
267254
executor.fetch_one(self).await
268255
}

tests/sqlite/sqlite.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use sqlx::{
88
};
99
use sqlx_sqlite::LockedSqliteHandle;
1010
use sqlx_test::new;
11+
use std::future::Future;
1112
use std::sync::atomic::{AtomicBool, Ordering};
1213
use std::sync::Arc;
1314

@@ -969,6 +970,24 @@ async fn test_multiple_set_rollback_hook_calls_drop_old_handler() -> anyhow::Res
969970
Ok(())
970971
}
971972

973+
#[sqlx_macros::test]
974+
async fn issue_3150() {
975+
// Same bounds as `tokio::spawn()`
976+
async fn fake_spawn<F>(future: F) -> F::Output
977+
where
978+
F: Future + Send + 'static,
979+
{
980+
future.await
981+
}
982+
983+
fake_spawn(async {
984+
let mut db = SqliteConnection::connect(":memory:").await.unwrap();
985+
sqlx::raw_sql("").execute(&mut db).await.unwrap();
986+
db.close().await.unwrap();
987+
})
988+
.await;
989+
}
990+
972991
#[cfg(feature = "sqlite-preupdate-hook")]
973992
#[sqlx_macros::test]
974993
async fn test_query_with_preupdate_hook_insert() -> anyhow::Result<()> {

0 commit comments

Comments
 (0)