Skip to content

Commit 71a99bb

Browse files
committed
refactor(core): Also relax lifetime of argument passed to Query::bind and Query::try_bind
Signed-off-by: Joshua Potts <[email protected]>
1 parent e1ec002 commit 71a99bb

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

sqlx-core/src/query.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ where
7373
}
7474
}
7575

76-
impl<'q, DB: Database> Query<'q, DB, <DB as Database>::Arguments> {
76+
impl<DB: Database> Query<'_, DB, <DB as Database>::Arguments> {
7777
/// Bind a value for use with this SQL query.
7878
///
7979
/// If the number of times this is called does not match the number of bind parameters that
@@ -84,7 +84,7 @@ impl<'q, DB: Database> Query<'q, DB, <DB as Database>::Arguments> {
8484
/// flavors will perform type coercion (Postgres will return a database error).
8585
///
8686
/// If encoding the value fails, the error is stored and later surfaced when executing the query.
87-
pub fn bind<T: 'q + Encode<'q, DB> + Type<DB>>(mut self, value: T) -> Self {
87+
pub fn bind<'t, T: Encode<'t, DB> + Type<DB>>(mut self, value: T) -> Self {
8888
let Ok(arguments) = self.get_arguments() else {
8989
return self;
9090
};
@@ -101,7 +101,7 @@ impl<'q, DB: Database> Query<'q, DB, <DB as Database>::Arguments> {
101101
}
102102

103103
/// Like [`Query::bind`] but immediately returns an error if encoding a value failed.
104-
pub fn try_bind<T: 'q + Encode<'q, DB> + Type<DB>>(
104+
pub fn try_bind<'t, T: Encode<'t, DB> + Type<DB>>(
105105
&mut self,
106106
value: T,
107107
) -> Result<(), BoxDynError> {

sqlx-test/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use sqlx::pool::PoolOptions;
2-
use sqlx::{Connection, Database, Pool};
2+
use sqlx::{Connection, Database, Error, Pool};
33
use std::env;
44

55
pub fn setup_if_needed() {
@@ -9,13 +9,15 @@ pub fn setup_if_needed() {
99

1010
// Make a new connection
1111
// Ensure [dotenvy] and [env_logger] have been setup
12-
pub async fn new<DB>() -> anyhow::Result<DB::Connection>
12+
pub async fn new<DB>() -> sqlx::Result<DB::Connection>
1313
where
1414
DB: Database,
1515
{
1616
setup_if_needed();
1717

18-
Ok(DB::Connection::connect(&env::var("DATABASE_URL")?).await?)
18+
let db_url = env::var("DATABASE_URL").map_err(|e| Error::Configuration(Box::new(e)))?;
19+
20+
Ok(DB::Connection::connect(&db_url).await?)
1921
}
2022

2123
// Make a new pool

tests/any/any.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use sqlx::any::AnyRow;
1+
use sqlx::any::{install_default_drivers, AnyRow};
22
use sqlx::{Any, Connection, Executor, Row};
3+
use sqlx_core::error::BoxDynError;
34
use sqlx_core::sql_str::AssertSqlSafe;
5+
use sqlx_core::Error;
46
use sqlx_test::new;
57

68
#[sqlx_macros::test]
@@ -142,3 +144,65 @@ async fn it_can_fail_and_recover_with_pool() -> anyhow::Result<()> {
142144

143145
Ok(())
144146
}
147+
148+
#[sqlx_macros::test]
149+
async fn it_can_query_by_string_args() -> sqlx::Result<()> {
150+
install_default_drivers();
151+
152+
let mut conn = new::<Any>().await?;
153+
154+
let string = "Hello, world!".to_string();
155+
let ref tuple = ("Hello, world!".to_string(),);
156+
157+
#[cfg(feature = "postgres")]
158+
const SQL: &str =
159+
"SELECT 'Hello, world!' as string where 'Hello, world!' in ($1, $2, $3, $4, $5, $6, $7)";
160+
161+
#[cfg(not(feature = "postgres"))]
162+
const SQL: &str =
163+
"SELECT 'Hello, world!' as string where 'Hello, world!' in (?, ?, ?, ?, ?, ?, ?)";
164+
165+
{
166+
let query = sqlx::query(SQL)
167+
// validate flexibility of lifetimes
168+
.bind(&string)
169+
.bind(&string[..])
170+
.bind(Some(&string))
171+
.bind(Some(&string[..]))
172+
.bind(&Option::<String>::None)
173+
.bind(&string.clone())
174+
.bind(&tuple.0); // should not get "temporary value is freed at the end of this statement" here
175+
176+
let result = query.fetch_one(&mut conn).await?;
177+
178+
let column_0: String = result.try_get(0)?;
179+
180+
assert_eq!(column_0, string);
181+
}
182+
183+
{
184+
let mut query = sqlx::query(SQL);
185+
186+
let query = || -> Result<_, BoxDynError> {
187+
// validate flexibility of lifetimes
188+
query.try_bind(&string)?;
189+
query.try_bind(&string[..])?;
190+
query.try_bind(Some(&string))?;
191+
query.try_bind(Some(&string[..]))?;
192+
query.try_bind(&Option::<String>::None)?;
193+
query.try_bind(&string.clone())?;
194+
query.try_bind(&tuple.0)?;
195+
196+
Ok(query)
197+
}()
198+
.map_err(Error::Encode)?;
199+
200+
let result = query.fetch_one(&mut conn).await?;
201+
202+
let column_0: String = result.try_get(0)?;
203+
204+
assert_eq!(column_0, string);
205+
}
206+
207+
Ok(())
208+
}

0 commit comments

Comments
 (0)