From 0317728310f707ccad1072fdbdec6b0b04b4eb2f Mon Sep 17 00:00:00 2001 From: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Date: Sat, 2 Aug 2025 18:57:30 -0400 Subject: [PATCH 1/2] refactor(core): Remove lifetime parameter from Arguments trait Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> --- sqlx-core/src/any/arguments.rs | 8 ++--- sqlx-core/src/any/database.rs | 4 +-- sqlx-core/src/any/types/blob.rs | 6 ++-- sqlx-core/src/any/types/bool.rs | 4 +-- sqlx-core/src/any/types/float.rs | 4 +-- sqlx-core/src/any/types/int.rs | 12 +++---- sqlx-core/src/any/types/str.rs | 13 +++----- sqlx-core/src/arguments.rs | 27 +++++++--------- sqlx-core/src/database.rs | 4 +-- sqlx-core/src/encode.rs | 22 ++++++------- sqlx-core/src/executor.rs | 10 +++--- sqlx-core/src/query.rs | 33 +++++++++----------- sqlx-core/src/query_as.rs | 20 ++++++------ sqlx-core/src/query_builder.rs | 43 +++++++++++++------------- sqlx-core/src/query_scalar.rs | 18 +++++------ sqlx-core/src/raw_sql.rs | 4 +-- sqlx-core/src/statement.rs | 26 ++++++++-------- sqlx-core/src/testing/fixtures.rs | 2 +- sqlx-core/src/types/bstr.rs | 4 +-- sqlx-core/src/types/json.rs | 8 ++--- sqlx-core/src/types/non_zero.rs | 4 +-- sqlx-core/src/types/text.rs | 2 +- sqlx-macros-core/src/derives/encode.rs | 6 ++-- sqlx-macros-core/src/query/args.rs | 4 +-- sqlx-mysql/src/arguments.rs | 6 ++-- sqlx-mysql/src/database.rs | 4 +-- sqlx-mysql/src/types/mysql_time.rs | 4 +-- sqlx-postgres/src/arguments.rs | 6 ++-- sqlx-postgres/src/database.rs | 4 +-- sqlx-sqlite/src/arguments.rs | 12 +++---- sqlx-sqlite/src/database.rs | 4 +-- sqlx-sqlite/src/types/str.rs | 5 +-- tests/mysql/types.rs | 2 +- tests/postgres/query_builder.rs | 21 ++++++------- 34 files changed, 168 insertions(+), 188 deletions(-) diff --git a/sqlx-core/src/any/arguments.rs b/sqlx-core/src/any/arguments.rs index 28dadaa757..59d6f4d6e0 100644 --- a/sqlx-core/src/any/arguments.rs +++ b/sqlx-core/src/any/arguments.rs @@ -12,16 +12,16 @@ pub struct AnyArguments { pub values: AnyArgumentBuffer, } -impl<'q> Arguments<'q> for AnyArguments { +impl Arguments for AnyArguments { type Database = Any; fn reserve(&mut self, additional: usize, _size: usize) { self.values.0.reserve(additional); } - fn add(&mut self, value: T) -> Result<(), BoxDynError> + fn add<'t, T>(&mut self, value: T) -> Result<(), BoxDynError> where - T: 'q + Encode<'q, Self::Database> + Type, + T: Encode<'t, Self::Database> + Type, { let _: IsNull = value.encode(&mut self.values)?; Ok(()) @@ -37,7 +37,7 @@ pub struct AnyArgumentBuffer(#[doc(hidden)] pub Vec); impl AnyArguments { #[doc(hidden)] - pub fn convert_into<'a, A: Arguments<'a>>(self) -> Result + pub fn convert_into<'a, A: Arguments>(self) -> Result where Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, diff --git a/sqlx-core/src/any/database.rs b/sqlx-core/src/any/database.rs index 6e7a5f5ea8..6dd47003a2 100644 --- a/sqlx-core/src/any/database.rs +++ b/sqlx-core/src/any/database.rs @@ -25,8 +25,8 @@ impl Database for Any { type Value = AnyValue; type ValueRef<'r> = AnyValueRef<'r>; - type Arguments<'q> = AnyArguments; - type ArgumentBuffer<'q> = AnyArgumentBuffer; + type Arguments = AnyArguments; + type ArgumentBuffer = AnyArgumentBuffer; type Statement = AnyStatement; diff --git a/sqlx-core/src/any/types/blob.rs b/sqlx-core/src/any/types/blob.rs index 21379a6429..c6c82dde88 100644 --- a/sqlx-core/src/any/types/blob.rs +++ b/sqlx-core/src/any/types/blob.rs @@ -17,7 +17,7 @@ impl Type for [u8] { impl<'q> Encode<'q, Any> for &'q [u8] { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::Blob(Arc::new(self.to_vec()))); Ok(IsNull::No) @@ -39,10 +39,10 @@ impl Type for Vec { } } -impl<'q> Encode<'q, Any> for Vec { +impl Encode<'_, Any> for Vec { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::Blob(Arc::new(self.clone()))); Ok(IsNull::No) diff --git a/sqlx-core/src/any/types/bool.rs b/sqlx-core/src/any/types/bool.rs index ff915c5bfd..bc143e9bd5 100644 --- a/sqlx-core/src/any/types/bool.rs +++ b/sqlx-core/src/any/types/bool.rs @@ -13,10 +13,10 @@ impl Type for bool { } } -impl<'q> Encode<'q, Any> for bool { +impl Encode<'_, Any> for bool { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::Bool(*self)); Ok(IsNull::No) diff --git a/sqlx-core/src/any/types/float.rs b/sqlx-core/src/any/types/float.rs index 36ee38a05f..119e5ca95f 100644 --- a/sqlx-core/src/any/types/float.rs +++ b/sqlx-core/src/any/types/float.rs @@ -37,10 +37,10 @@ impl Type for f64 { } } -impl<'q> Encode<'q, Any> for f64 { +impl Encode<'_, Any> for f64 { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::Double(*self)); Ok(IsNull::No) diff --git a/sqlx-core/src/any/types/int.rs b/sqlx-core/src/any/types/int.rs index 56152af146..e2bb43212f 100644 --- a/sqlx-core/src/any/types/int.rs +++ b/sqlx-core/src/any/types/int.rs @@ -17,10 +17,10 @@ impl Type for i16 { } } -impl<'q> Encode<'q, Any> for i16 { +impl Encode<'_, Any> for i16 { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::SmallInt(*self)); Ok(IsNull::No) @@ -45,10 +45,10 @@ impl Type for i32 { } } -impl<'q> Encode<'q, Any> for i32 { +impl Encode<'_, Any> for i32 { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::Integer(*self)); Ok(IsNull::No) @@ -73,10 +73,10 @@ impl Type for i64 { } } -impl<'q> Encode<'q, Any> for i64 { +impl Encode<'_, Any> for i64 { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::BigInt(*self)); Ok(IsNull::No) diff --git a/sqlx-core/src/any/types/str.rs b/sqlx-core/src/any/types/str.rs index 3faf6a1708..620262491b 100644 --- a/sqlx-core/src/any/types/str.rs +++ b/sqlx-core/src/any/types/str.rs @@ -16,7 +16,7 @@ impl Type for str { } impl<'a> Encode<'a, Any> for &'a str { - fn encode(self, buf: &mut ::ArgumentBuffer<'a>) -> Result + fn encode(self, buf: &mut ::ArgumentBuffer) -> Result where Self: Sized, { @@ -26,7 +26,7 @@ impl<'a> Encode<'a, Any> for &'a str { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'a>, + buf: &mut ::ArgumentBuffer, ) -> Result { (*self).encode(buf) } @@ -47,18 +47,15 @@ impl Type for String { } } -impl<'q> Encode<'q, Any> for String { - fn encode( - self, - buf: &mut ::ArgumentBuffer<'q>, - ) -> Result { +impl Encode<'_, Any> for String { + fn encode(self, buf: &mut ::ArgumentBuffer) -> Result { buf.0.push(AnyValueKind::Text(Arc::new(self))); Ok(IsNull::No) } fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { buf.0.push(AnyValueKind::Text(Arc::new(self.clone()))); Ok(IsNull::No) diff --git a/sqlx-core/src/arguments.rs b/sqlx-core/src/arguments.rs index 4bf826ed31..7b9da60b9c 100644 --- a/sqlx-core/src/arguments.rs +++ b/sqlx-core/src/arguments.rs @@ -9,7 +9,7 @@ use std::fmt::{self, Write}; /// A tuple of arguments to be sent to the database. // This lint is designed for general collections, but `Arguments` is not meant to be as such. #[allow(clippy::len_without_is_empty)] -pub trait Arguments<'q>: Send + Sized + Default { +pub trait Arguments: Send + Sized + Default { type Database: Database; /// Reserves the capacity for at least `additional` more values (of `size` total bytes) to @@ -17,9 +17,9 @@ pub trait Arguments<'q>: Send + Sized + Default { fn reserve(&mut self, additional: usize, size: usize); /// Add the value to the end of the arguments. - fn add(&mut self, value: T) -> Result<(), BoxDynError> + fn add<'t, T>(&mut self, value: T) -> Result<(), BoxDynError> where - T: 'q + Encode<'q, Self::Database> + Type; + T: Encode<'t, Self::Database> + Type; /// The number of arguments that were already added. fn len(&self) -> usize; @@ -29,19 +29,17 @@ pub trait Arguments<'q>: Send + Sized + Default { } } -pub trait IntoArguments<'q, DB: Database>: Sized + Send { - fn into_arguments(self) -> ::Arguments<'q>; +pub trait IntoArguments: Sized + Send { + fn into_arguments(self) -> ::Arguments; } // NOTE: required due to lack of lazy normalization #[macro_export] macro_rules! impl_into_arguments_for_arguments { ($Arguments:path) => { - impl<'q> - $crate::arguments::IntoArguments< - 'q, - <$Arguments as $crate::arguments::Arguments<'q>>::Database, - > for $Arguments + impl + $crate::arguments::IntoArguments<<$Arguments as $crate::arguments::Arguments>::Database> + for $Arguments { fn into_arguments(self) -> $Arguments { self @@ -51,13 +49,10 @@ macro_rules! impl_into_arguments_for_arguments { } /// used by the query macros to prevent supernumerary `.bind()` calls -pub struct ImmutableArguments<'q, DB: Database>(pub ::Arguments<'q>); +pub struct ImmutableArguments(pub ::Arguments); -impl<'q, DB: Database> IntoArguments<'q, DB> for ImmutableArguments<'q, DB> { - fn into_arguments(self) -> ::Arguments<'q> { +impl IntoArguments for ImmutableArguments { + fn into_arguments(self) -> ::Arguments { self.0 } } - -// TODO: Impl `IntoArguments` for &[&dyn Encode] -// TODO: Impl `IntoArguments` for (impl Encode, ...) x16 diff --git a/sqlx-core/src/database.rs b/sqlx-core/src/database.rs index f89e5e7156..e7aaeb1ffc 100644 --- a/sqlx-core/src/database.rs +++ b/sqlx-core/src/database.rs @@ -96,9 +96,9 @@ pub trait Database: 'static + Sized + Send + Debug { type ValueRef<'r>: ValueRef<'r, Database = Self>; /// The concrete `Arguments` implementation for this database. - type Arguments<'q>: Arguments<'q, Database = Self>; + type Arguments: Arguments; /// The concrete type used as a buffer for arguments while encoding. - type ArgumentBuffer<'q>; + type ArgumentBuffer; /// The concrete `Statement` implementation for this database. type Statement: Statement; diff --git a/sqlx-core/src/encode.rs b/sqlx-core/src/encode.rs index ba9a1d40c9..173c283e73 100644 --- a/sqlx-core/src/encode.rs +++ b/sqlx-core/src/encode.rs @@ -29,7 +29,7 @@ impl IsNull { /// Encode a single value to be sent to the database. pub trait Encode<'q, DB: Database> { /// Writes the value of `self` into `buf` in the expected format for the database. - fn encode(self, buf: &mut ::ArgumentBuffer<'q>) -> Result + fn encode(self, buf: &mut ::ArgumentBuffer) -> Result where Self: Sized, { @@ -42,7 +42,7 @@ pub trait Encode<'q, DB: Database> { /// memory. fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result; fn produces(&self) -> Option { @@ -62,14 +62,14 @@ where T: Encode<'q, DB>, { #[inline] - fn encode(self, buf: &mut ::ArgumentBuffer<'q>) -> Result { + fn encode(self, buf: &mut ::ArgumentBuffer) -> Result { >::encode_by_ref(self, buf) } #[inline] fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { <&T as Encode>::encode(self, buf) } @@ -104,7 +104,7 @@ macro_rules! impl_encode_for_option { #[inline] fn encode( self, - buf: &mut <$DB as $crate::database::Database>::ArgumentBuffer<'q>, + buf: &mut <$DB as $crate::database::Database>::ArgumentBuffer, ) -> Result<$crate::encode::IsNull, $crate::error::BoxDynError> { if let Some(v) = self { v.encode(buf) @@ -116,7 +116,7 @@ macro_rules! impl_encode_for_option { #[inline] fn encode_by_ref( &self, - buf: &mut <$DB as $crate::database::Database>::ArgumentBuffer<'q>, + buf: &mut <$DB as $crate::database::Database>::ArgumentBuffer, ) -> Result<$crate::encode::IsNull, $crate::error::BoxDynError> { if let Some(v) = self { v.encode_by_ref(buf) @@ -142,7 +142,7 @@ macro_rules! impl_encode_for_smartpointer { #[inline] fn encode( self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { >::encode_by_ref(self.as_ref(), buf) } @@ -150,7 +150,7 @@ macro_rules! impl_encode_for_smartpointer { #[inline] fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { <&T as Encode>::encode(self, buf) } @@ -178,14 +178,14 @@ where T: ToOwned, { #[inline] - fn encode(self, buf: &mut ::ArgumentBuffer<'q>) -> Result { + fn encode(self, buf: &mut ::ArgumentBuffer) -> Result { <&T as Encode>::encode_by_ref(&self.as_ref(), buf) } #[inline] fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { <&T as Encode>::encode_by_ref(&self.as_ref(), buf) } @@ -207,7 +207,7 @@ macro_rules! forward_encode_impl { impl<'q> Encode<'q, $db> for $for_type { fn encode_by_ref( &self, - buf: &mut <$db as sqlx_core::database::Database>::ArgumentBuffer<'q>, + buf: &mut <$db as sqlx_core::database::Database>::ArgumentBuffer, ) -> Result { <$forward_to as Encode<$db>>::encode(self.as_ref(), buf) } diff --git a/sqlx-core/src/executor.rs b/sqlx-core/src/executor.rs index ab9737c9cd..e1c42fc706 100644 --- a/sqlx-core/src/executor.rs +++ b/sqlx-core/src/executor.rs @@ -204,13 +204,13 @@ pub trait Execute<'q, DB: Database>: Send + Sized { /// will be prepared (and cached) before execution. /// /// Returns `Err` if encoding any of the arguments failed. - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError>; + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError>; /// Returns `true` if the statement should be cached. fn persistent(&self) -> bool; } -impl<'q, DB: Database, T> Execute<'q, DB> for T +impl Execute<'_, DB> for T where T: SqlSafeStr + Send, { @@ -225,7 +225,7 @@ where } #[inline] - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError> { + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError> { Ok(None) } @@ -235,7 +235,7 @@ where } } -impl<'q, DB: Database, T> Execute<'q, DB> for (T, Option<::Arguments<'q>>) +impl Execute<'_, DB> for (T, Option<::Arguments>) where T: SqlSafeStr + Send, { @@ -250,7 +250,7 @@ where } #[inline] - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError> { + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError> { Ok(self.1.take()) } diff --git a/sqlx-core/src/query.rs b/sqlx-core/src/query.rs index f76b2bd842..9d8f14e7bc 100644 --- a/sqlx-core/src/query.rs +++ b/sqlx-core/src/query.rs @@ -42,7 +42,7 @@ pub struct Map<'q, DB: Database, F, A> { impl<'q, DB, A> Execute<'q, DB> for Query<'q, DB, A> where DB: Database, - A: Send + IntoArguments<'q, DB>, + A: Send + IntoArguments, { #[inline] fn sql(self) -> SqlStr { @@ -60,7 +60,7 @@ where } #[inline] - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError> { + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError> { self.arguments .take() .transpose() @@ -73,7 +73,7 @@ where } } -impl<'q, DB: Database> Query<'q, DB, ::Arguments<'q>> { +impl<'q, DB: Database> Query<'q, DB, ::Arguments> { /// Bind a value for use with this SQL query. /// /// If the number of times this is called does not match the number of bind parameters that @@ -110,7 +110,7 @@ impl<'q, DB: Database> Query<'q, DB, ::Arguments<'q>> { arguments.add(value) } - fn get_arguments(&mut self) -> Result<&mut DB::Arguments<'q>, BoxDynError> { + fn get_arguments(&mut self) -> Result<&mut DB::Arguments, BoxDynError> { let Some(Ok(arguments)) = self.arguments.as_mut().map(Result::as_mut) else { return Err("A previous call to Query::bind produced an error" .to_owned() @@ -144,7 +144,7 @@ where impl<'q, DB, A: Send> Query<'q, DB, A> where DB: Database, - A: 'q + IntoArguments<'q, DB>, + A: 'q + IntoArguments, { /// Map each row in the result to another type. /// @@ -301,7 +301,7 @@ where impl<'q, DB, F: Send, A: Send> Execute<'q, DB> for Map<'q, DB, F, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, { #[inline] fn sql(self) -> SqlStr { @@ -314,7 +314,7 @@ where } #[inline] - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError> { + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError> { self.inner.take_arguments() } @@ -329,7 +329,7 @@ where DB: Database, F: FnMut(DB::Row) -> Result + Send, O: Send + Unpin, - A: 'q + Send + IntoArguments<'q, DB>, + A: 'q + Send + IntoArguments, { /// Map each row in the result to another type. /// @@ -500,9 +500,7 @@ where } /// Execute a single SQL query as a prepared statement (explicitly created). -pub fn query_statement( - statement: &DB::Statement, -) -> Query<'_, DB, ::Arguments<'_>> +pub fn query_statement(statement: &DB::Statement) -> Query<'_, DB, ::Arguments> where DB: Database, { @@ -515,13 +513,10 @@ where } /// Execute a single SQL query as a prepared statement (explicitly created), with the given arguments. -pub fn query_statement_with<'q, DB, A>( - statement: &'q DB::Statement, - arguments: A, -) -> Query<'q, DB, A> +pub fn query_statement_with(statement: &DB::Statement, arguments: A) -> Query<'_, DB, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, { Query { database: PhantomData, @@ -655,7 +650,7 @@ where /// /// As an additional benefit, query parameters are usually sent in a compact binary encoding instead of a human-readable /// text encoding, which saves bandwidth. -pub fn query<'a, DB>(sql: impl SqlSafeStr) -> Query<'a, DB, ::Arguments<'a>> +pub fn query<'a, DB>(sql: impl SqlSafeStr) -> Query<'a, DB, ::Arguments> where DB: Database, { @@ -673,7 +668,7 @@ where pub fn query_with<'q, DB, A>(sql: impl SqlSafeStr, arguments: A) -> Query<'q, DB, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, { query_with_result(sql, Ok(arguments)) } @@ -685,7 +680,7 @@ pub fn query_with_result<'q, DB, A>( ) -> Query<'q, DB, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, { Query { database: PhantomData, diff --git a/sqlx-core/src/query_as.rs b/sqlx-core/src/query_as.rs index e58a3f0f8b..00194cba57 100644 --- a/sqlx-core/src/query_as.rs +++ b/sqlx-core/src/query_as.rs @@ -25,7 +25,7 @@ pub struct QueryAs<'q, DB: Database, O, A> { impl<'q, DB, O: Send, A: Send> Execute<'q, DB> for QueryAs<'q, DB, O, A> where DB: Database, - A: 'q + IntoArguments<'q, DB>, + A: 'q + IntoArguments, { #[inline] fn sql(self) -> SqlStr { @@ -38,7 +38,7 @@ where } #[inline] - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError> { + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError> { self.inner.take_arguments() } @@ -48,7 +48,7 @@ where } } -impl<'q, DB: Database, O> QueryAs<'q, DB, O, ::Arguments<'q>> { +impl<'q, DB: Database, O> QueryAs<'q, DB, O, ::Arguments> { /// Bind a value for use with this SQL query. /// /// See [`Query::bind`](Query::bind). @@ -83,7 +83,7 @@ where impl<'q, DB, O, A> QueryAs<'q, DB, O, A> where DB: Database, - A: 'q + IntoArguments<'q, DB>, + A: 'q + IntoArguments, O: Send + Unpin + for<'r> FromRow<'r, DB::Row>, { /// Execute the query and return the generated results as a stream. @@ -338,9 +338,7 @@ where /// /// ``` #[inline] -pub fn query_as<'q, DB, O>( - sql: impl SqlSafeStr, -) -> QueryAs<'q, DB, O, ::Arguments<'q>> +pub fn query_as<'q, DB, O>(sql: impl SqlSafeStr) -> QueryAs<'q, DB, O, ::Arguments> where DB: Database, O: for<'r> FromRow<'r, DB::Row>, @@ -361,7 +359,7 @@ where pub fn query_as_with<'q, DB, O, A>(sql: impl SqlSafeStr, arguments: A) -> QueryAs<'q, DB, O, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, O: for<'r> FromRow<'r, DB::Row>, { query_as_with_result(sql, Ok(arguments)) @@ -375,7 +373,7 @@ pub fn query_as_with_result<'q, DB, O, A>( ) -> QueryAs<'q, DB, O, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, O: for<'r> FromRow<'r, DB::Row>, { QueryAs { @@ -387,7 +385,7 @@ where // Make a SQL query from a statement, that is mapped to a concrete type. pub fn query_statement_as( statement: &DB::Statement, -) -> QueryAs<'_, DB, O, ::Arguments<'_>> +) -> QueryAs<'_, DB, O, ::Arguments> where DB: Database, O: for<'r> FromRow<'r, DB::Row>, @@ -405,7 +403,7 @@ pub fn query_statement_as_with<'q, DB, O, A>( ) -> QueryAs<'q, DB, O, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, O: for<'r> FromRow<'r, DB::Row>, { QueryAs { diff --git a/sqlx-core/src/query_builder.rs b/sqlx-core/src/query_builder.rs index 7dff67831c..25aa500aea 100644 --- a/sqlx-core/src/query_builder.rs +++ b/sqlx-core/src/query_builder.rs @@ -25,16 +25,16 @@ use crate::Either; /// and `UNNEST()`. [See our FAQ] for details. /// /// [See our FAQ]: https://github.com/launchbadge/sqlx/blob/master/FAQ.md#how-can-i-bind-an-array-to-a-values-clause-how-can-i-do-bulk-inserts -pub struct QueryBuilder<'args, DB> +pub struct QueryBuilder where DB: Database, { query: Arc, init_len: usize, - arguments: Option<::Arguments<'args>>, + arguments: Option<::Arguments>, } -impl Default for QueryBuilder<'_, DB> { +impl Default for QueryBuilder { fn default() -> Self { QueryBuilder { init_len: 0, @@ -46,7 +46,7 @@ impl Default for QueryBuilder<'_, DB> { const ERROR: &str = "BUG: query must not be shared at this point in time"; -impl<'args, DB: Database> QueryBuilder<'args, DB> +impl QueryBuilder where DB: Database, { @@ -55,7 +55,7 @@ where /// Start building a query with an initial SQL fragment, which may be an empty string. pub fn new(init: impl Into) -> Self where - ::Arguments<'args>: Default, + ::Arguments: Default, { let init = init.into(); @@ -73,7 +73,7 @@ where pub fn with_arguments(init: impl Into, arguments: A) -> Self where DB: Database, - A: IntoArguments<'args, DB>, + A: IntoArguments, { let init = init.into(); @@ -152,9 +152,9 @@ where /// /// [`SQLITE_LIMIT_VARIABLE_NUMBER`]: https://www.sqlite.org/limits.html#max_variable_number /// [postgres-limit-issue]: https://github.com/launchbadge/sqlx/issues/671#issuecomment-687043510 - pub fn push_bind(&mut self, value: T) -> &mut Self + pub fn push_bind<'t, T>(&mut self, value: T) -> &mut Self where - T: 'args + Encode<'args, DB> + Type, + T: Encode<'t, DB> + Type, { self.sanity_check(); @@ -199,9 +199,8 @@ where /// assert!(sql.ends_with("in (?, ?) ")); /// # } /// ``` - pub fn separated<'qb, Sep>(&'qb mut self, separator: Sep) -> Separated<'qb, 'args, DB, Sep> + pub fn separated(&mut self, separator: Sep) -> Separated<'_, DB, Sep> where - 'args: 'qb, Sep: Display, { self.sanity_check(); @@ -313,7 +312,7 @@ where pub fn push_values(&mut self, tuples: I, mut push_tuple: F) -> &mut Self where I: IntoIterator, - F: FnMut(Separated<'_, 'args, DB, &'static str>, I::Item), + F: FnMut(Separated<'_, DB, &'static str>, I::Item), { self.sanity_check(); @@ -425,7 +424,7 @@ where pub fn push_tuples(&mut self, tuples: I, mut push_tuple: F) -> &mut Self where I: IntoIterator, - F: FnMut(Separated<'_, 'args, DB, &'static str>, I::Item), + F: FnMut(Separated<'_, DB, &'static str>, I::Item), { self.sanity_check(); @@ -457,7 +456,7 @@ where /// to the state it was in immediately after [`new()`][Self::new]. /// /// Calling any other method but `.reset()` after `.build()` will panic for sanity reasons. - pub fn build(&mut self) -> Query<'_, DB, ::Arguments<'args>> { + pub fn build(&mut self) -> Query<'_, DB, ::Arguments> { self.sanity_check(); Query { @@ -482,7 +481,7 @@ where /// Calling any other method but `.reset()` after `.build()` will panic for sanity reasons. pub fn build_query_as<'q, T: FromRow<'q, DB::Row>>( &'q mut self, - ) -> QueryAs<'q, DB, T, ::Arguments<'args>> { + ) -> QueryAs<'q, DB, T, ::Arguments> { QueryAs { inner: self.build(), output: PhantomData, @@ -503,7 +502,7 @@ where /// Calling any other method but `.reset()` after `.build()` will panic for sanity reasons. pub fn build_query_scalar<'q, T>( &'q mut self, - ) -> QueryScalar<'q, DB, T, ::Arguments<'args>> + ) -> QueryScalar<'q, DB, T, ::Arguments> where DB: Database, (T,): for<'r> FromRow<'r, DB::Row>, @@ -547,16 +546,16 @@ where /// /// See [`QueryBuilder::separated()`] for details. #[allow(explicit_outlives_requirements)] -pub struct Separated<'qb, 'args: 'qb, DB, Sep> +pub struct Separated<'qb, DB, Sep> where DB: Database, { - query_builder: &'qb mut QueryBuilder<'args, DB>, + query_builder: &'qb mut QueryBuilder, separator: Sep, push_separator: bool, } -impl<'qb, 'args: 'qb, DB, Sep> Separated<'qb, 'args, DB, Sep> +impl Separated<'_, DB, Sep> where DB: Database, Sep: Display, @@ -587,9 +586,9 @@ where /// Push the separator if applicable, then append a bind argument. /// /// See [`QueryBuilder::push_bind()`] for details. - pub fn push_bind(&mut self, value: T) -> &mut Self + pub fn push_bind<'t, T>(&mut self, value: T) -> &mut Self where - T: 'args + Encode<'args, DB> + Type, + T: Encode<'t, DB> + Type, { if self.push_separator { self.query_builder.push(&self.separator); @@ -605,9 +604,9 @@ where /// without a separator. /// /// Simply calls [`QueryBuilder::push_bind()`] directly. - pub fn push_bind_unseparated(&mut self, value: T) -> &mut Self + pub fn push_bind_unseparated<'t, T>(&mut self, value: T) -> &mut Self where - T: 'args + Encode<'args, DB> + Type, + T: Encode<'t, DB> + Type, { self.query_builder.push_bind(value); self diff --git a/sqlx-core/src/query_scalar.rs b/sqlx-core/src/query_scalar.rs index 1059463874..f760158c4a 100644 --- a/sqlx-core/src/query_scalar.rs +++ b/sqlx-core/src/query_scalar.rs @@ -23,7 +23,7 @@ pub struct QueryScalar<'q, DB: Database, O, A> { impl<'q, DB: Database, O: Send, A: Send> Execute<'q, DB> for QueryScalar<'q, DB, O, A> where - A: 'q + IntoArguments<'q, DB>, + A: 'q + IntoArguments, { #[inline] fn sql(self) -> SqlStr { @@ -35,7 +35,7 @@ where } #[inline] - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError> { + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError> { self.inner.take_arguments() } @@ -45,7 +45,7 @@ where } } -impl<'q, DB: Database, O> QueryScalar<'q, DB, O, ::Arguments<'q>> { +impl<'q, DB: Database, O> QueryScalar<'q, DB, O, ::Arguments> { /// Bind a value for use with this SQL query. /// /// See [`Query::bind`](crate::query::Query::bind). @@ -81,7 +81,7 @@ impl<'q, DB, O, A> QueryScalar<'q, DB, O, A> where DB: Database, O: Send + Unpin, - A: 'q + IntoArguments<'q, DB>, + A: 'q + IntoArguments, (O,): Send + Unpin + for<'r> FromRow<'r, DB::Row>, { /// Execute the query and return the generated results as a stream. @@ -321,7 +321,7 @@ where #[inline] pub fn query_scalar<'q, DB, O>( sql: impl SqlSafeStr, -) -> QueryScalar<'q, DB, O, ::Arguments<'q>> +) -> QueryScalar<'q, DB, O, ::Arguments> where DB: Database, (O,): for<'r> FromRow<'r, DB::Row>, @@ -344,7 +344,7 @@ pub fn query_scalar_with<'q, DB, O, A>( ) -> QueryScalar<'q, DB, O, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, (O,): for<'r> FromRow<'r, DB::Row>, { query_scalar_with_result(sql, Ok(arguments)) @@ -358,7 +358,7 @@ pub fn query_scalar_with_result<'q, DB, O, A>( ) -> QueryScalar<'q, DB, O, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, (O,): for<'r> FromRow<'r, DB::Row>, { QueryScalar { @@ -369,7 +369,7 @@ where // Make a SQL query from a statement, that is mapped to a concrete value. pub fn query_statement_scalar( statement: &DB::Statement, -) -> QueryScalar<'_, DB, O, ::Arguments<'_>> +) -> QueryScalar<'_, DB, O, ::Arguments> where DB: Database, (O,): for<'r> FromRow<'r, DB::Row>, @@ -386,7 +386,7 @@ pub fn query_statement_scalar_with<'q, DB, O, A>( ) -> QueryScalar<'q, DB, O, A> where DB: Database, - A: IntoArguments<'q, DB>, + A: IntoArguments, (O,): for<'r> FromRow<'r, DB::Row>, { QueryScalar { diff --git a/sqlx-core/src/raw_sql.rs b/sqlx-core/src/raw_sql.rs index d2668ebe40..0292885422 100644 --- a/sqlx-core/src/raw_sql.rs +++ b/sqlx-core/src/raw_sql.rs @@ -120,7 +120,7 @@ pub fn raw_sql(sql: impl SqlSafeStr) -> RawSql { RawSql(sql.into_sql_str()) } -impl<'q, DB: Database> Execute<'q, DB> for RawSql { +impl Execute<'_, DB> for RawSql { fn sql(self) -> SqlStr { self.0 } @@ -129,7 +129,7 @@ impl<'q, DB: Database> Execute<'q, DB> for RawSql { None } - fn take_arguments(&mut self) -> Result::Arguments<'q>>, BoxDynError> { + fn take_arguments(&mut self) -> Result::Arguments>, BoxDynError> { Ok(None) } diff --git a/sqlx-core/src/statement.rs b/sqlx-core/src/statement.rs index 76d0325639..92ae8a629e 100644 --- a/sqlx-core/src/statement.rs +++ b/sqlx-core/src/statement.rs @@ -59,33 +59,33 @@ pub trait Statement: Send + Sync + Clone { Ok(&self.columns()[index.index(self)?]) } - fn query(&self) -> Query<'_, Self::Database, ::Arguments<'_>>; + fn query(&self) -> Query<'_, Self::Database, ::Arguments>; - fn query_with<'s, A>(&'s self, arguments: A) -> Query<'s, Self::Database, A> + fn query_with(&self, arguments: A) -> Query<'_, Self::Database, A> where - A: IntoArguments<'s, Self::Database>; + A: IntoArguments; fn query_as( &self, - ) -> QueryAs<'_, Self::Database, O, ::Arguments<'_>> + ) -> QueryAs<'_, Self::Database, O, ::Arguments> where O: for<'r> FromRow<'r, ::Row>; fn query_as_with<'s, O, A>(&'s self, arguments: A) -> QueryAs<'s, Self::Database, O, A> where O: for<'r> FromRow<'r, ::Row>, - A: IntoArguments<'s, Self::Database>; + A: IntoArguments; fn query_scalar( &self, - ) -> QueryScalar<'_, Self::Database, O, ::Arguments<'_>> + ) -> QueryScalar<'_, Self::Database, O, ::Arguments> where (O,): for<'r> FromRow<'r, ::Row>; fn query_scalar_with<'s, O, A>(&'s self, arguments: A) -> QueryScalar<'s, Self::Database, O, A> where (O,): for<'r> FromRow<'r, ::Row>, - A: IntoArguments<'s, Self::Database>; + A: IntoArguments; } #[macro_export] @@ -97,9 +97,9 @@ macro_rules! impl_statement_query { } #[inline] - fn query_with<'s, A>(&'s self, arguments: A) -> $crate::query::Query<'s, Self::Database, A> + fn query_with(&self, arguments: A) -> $crate::query::Query<'_, Self::Database, A> where - A: $crate::arguments::IntoArguments<'s, Self::Database>, + A: $crate::arguments::IntoArguments, { $crate::query::query_statement_with(self, arguments) } @@ -111,7 +111,7 @@ macro_rules! impl_statement_query { '_, Self::Database, O, - ::Arguments<'_>, + ::Arguments, > where O: for<'r> $crate::from_row::FromRow< @@ -132,7 +132,7 @@ macro_rules! impl_statement_query { 'r, ::Row, >, - A: $crate::arguments::IntoArguments<'s, Self::Database>, + A: $crate::arguments::IntoArguments, { $crate::query_as::query_statement_as_with(self, arguments) } @@ -144,7 +144,7 @@ macro_rules! impl_statement_query { '_, Self::Database, O, - ::Arguments<'_>, + ::Arguments, > where (O,): for<'r> $crate::from_row::FromRow< @@ -165,7 +165,7 @@ macro_rules! impl_statement_query { 'r, ::Row, >, - A: $crate::arguments::IntoArguments<'s, Self::Database>, + A: $crate::arguments::IntoArguments, { $crate::query_scalar::query_statement_scalar_with(self, arguments) } diff --git a/sqlx-core/src/testing/fixtures.rs b/sqlx-core/src/testing/fixtures.rs index 32fdfe2219..17f67e0fda 100644 --- a/sqlx-core/src/testing/fixtures.rs +++ b/sqlx-core/src/testing/fixtures.rs @@ -112,7 +112,7 @@ impl FixtureSnapshot { #[allow(clippy::to_string_trait_impl)] impl ToString for Fixture where - for<'a> ::Arguments<'a>: Default, + for<'a> ::Arguments: Default, { fn to_string(&self) -> String { let mut query = QueryBuilder::::new(""); diff --git a/sqlx-core/src/types/bstr.rs b/sqlx-core/src/types/bstr.rs index 4b6daadfde..5afae9a865 100644 --- a/sqlx-core/src/types/bstr.rs +++ b/sqlx-core/src/types/bstr.rs @@ -39,7 +39,7 @@ where { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { <&[u8] as Encode>::encode(self.as_bytes(), buf) } @@ -52,7 +52,7 @@ where { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { as Encode>::encode(self.as_bytes().to_vec(), buf) } diff --git a/sqlx-core/src/types/json.rs b/sqlx-core/src/types/json.rs index 2cff5e149b..3b94d8729b 100644 --- a/sqlx-core/src/types/json.rs +++ b/sqlx-core/src/types/json.rs @@ -166,7 +166,7 @@ where { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { as Encode<'q, DB>>::encode(Json(self), buf) } @@ -203,7 +203,7 @@ where { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { as Encode<'q, DB>>::encode(Json(self), buf) } @@ -216,7 +216,7 @@ where { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { as Encode<'q, DB>>::encode(Json(self), buf) } @@ -229,7 +229,7 @@ where { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { as Encode<'q, DB>>::encode(Json(self), buf) } diff --git a/sqlx-core/src/types/non_zero.rs b/sqlx-core/src/types/non_zero.rs index 3d92810ef9..4f04768468 100644 --- a/sqlx-core/src/types/non_zero.rs +++ b/sqlx-core/src/types/non_zero.rs @@ -33,11 +33,11 @@ macro_rules! impl_non_zero { DB: Database, $int: Encode<'q, DB>, { - fn encode_by_ref(&self, buf: &mut ::ArgumentBuffer<'q>) -> Result { + fn encode_by_ref(&self, buf: &mut ::ArgumentBuffer) -> Result { <$int as Encode<'q, DB>>::encode_by_ref(&self.get(), buf) } - fn encode(self, buf: &mut ::ArgumentBuffer<'q>) -> Result + fn encode(self, buf: &mut ::ArgumentBuffer) -> Result where Self: Sized, { diff --git a/sqlx-core/src/types/text.rs b/sqlx-core/src/types/text.rs index f5e323eea8..941e80ce10 100644 --- a/sqlx-core/src/types/text.rs +++ b/sqlx-core/src/types/text.rs @@ -115,7 +115,7 @@ where String: Encode<'q, DB>, DB: Database, { - fn encode_by_ref(&self, buf: &mut ::ArgumentBuffer<'q>) -> Result { + fn encode_by_ref(&self, buf: &mut ::ArgumentBuffer) -> Result { self.0.to_string().encode(buf) } } diff --git a/sqlx-macros-core/src/derives/encode.rs b/sqlx-macros-core/src/derives/encode.rs index 8850efdf4f..1dc1b5ad10 100644 --- a/sqlx-macros-core/src/derives/encode.rs +++ b/sqlx-macros-core/src/derives/encode.rs @@ -89,7 +89,7 @@ fn expand_derive_encode_transparent( { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<#lifetime>, + buf: &mut ::ArgumentBuffer, ) -> ::std::result::Result<::sqlx::encode::IsNull, ::sqlx::error::BoxDynError> { <#ty as ::sqlx::encode::Encode<#lifetime, DB>>::encode_by_ref(&self.#field_ident, buf) } @@ -128,7 +128,7 @@ fn expand_derive_encode_weak_enum( { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> ::std::result::Result<::sqlx::encode::IsNull, ::sqlx::error::BoxDynError> { let value = match self { #(#values)* @@ -178,7 +178,7 @@ fn expand_derive_encode_strong_enum( { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> ::std::result::Result<::sqlx::encode::IsNull, ::sqlx::error::BoxDynError> { let val = match self { #(#value_arms)* diff --git a/sqlx-macros-core/src/query/args.rs b/sqlx-macros-core/src/query/args.rs index 1b338efa3e..701957b42e 100644 --- a/sqlx-macros-core/src/query/args.rs +++ b/sqlx-macros-core/src/query/args.rs @@ -22,7 +22,7 @@ pub fn quote_args( if input.arg_exprs.is_empty() { return Ok(quote! { - let query_args = ::core::result::Result::<_, ::sqlx::error::BoxDynError>::Ok(<#db_path as ::sqlx::database::Database>::Arguments::<'_>::default()); + let query_args = ::core::result::Result::<_, ::sqlx::error::BoxDynError>::Ok(<#db_path as ::sqlx::database::Database>::Arguments::default()); }); } @@ -95,7 +95,7 @@ pub fn quote_args( #args_check - let mut query_args = <#db_path as ::sqlx::database::Database>::Arguments::<'_>::default(); + let mut query_args = <#db_path as ::sqlx::database::Database>::Arguments::default(); query_args.reserve( #args_count, 0 #(+ ::sqlx::encode::Encode::<#db_path>::size_hint(#arg_name))* diff --git a/sqlx-mysql/src/arguments.rs b/sqlx-mysql/src/arguments.rs index 464529cba2..306431039d 100644 --- a/sqlx-mysql/src/arguments.rs +++ b/sqlx-mysql/src/arguments.rs @@ -37,7 +37,7 @@ impl MySqlArguments { } } -impl<'q> Arguments<'q> for MySqlArguments { +impl Arguments for MySqlArguments { type Database = MySql; fn reserve(&mut self, len: usize, size: usize) { @@ -45,9 +45,9 @@ impl<'q> Arguments<'q> for MySqlArguments { self.values.reserve(size); } - fn add(&mut self, value: T) -> Result<(), BoxDynError> + fn add<'t, T>(&mut self, value: T) -> Result<(), BoxDynError> where - T: Encode<'q, Self::Database> + Type, + T: Encode<'t, Self::Database> + Type, { self.add(value) } diff --git a/sqlx-mysql/src/database.rs b/sqlx-mysql/src/database.rs index 0e3f51f532..849ddbde61 100644 --- a/sqlx-mysql/src/database.rs +++ b/sqlx-mysql/src/database.rs @@ -25,8 +25,8 @@ impl Database for MySql { type Value = MySqlValue; type ValueRef<'r> = MySqlValueRef<'r>; - type Arguments<'q> = MySqlArguments; - type ArgumentBuffer<'q> = Vec; + type Arguments = MySqlArguments; + type ArgumentBuffer = Vec; type Statement = MySqlStatement; diff --git a/sqlx-mysql/src/types/mysql_time.rs b/sqlx-mysql/src/types/mysql_time.rs index b549af5765..6af10aa216 100644 --- a/sqlx-mysql/src/types/mysql_time.rs +++ b/sqlx-mysql/src/types/mysql_time.rs @@ -409,10 +409,10 @@ impl<'r> Decode<'r, MySql> for MySqlTime { } } -impl<'q> Encode<'q, MySql> for MySqlTime { +impl Encode<'_, MySql> for MySqlTime { fn encode_by_ref( &self, - buf: &mut ::ArgumentBuffer<'q>, + buf: &mut ::ArgumentBuffer, ) -> Result { if self.is_zero() { buf.put_u8(0); diff --git a/sqlx-postgres/src/arguments.rs b/sqlx-postgres/src/arguments.rs index 62a227e52d..c0db982c7d 100644 --- a/sqlx-postgres/src/arguments.rs +++ b/sqlx-postgres/src/arguments.rs @@ -138,7 +138,7 @@ impl PgArguments { } } -impl<'q> Arguments<'q> for PgArguments { +impl Arguments for PgArguments { type Database = Postgres; fn reserve(&mut self, additional: usize, size: usize) { @@ -146,9 +146,9 @@ impl<'q> Arguments<'q> for PgArguments { self.buffer.reserve(size); } - fn add(&mut self, value: T) -> Result<(), BoxDynError> + fn add<'t, T>(&mut self, value: T) -> Result<(), BoxDynError> where - T: Encode<'q, Self::Database> + Type, + T: Encode<'t, Self::Database> + Type, { self.add(value) } diff --git a/sqlx-postgres/src/database.rs b/sqlx-postgres/src/database.rs index fbc762615b..77945b8cfe 100644 --- a/sqlx-postgres/src/database.rs +++ b/sqlx-postgres/src/database.rs @@ -27,8 +27,8 @@ impl Database for Postgres { type Value = PgValue; type ValueRef<'r> = PgValueRef<'r>; - type Arguments<'q> = PgArguments; - type ArgumentBuffer<'q> = PgArgumentBuffer; + type Arguments = PgArguments; + type ArgumentBuffer = PgArgumentBuffer; type Statement = PgStatement; diff --git a/sqlx-sqlite/src/arguments.rs b/sqlx-sqlite/src/arguments.rs index 6354cbebc9..4fd7da5067 100644 --- a/sqlx-sqlite/src/arguments.rs +++ b/sqlx-sqlite/src/arguments.rs @@ -28,10 +28,10 @@ pub struct SqliteArguments { #[derive(Default, Debug, Clone)] pub struct SqliteArgumentsBuffer(Vec); -impl<'q> SqliteArguments { - pub(crate) fn add(&mut self, value: T) -> Result<(), BoxDynError> +impl SqliteArguments { + pub(crate) fn add<'t, T>(&mut self, value: T) -> Result<(), BoxDynError> where - T: Encode<'q, Sqlite>, + T: Encode<'t, Sqlite>, { let value_length_before_encoding = self.values.0.len(); @@ -49,16 +49,16 @@ impl<'q> SqliteArguments { } } -impl<'q> Arguments<'q> for SqliteArguments { +impl Arguments for SqliteArguments { type Database = Sqlite; fn reserve(&mut self, len: usize, _size_hint: usize) { self.values.0.reserve(len); } - fn add(&mut self, value: T) -> Result<(), BoxDynError> + fn add<'t, T>(&mut self, value: T) -> Result<(), BoxDynError> where - T: Encode<'q, Self::Database>, + T: Encode<'t, Self::Database>, { self.add(value) } diff --git a/sqlx-sqlite/src/database.rs b/sqlx-sqlite/src/database.rs index 2e83880544..ca52d1cf6b 100644 --- a/sqlx-sqlite/src/database.rs +++ b/sqlx-sqlite/src/database.rs @@ -26,8 +26,8 @@ impl Database for Sqlite { type Value = SqliteValue; type ValueRef<'r> = SqliteValueRef<'r>; - type Arguments<'q> = SqliteArguments; - type ArgumentBuffer<'q> = SqliteArgumentsBuffer; + type Arguments = SqliteArguments; + type ArgumentBuffer = SqliteArgumentsBuffer; type Statement = SqliteStatement; diff --git a/sqlx-sqlite/src/types/str.rs b/sqlx-sqlite/src/types/str.rs index 3c620a9857..a28f778b63 100644 --- a/sqlx-sqlite/src/types/str.rs +++ b/sqlx-sqlite/src/types/str.rs @@ -85,10 +85,7 @@ impl Encode<'_, Sqlite> for Cow<'_, str> { } impl Encode<'_, Sqlite> for Arc { - fn encode( - self, - args: &mut ::ArgumentBuffer<'_>, - ) -> Result + fn encode(self, args: &mut ::ArgumentBuffer) -> Result where Self: Sized, { diff --git a/tests/mysql/types.rs b/tests/mysql/types.rs index 9686d41721..e8e37f06ed 100644 --- a/tests/mysql/types.rs +++ b/tests/mysql/types.rs @@ -8,7 +8,7 @@ use std::str::FromStr; use std::sync::Arc; use sqlx::mysql::MySql; -use sqlx::{Executor, FromRow, Row}; +use sqlx::{Executor, Row}; use sqlx::types::Text; diff --git a/tests/postgres/query_builder.rs b/tests/postgres/query_builder.rs index 5b73bcff35..60be9761d6 100644 --- a/tests/postgres/query_builder.rs +++ b/tests/postgres/query_builder.rs @@ -7,13 +7,13 @@ use sqlx_test::new; #[test] fn test_new() { - let qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users"); + let qb: QueryBuilder = QueryBuilder::new("SELECT * FROM users"); assert_eq!(qb.sql(), "SELECT * FROM users"); } #[test] fn test_push() { - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users"); + let mut qb: QueryBuilder = QueryBuilder::new("SELECT * FROM users"); let second_line = " WHERE last_name LIKE '[A-N]%';"; qb.push(second_line); @@ -26,7 +26,7 @@ fn test_push() { #[test] #[should_panic] fn test_push_panics_after_build_without_reset() { - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users;"); + let mut qb: QueryBuilder = QueryBuilder::new("SELECT * FROM users;"); let _query = qb.build(); @@ -35,7 +35,7 @@ fn test_push_panics_after_build_without_reset() { #[test] fn test_push_bind() { - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users WHERE id = "); + let mut qb: QueryBuilder = QueryBuilder::new("SELECT * FROM users WHERE id = "); qb.push_bind(42i32) .push(" OR membership_level = ") @@ -49,7 +49,7 @@ fn test_push_bind() { #[test] fn test_build() { - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users"); + let mut qb: QueryBuilder = QueryBuilder::new("SELECT * FROM users"); qb.push(" WHERE id = ").push_bind(42i32); let query = qb.build(); @@ -60,7 +60,7 @@ fn test_build() { #[test] fn test_reset() { - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new(""); + let mut qb: QueryBuilder = QueryBuilder::new(""); { let _query = qb @@ -76,7 +76,7 @@ fn test_reset() { #[test] fn test_query_builder_reuse() { - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new(""); + let mut qb: QueryBuilder = QueryBuilder::new(""); let _query = qb .push("SELECT * FROM users WHERE id = ") @@ -92,7 +92,7 @@ fn test_query_builder_reuse() { #[test] fn test_query_builder_with_args() { - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new(""); + let mut qb: QueryBuilder = QueryBuilder::new(""); let mut query = qb .push("SELECT * FROM users WHERE id = ") @@ -101,8 +101,7 @@ fn test_query_builder_with_args() { let args = query.take_arguments().unwrap().unwrap(); - let mut qb: QueryBuilder<'_, Postgres> = - QueryBuilder::with_arguments(query.sql().as_str(), args); + let mut qb: QueryBuilder = QueryBuilder::with_arguments(query.sql().as_str(), args); let query = qb.push(" OR membership_level = ").push_bind(3i32).build(); assert_eq!( @@ -118,7 +117,7 @@ async fn test_max_number_of_binds() -> anyhow::Result<()> { // // https://github.com/launchbadge/sqlx/issues/3464 - let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT ARRAY["); + let mut qb: QueryBuilder = QueryBuilder::new("SELECT ARRAY["); let mut elements = qb.separated(','); From 26f626f48f96f28f085f1d898af37379bdc89177 Mon Sep 17 00:00:00 2001 From: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Date: Thu, 21 Aug 2025 20:59:15 -0400 Subject: [PATCH 2/2] refactor(core): Also relax lifetime of argument passed to Query::bind and Query::try_bind Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> --- sqlx-core/src/query.rs | 6 ++-- sqlx-test/src/lib.rs | 8 +++-- tests/any/any.rs | 66 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/sqlx-core/src/query.rs b/sqlx-core/src/query.rs index 9d8f14e7bc..d549e3ca99 100644 --- a/sqlx-core/src/query.rs +++ b/sqlx-core/src/query.rs @@ -73,7 +73,7 @@ where } } -impl<'q, DB: Database> Query<'q, DB, ::Arguments> { +impl Query<'_, DB, ::Arguments> { /// Bind a value for use with this SQL query. /// /// 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, ::Arguments> { /// flavors will perform type coercion (Postgres will return a database error). /// /// If encoding the value fails, the error is stored and later surfaced when executing the query. - pub fn bind + Type>(mut self, value: T) -> Self { + pub fn bind<'t, T: Encode<'t, DB> + Type>(mut self, value: T) -> Self { let Ok(arguments) = self.get_arguments() else { return self; }; @@ -101,7 +101,7 @@ impl<'q, DB: Database> Query<'q, DB, ::Arguments> { } /// Like [`Query::bind`] but immediately returns an error if encoding a value failed. - pub fn try_bind + Type>( + pub fn try_bind<'t, T: Encode<'t, DB> + Type>( &mut self, value: T, ) -> Result<(), BoxDynError> { diff --git a/sqlx-test/src/lib.rs b/sqlx-test/src/lib.rs index 0aefbf626b..3744724c12 100644 --- a/sqlx-test/src/lib.rs +++ b/sqlx-test/src/lib.rs @@ -1,5 +1,5 @@ use sqlx::pool::PoolOptions; -use sqlx::{Connection, Database, Pool}; +use sqlx::{Connection, Database, Error, Pool}; use std::env; pub fn setup_if_needed() { @@ -9,13 +9,15 @@ pub fn setup_if_needed() { // Make a new connection // Ensure [dotenvy] and [env_logger] have been setup -pub async fn new() -> anyhow::Result +pub async fn new() -> sqlx::Result where DB: Database, { setup_if_needed(); - Ok(DB::Connection::connect(&env::var("DATABASE_URL")?).await?) + let db_url = env::var("DATABASE_URL").map_err(|e| Error::Configuration(Box::new(e)))?; + + Ok(DB::Connection::connect(&db_url).await?) } // Make a new pool diff --git a/tests/any/any.rs b/tests/any/any.rs index 62dc20403e..71c561cadb 100644 --- a/tests/any/any.rs +++ b/tests/any/any.rs @@ -1,6 +1,8 @@ -use sqlx::any::AnyRow; +use sqlx::any::{install_default_drivers, AnyRow}; use sqlx::{Any, Connection, Executor, Row}; +use sqlx_core::error::BoxDynError; use sqlx_core::sql_str::AssertSqlSafe; +use sqlx_core::Error; use sqlx_test::new; #[sqlx_macros::test] @@ -142,3 +144,65 @@ async fn it_can_fail_and_recover_with_pool() -> anyhow::Result<()> { Ok(()) } + +#[sqlx_macros::test] +async fn it_can_query_by_string_args() -> sqlx::Result<()> { + install_default_drivers(); + + let mut conn = new::().await?; + + let string = "Hello, world!".to_string(); + let ref tuple = ("Hello, world!".to_string(),); + + #[cfg(feature = "postgres")] + const SQL: &str = + "SELECT 'Hello, world!' as string where 'Hello, world!' in ($1, $2, $3, $4, $5, $6, $7)"; + + #[cfg(not(feature = "postgres"))] + const SQL: &str = + "SELECT 'Hello, world!' as string where 'Hello, world!' in (?, ?, ?, ?, ?, ?, ?)"; + + { + let query = sqlx::query(SQL) + // validate flexibility of lifetimes + .bind(&string) + .bind(&string[..]) + .bind(Some(&string)) + .bind(Some(&string[..])) + .bind(&Option::::None) + .bind(&string.clone()) + .bind(&tuple.0); // should not get "temporary value is freed at the end of this statement" here + + let result = query.fetch_one(&mut conn).await?; + + let column_0: String = result.try_get(0)?; + + assert_eq!(column_0, string); + } + + { + let mut query = sqlx::query(SQL); + + let query = || -> Result<_, BoxDynError> { + // validate flexibility of lifetimes + query.try_bind(&string)?; + query.try_bind(&string[..])?; + query.try_bind(Some(&string))?; + query.try_bind(Some(&string[..]))?; + query.try_bind(&Option::::None)?; + query.try_bind(&string.clone())?; + query.try_bind(&tuple.0)?; + + Ok(query) + }() + .map_err(Error::Encode)?; + + let result = query.fetch_one(&mut conn).await?; + + let column_0: String = result.try_get(0)?; + + assert_eq!(column_0, string); + } + + Ok(()) +}