From 6d79bd007a1bdebc7caff3043ac38c837e115dfa Mon Sep 17 00:00:00 2001 From: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Date: Fri, 1 Aug 2025 13:14:21 -0400 Subject: [PATCH 1/5] bug(sqlite): query macro argument lifetime use inconsistent with other db platforms Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> --- tests/sqlite/macros.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/sqlite/macros.rs b/tests/sqlite/macros.rs index 74e689260a..0ab4dd56bf 100644 --- a/tests/sqlite/macros.rs +++ b/tests/sqlite/macros.rs @@ -175,6 +175,31 @@ async fn test_query_scalar() -> anyhow::Result<()> { Ok(()) } +#[sqlx_macros::test] +async fn query_by_string() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let string = "Hello, world!".to_string(); + let ref tuple = ("Hello, world!".to_string(),); + + let result = sqlx::query!( + "SELECT 'Hello, world!' as string where 'Hello, world!' in (?, ?, ?, ?, ?, ?, ?)", + string, // make sure we don't actually take ownership here + &string[..], + Some(&string), + Some(&string[..]), + Option::::None, + string.clone(), + tuple.0 // make sure we're not trying to move out of a field expression + ) + .fetch_one(&mut conn) + .await?; + + assert_eq!(result.string, string); + + Ok(()) +} + #[sqlx_macros::test] async fn macro_select_from_view() -> anyhow::Result<()> { let mut conn = new::().await?; From c58e2b151894e879a5d268836408847a814d83e1 Mon Sep 17 00:00:00 2001 From: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Date: Fri, 1 Aug 2025 16:34:32 -0400 Subject: [PATCH 2/5] refactor(sqlite): Improve support for references as query macro bind arguments by removing lifetime parameter from SqliteArguments Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> --- sqlx-sqlite/src/any.rs | 7 ++- sqlx-sqlite/src/arguments.rs | 42 ++++-------------- sqlx-sqlite/src/connection/execute.rs | 14 +++--- sqlx-sqlite/src/connection/worker.rs | 6 +-- sqlx-sqlite/src/database.rs | 4 +- sqlx-sqlite/src/lib.rs | 2 +- sqlx-sqlite/src/statement/mod.rs | 2 +- sqlx-sqlite/src/types/bool.rs | 7 +-- sqlx-sqlite/src/types/bytes.rs | 62 +++++++++------------------ sqlx-sqlite/src/types/chrono.rs | 8 ++-- sqlx-sqlite/src/types/float.rs | 14 ++---- sqlx-sqlite/src/types/int.rs | 28 ++++-------- sqlx-sqlite/src/types/json.rs | 2 +- sqlx-sqlite/src/types/str.rs | 62 +++++++++------------------ sqlx-sqlite/src/types/text.rs | 4 +- sqlx-sqlite/src/types/time.rs | 8 ++-- sqlx-sqlite/src/types/uint.rs | 21 +++------ sqlx-sqlite/src/types/uuid.rs | 30 ++++--------- 18 files changed, 108 insertions(+), 215 deletions(-) diff --git a/sqlx-sqlite/src/any.rs b/sqlx-sqlite/src/any.rs index d33677c64e..e4768cf476 100644 --- a/sqlx-sqlite/src/any.rs +++ b/sqlx-sqlite/src/any.rs @@ -203,8 +203,7 @@ impl<'a> TryFrom<&'a AnyConnectOptions> for SqliteConnectOptions { } } -/// Instead of `AnyArguments::convert_into()`, we can do a direct mapping and preserve the lifetime. -fn map_arguments(args: AnyArguments<'_>) -> SqliteArguments<'_> { +fn map_arguments(args: AnyArguments<'_>) -> SqliteArguments { SqliteArguments { values: args .values @@ -218,8 +217,8 @@ fn map_arguments(args: AnyArguments<'_>) -> SqliteArguments<'_> { AnyValueKind::BigInt(i) => SqliteArgumentValue::Int64(i), AnyValueKind::Real(r) => SqliteArgumentValue::Double(r as f64), AnyValueKind::Double(d) => SqliteArgumentValue::Double(d), - AnyValueKind::Text(t) => SqliteArgumentValue::Text(t), - AnyValueKind::Blob(b) => SqliteArgumentValue::Blob(b), + AnyValueKind::Text(t) => SqliteArgumentValue::Text(t.to_string()), + AnyValueKind::Blob(b) => SqliteArgumentValue::Blob(b.to_vec()), // AnyValueKind is `#[non_exhaustive]` but we should have covered everything _ => unreachable!("BUG: missing mapping for {val:?}"), }) diff --git a/sqlx-sqlite/src/arguments.rs b/sqlx-sqlite/src/arguments.rs index 410b4caa99..21a166b4f4 100644 --- a/sqlx-sqlite/src/arguments.rs +++ b/sqlx-sqlite/src/arguments.rs @@ -4,27 +4,26 @@ use crate::statement::StatementHandle; use crate::Sqlite; use atoi::atoi; use libsqlite3_sys::SQLITE_OK; -use std::borrow::Cow; pub(crate) use sqlx_core::arguments::*; use sqlx_core::error::BoxDynError; #[derive(Debug, Clone)] -pub enum SqliteArgumentValue<'q> { +pub enum SqliteArgumentValue { Null, - Text(Cow<'q, str>), - Blob(Cow<'q, [u8]>), + Text(String), + Blob(Vec), Double(f64), Int(i32), Int64(i64), } #[derive(Default, Debug, Clone)] -pub struct SqliteArguments<'q> { - pub(crate) values: Vec>, +pub struct SqliteArguments { + pub(crate) values: Vec, } -impl<'q> SqliteArguments<'q> { +impl<'q> SqliteArguments { pub(crate) fn add(&mut self, value: T) -> Result<(), BoxDynError> where T: Encode<'q, Sqlite>, @@ -43,19 +42,9 @@ impl<'q> SqliteArguments<'q> { Ok(()) } - - pub(crate) fn into_static(self) -> SqliteArguments<'static> { - SqliteArguments { - values: self - .values - .into_iter() - .map(SqliteArgumentValue::into_static) - .collect(), - } - } } -impl<'q> Arguments<'q> for SqliteArguments<'q> { +impl<'q> Arguments<'q> for SqliteArguments { type Database = Sqlite; fn reserve(&mut self, len: usize, _size_hint: usize) { @@ -74,7 +63,7 @@ impl<'q> Arguments<'q> for SqliteArguments<'q> { } } -impl SqliteArguments<'_> { +impl SqliteArguments { pub(super) fn bind(&self, handle: &mut StatementHandle, offset: usize) -> Result { let mut arg_i = offset; // for handle in &statement.handles { @@ -120,20 +109,7 @@ impl SqliteArguments<'_> { } } -impl SqliteArgumentValue<'_> { - fn into_static(self) -> SqliteArgumentValue<'static> { - use SqliteArgumentValue::*; - - match self { - Null => Null, - Text(text) => Text(text.into_owned().into()), - Blob(blob) => Blob(blob.into_owned().into()), - Int(v) => Int(v), - Int64(v) => Int64(v), - Double(v) => Double(v), - } - } - +impl SqliteArgumentValue { fn bind(&self, handle: &mut StatementHandle, i: usize) -> Result<(), Error> { use SqliteArgumentValue::*; diff --git a/sqlx-sqlite/src/connection/execute.rs b/sqlx-sqlite/src/connection/execute.rs index 7acbc91ff8..733a1abbe6 100644 --- a/sqlx-sqlite/src/connection/execute.rs +++ b/sqlx-sqlite/src/connection/execute.rs @@ -10,7 +10,7 @@ pub struct ExecuteIter<'a> { handle: &'a mut ConnectionHandle, statement: &'a mut VirtualStatement, logger: QueryLogger, - args: Option>, + args: Option, /// since a `VirtualStatement` can encompass multiple actual statements, /// this keeps track of the number of arguments so far @@ -19,12 +19,12 @@ pub struct ExecuteIter<'a> { goto_next: bool, } -pub(crate) fn iter<'a>( - conn: &'a mut ConnectionState, +pub(crate) fn iter( + conn: &mut ConnectionState, query: impl SqlSafeStr, - args: Option>, + args: Option, persistent: bool, -) -> Result, Error> { +) -> Result, Error> { let query = query.into_sql_str(); // fetch the cached statement or allocate a new one let statement = conn.statements.get(query.as_str(), persistent)?; @@ -43,7 +43,7 @@ pub(crate) fn iter<'a>( fn bind( statement: &mut StatementHandle, - arguments: &Option>, + arguments: &Option, offset: usize, ) -> Result { let mut n = 0; @@ -56,7 +56,7 @@ fn bind( } impl ExecuteIter<'_> { - pub fn finish(&mut self) -> Result<(), Error> { + pub fn finish(self) -> Result<(), Error> { for res in self { let _ = res?; } diff --git a/sqlx-sqlite/src/connection/worker.rs b/sqlx-sqlite/src/connection/worker.rs index ae50f3e896..f1dbea3682 100644 --- a/sqlx-sqlite/src/connection/worker.rs +++ b/sqlx-sqlite/src/connection/worker.rs @@ -63,7 +63,7 @@ enum Command { }, Execute { query: SqlStr, - arguments: Option>, + arguments: Option, persistent: bool, tx: flume::Sender, Error>>, limit: Option, @@ -353,7 +353,7 @@ impl ConnectionWorker { pub(crate) async fn execute( &mut self, query: SqlStr, - args: Option>, + args: Option, chan_size: usize, persistent: bool, limit: Option, @@ -364,7 +364,7 @@ impl ConnectionWorker { .send_async(( Command::Execute { query, - arguments: args.map(SqliteArguments::into_static), + arguments: args, persistent, tx, limit, diff --git a/sqlx-sqlite/src/database.rs b/sqlx-sqlite/src/database.rs index d34d8eb8c3..1cc9641d28 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<'q>; - type ArgumentBuffer<'q> = Vec>; + type Arguments<'q> = SqliteArguments; + type ArgumentBuffer<'q> = Vec; type Statement = SqliteStatement; diff --git a/sqlx-sqlite/src/lib.rs b/sqlx-sqlite/src/lib.rs index 36d3ee7e69..4efe48e25d 100644 --- a/sqlx-sqlite/src/lib.rs +++ b/sqlx-sqlite/src/lib.rs @@ -147,7 +147,7 @@ impl<'c, T: Executor<'c, Database = Sqlite>> SqliteExecutor<'c> for T {} pub type SqliteTransaction<'c> = sqlx_core::transaction::Transaction<'c, Sqlite>; // NOTE: required due to the lack of lazy normalization -impl_into_arguments_for_arguments!(SqliteArguments<'q>); +impl_into_arguments_for_arguments!(SqliteArguments); impl_column_index_for_row!(SqliteRow); impl_column_index_for_statement!(SqliteStatement); impl_acquire!(Sqlite, SqliteConnection); diff --git a/sqlx-sqlite/src/statement/mod.rs b/sqlx-sqlite/src/statement/mod.rs index 407c567045..93f28b7dc4 100644 --- a/sqlx-sqlite/src/statement/mod.rs +++ b/sqlx-sqlite/src/statement/mod.rs @@ -45,7 +45,7 @@ impl Statement for SqliteStatement { &self.columns } - impl_statement_query!(SqliteArguments<'_>); + impl_statement_query!(SqliteArguments); } impl ColumnIndex for &'_ str { diff --git a/sqlx-sqlite/src/types/bool.rs b/sqlx-sqlite/src/types/bool.rs index a229298ff9..b210305ecb 100644 --- a/sqlx-sqlite/src/types/bool.rs +++ b/sqlx-sqlite/src/types/bool.rs @@ -15,11 +15,8 @@ impl Type for bool { } } -impl<'q> Encode<'q, Sqlite> for bool { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for bool { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int((*self).into())); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/bytes.rs b/sqlx-sqlite/src/types/bytes.rs index 2d67335a52..80fd331478 100644 --- a/sqlx-sqlite/src/types/bytes.rs +++ b/sqlx-sqlite/src/types/bytes.rs @@ -19,12 +19,9 @@ impl Type for [u8] { } } -impl<'q> Encode<'q, Sqlite> for &'q [u8] { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Blob(Cow::Borrowed(self))); +impl Encode<'_, Sqlite> for &'_ [u8] { + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self.to_vec())); Ok(IsNull::No) } @@ -37,19 +34,14 @@ impl<'r> Decode<'r, Sqlite> for &'r [u8] { } impl Encode<'_, Sqlite> for Box<[u8]> { - fn encode(self, args: &mut Vec>) -> Result { - args.push(SqliteArgumentValue::Blob(Cow::Owned(self.into_vec()))); + fn encode(self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self.into_vec())); Ok(IsNull::No) } - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Blob(Cow::Owned( - self.clone().into_vec(), - ))); + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self.clone().into_vec())); Ok(IsNull::No) } @@ -65,18 +57,15 @@ impl Type for Vec { } } -impl<'q> Encode<'q, Sqlite> for Vec { - fn encode(self, args: &mut Vec>) -> Result { - args.push(SqliteArgumentValue::Blob(Cow::Owned(self))); +impl Encode<'_, Sqlite> for Vec { + fn encode(self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self)); Ok(IsNull::No) } - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Blob(Cow::Owned(self.clone()))); + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self.clone())); Ok(IsNull::No) } @@ -88,37 +77,28 @@ impl<'r> Decode<'r, Sqlite> for Vec { } } -impl<'q> Encode<'q, Sqlite> for Cow<'q, [u8]> { - fn encode(self, args: &mut Vec>) -> Result { - args.push(SqliteArgumentValue::Blob(self)); +impl Encode<'_, Sqlite> for Cow<'_, [u8]> { + fn encode(self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self.to_vec())); Ok(IsNull::No) } - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Blob(self.clone())); + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self.to_vec())); Ok(IsNull::No) } } -impl<'q> Encode<'q, Sqlite> for Arc<[u8]> { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for Arc<[u8]> { + fn encode_by_ref(&self, args: &mut Vec) -> Result { as Encode<'_, Sqlite>>::encode(self.to_vec(), args) } } -impl<'q> Encode<'q, Sqlite> for Rc<[u8]> { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for Rc<[u8]> { + fn encode_by_ref(&self, args: &mut Vec) -> Result { as Encode<'_, Sqlite>>::encode(self.to_vec(), args) } } diff --git a/sqlx-sqlite/src/types/chrono.rs b/sqlx-sqlite/src/types/chrono.rs index 5c4a41caff..51e21c0fac 100644 --- a/sqlx-sqlite/src/types/chrono.rs +++ b/sqlx-sqlite/src/types/chrono.rs @@ -65,25 +65,25 @@ impl Encode<'_, Sqlite> for DateTime where Tz::Offset: Display, { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { Encode::::encode(self.to_rfc3339_opts(SecondsFormat::AutoSi, false), buf) } } impl Encode<'_, Sqlite> for NaiveDateTime { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { Encode::::encode(self.format("%F %T%.f").to_string(), buf) } } impl Encode<'_, Sqlite> for NaiveDate { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { Encode::::encode(self.format("%F").to_string(), buf) } } impl Encode<'_, Sqlite> for NaiveTime { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { Encode::::encode(self.format("%T%.f").to_string(), buf) } } diff --git a/sqlx-sqlite/src/types/float.rs b/sqlx-sqlite/src/types/float.rs index c6e105d783..b06a86b4d1 100644 --- a/sqlx-sqlite/src/types/float.rs +++ b/sqlx-sqlite/src/types/float.rs @@ -11,11 +11,8 @@ impl Type for f32 { } } -impl<'q> Encode<'q, Sqlite> for f32 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for f32 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Double((*self).into())); Ok(IsNull::No) @@ -36,11 +33,8 @@ impl Type for f64 { } } -impl<'q> Encode<'q, Sqlite> for f64 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for f64 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Double(*self)); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/int.rs b/sqlx-sqlite/src/types/int.rs index e87025e2fb..4fcd44a4c0 100644 --- a/sqlx-sqlite/src/types/int.rs +++ b/sqlx-sqlite/src/types/int.rs @@ -15,11 +15,8 @@ impl Type for i8 { } } -impl<'q> Encode<'q, Sqlite> for i8 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for i8 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -46,11 +43,8 @@ impl Type for i16 { } } -impl<'q> Encode<'q, Sqlite> for i16 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for i16 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -73,11 +67,8 @@ impl Type for i32 { } } -impl<'q> Encode<'q, Sqlite> for i32 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for i32 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int(*self)); Ok(IsNull::No) @@ -100,11 +91,8 @@ impl Type for i64 { } } -impl<'q> Encode<'q, Sqlite> for i64 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for i64 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int64(*self)); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/json.rs b/sqlx-sqlite/src/types/json.rs index b8b665c4d3..a08d45675d 100644 --- a/sqlx-sqlite/src/types/json.rs +++ b/sqlx-sqlite/src/types/json.rs @@ -20,7 +20,7 @@ impl Encode<'_, Sqlite> for Json where T: Serialize, { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { Encode::::encode(self.encode_to_string()?, buf) } } diff --git a/sqlx-sqlite/src/types/str.rs b/sqlx-sqlite/src/types/str.rs index 5392f6401a..f0bcfe6bc6 100644 --- a/sqlx-sqlite/src/types/str.rs +++ b/sqlx-sqlite/src/types/str.rs @@ -15,12 +15,9 @@ impl Type for str { } } -impl<'q> Encode<'q, Sqlite> for &'q str { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Text(Cow::Borrowed(*self))); +impl Encode<'_, Sqlite> for &'_ str { + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) } @@ -33,19 +30,14 @@ impl<'r> Decode<'r, Sqlite> for &'r str { } impl Encode<'_, Sqlite> for Box { - fn encode(self, args: &mut Vec>) -> Result { - args.push(SqliteArgumentValue::Text(Cow::Owned(self.into_string()))); + fn encode(self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.into_string())); Ok(IsNull::No) } - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Text(Cow::Owned( - self.clone().into_string(), - ))); + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) } @@ -57,18 +49,15 @@ impl Type for String { } } -impl<'q> Encode<'q, Sqlite> for String { - fn encode(self, args: &mut Vec>) -> Result { - args.push(SqliteArgumentValue::Text(Cow::Owned(self))); +impl Encode<'_, Sqlite> for String { + fn encode(self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self)); Ok(IsNull::No) } - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Text(Cow::Owned(self.clone()))); + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.clone())); Ok(IsNull::No) } @@ -80,37 +69,28 @@ impl<'r> Decode<'r, Sqlite> for String { } } -impl<'q> Encode<'q, Sqlite> for Cow<'q, str> { - fn encode(self, args: &mut Vec>) -> Result { - args.push(SqliteArgumentValue::Text(self)); +impl Encode<'_, Sqlite> for Cow<'_, str> { + fn encode(self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.into())); Ok(IsNull::No) } - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Text(self.clone())); + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) } } -impl<'q> Encode<'q, Sqlite> for Arc { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for Arc { + fn encode_by_ref(&self, args: &mut Vec) -> Result { >::encode(self.to_string(), args) } } -impl<'q> Encode<'q, Sqlite> for Rc { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for Rc { + fn encode_by_ref(&self, args: &mut Vec) -> Result { >::encode(self.to_string(), args) } } diff --git a/sqlx-sqlite/src/types/text.rs b/sqlx-sqlite/src/types/text.rs index 80aab0d4ba..b3459531f4 100644 --- a/sqlx-sqlite/src/types/text.rs +++ b/sqlx-sqlite/src/types/text.rs @@ -16,11 +16,11 @@ impl Type for Text { } } -impl<'q, T> Encode<'q, Sqlite> for Text +impl Encode<'_, Sqlite> for Text where T: Display, { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { Encode::::encode(self.0.to_string(), buf) } } diff --git a/sqlx-sqlite/src/types/time.rs b/sqlx-sqlite/src/types/time.rs index c7ad3b3d05..3a8ab62bfb 100644 --- a/sqlx-sqlite/src/types/time.rs +++ b/sqlx-sqlite/src/types/time.rs @@ -55,27 +55,27 @@ impl Type for Time { } impl Encode<'_, Sqlite> for OffsetDateTime { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { Encode::::encode(self.format(&Rfc3339)?, buf) } } impl Encode<'_, Sqlite> for PrimitiveDateTime { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { let format = fd!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]"); Encode::::encode(self.format(&format)?, buf) } } impl Encode<'_, Sqlite> for Date { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { let format = fd!("[year]-[month]-[day]"); Encode::::encode(self.format(&format)?, buf) } } impl Encode<'_, Sqlite> for Time { - fn encode_by_ref(&self, buf: &mut Vec>) -> Result { + fn encode_by_ref(&self, buf: &mut Vec) -> Result { let format = fd!("[hour]:[minute]:[second].[subsecond]"); Encode::::encode(self.format(&format)?, buf) } diff --git a/sqlx-sqlite/src/types/uint.rs b/sqlx-sqlite/src/types/uint.rs index f3d7da8c2f..42ba323e3e 100644 --- a/sqlx-sqlite/src/types/uint.rs +++ b/sqlx-sqlite/src/types/uint.rs @@ -15,11 +15,8 @@ impl Type for u8 { } } -impl<'q> Encode<'q, Sqlite> for u8 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for u8 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -46,11 +43,8 @@ impl Type for u16 { } } -impl<'q> Encode<'q, Sqlite> for u16 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for u16 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -73,11 +67,8 @@ impl Type for u32 { } } -impl<'q> Encode<'q, Sqlite> for u32 { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { +impl Encode<'_, Sqlite> for u32 { + fn encode_by_ref(&self, args: &mut Vec) -> Result { args.push(SqliteArgumentValue::Int64(*self as i64)); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/uuid.rs b/sqlx-sqlite/src/types/uuid.rs index 99291be86e..d9de26ffbc 100644 --- a/sqlx-sqlite/src/types/uuid.rs +++ b/sqlx-sqlite/src/types/uuid.rs @@ -4,7 +4,6 @@ use crate::error::BoxDynError; use crate::type_info::DataType; use crate::types::Type; use crate::{Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef}; -use std::borrow::Cow; use uuid::{ fmt::{Hyphenated, Simple}, Uuid, @@ -20,14 +19,9 @@ impl Type for Uuid { } } -impl<'q> Encode<'q, Sqlite> for Uuid { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Blob(Cow::Owned( - self.as_bytes().to_vec(), - ))); +impl Encode<'_, Sqlite> for Uuid { + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Blob(self.as_bytes().to_vec())); Ok(IsNull::No) } @@ -46,12 +40,9 @@ impl Type for Hyphenated { } } -impl<'q> Encode<'q, Sqlite> for Hyphenated { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Text(Cow::Owned(self.to_string()))); +impl Encode<'_, Sqlite> for Hyphenated { + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) } @@ -72,12 +63,9 @@ impl Type for Simple { } } -impl<'q> Encode<'q, Sqlite> for Simple { - fn encode_by_ref( - &self, - args: &mut Vec>, - ) -> Result { - args.push(SqliteArgumentValue::Text(Cow::Owned(self.to_string()))); +impl Encode<'_, Sqlite> for Simple { + fn encode_by_ref(&self, args: &mut Vec) -> Result { + args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) } From dc523b2724a9d2045b37e2c2b820093d1efdf91f Mon Sep 17 00:00:00 2001 From: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Date: Fri, 1 Aug 2025 17:38:52 -0400 Subject: [PATCH 3/5] refactor(sqlite): Introduce SqliteArgumentsBuffer type Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> --- sqlx-sqlite/src/any.rs | 39 +++++++++++++++++--------------- sqlx-sqlite/src/arguments.rs | 30 +++++++++++++++++------- sqlx-sqlite/src/database.rs | 8 +++---- sqlx-sqlite/src/lib.rs | 2 +- sqlx-sqlite/src/statement/mod.rs | 17 -------------- sqlx-sqlite/src/types/bool.rs | 3 ++- sqlx-sqlite/src/types/bytes.rs | 19 ++++++++-------- sqlx-sqlite/src/types/chrono.rs | 10 ++++---- sqlx-sqlite/src/types/float.rs | 5 ++-- sqlx-sqlite/src/types/int.rs | 9 ++++---- sqlx-sqlite/src/types/json.rs | 5 ++-- sqlx-sqlite/src/types/str.rs | 19 ++++++++-------- sqlx-sqlite/src/types/text.rs | 5 ++-- sqlx-sqlite/src/types/time.rs | 11 +++++---- sqlx-sqlite/src/types/uint.rs | 7 +++--- sqlx-sqlite/src/types/uuid.rs | 7 +++--- 16 files changed, 103 insertions(+), 93 deletions(-) diff --git a/sqlx-sqlite/src/any.rs b/sqlx-sqlite/src/any.rs index e4768cf476..5564b9a677 100644 --- a/sqlx-sqlite/src/any.rs +++ b/sqlx-sqlite/src/any.rs @@ -12,6 +12,7 @@ use sqlx_core::any::{ }; use sqlx_core::sql_str::SqlStr; +use crate::arguments::SqliteArgumentsBuffer; use crate::type_info::DataType; use sqlx_core::connection::{ConnectOptions, Connection}; use sqlx_core::database::Database; @@ -204,25 +205,27 @@ impl<'a> TryFrom<&'a AnyConnectOptions> for SqliteConnectOptions { } fn map_arguments(args: AnyArguments<'_>) -> SqliteArguments { + let values = args + .values + .0 + .into_iter() + .map(|val| match val { + AnyValueKind::Null(_) => SqliteArgumentValue::Null, + AnyValueKind::Bool(b) => SqliteArgumentValue::Int(b as i32), + AnyValueKind::SmallInt(i) => SqliteArgumentValue::Int(i as i32), + AnyValueKind::Integer(i) => SqliteArgumentValue::Int(i), + AnyValueKind::BigInt(i) => SqliteArgumentValue::Int64(i), + AnyValueKind::Real(r) => SqliteArgumentValue::Double(r as f64), + AnyValueKind::Double(d) => SqliteArgumentValue::Double(d), + AnyValueKind::Text(t) => SqliteArgumentValue::Text(t.to_string()), + AnyValueKind::Blob(b) => SqliteArgumentValue::Blob(b.to_vec()), + // AnyValueKind is `#[non_exhaustive]` but we should have covered everything + _ => unreachable!("BUG: missing mapping for {val:?}"), + }) + .collect(); + SqliteArguments { - values: args - .values - .0 - .into_iter() - .map(|val| match val { - AnyValueKind::Null(_) => SqliteArgumentValue::Null, - AnyValueKind::Bool(b) => SqliteArgumentValue::Int(b as i32), - AnyValueKind::SmallInt(i) => SqliteArgumentValue::Int(i as i32), - AnyValueKind::Integer(i) => SqliteArgumentValue::Int(i), - AnyValueKind::BigInt(i) => SqliteArgumentValue::Int64(i), - AnyValueKind::Real(r) => SqliteArgumentValue::Double(r as f64), - AnyValueKind::Double(d) => SqliteArgumentValue::Double(d), - AnyValueKind::Text(t) => SqliteArgumentValue::Text(t.to_string()), - AnyValueKind::Blob(b) => SqliteArgumentValue::Blob(b.to_vec()), - // AnyValueKind is `#[non_exhaustive]` but we should have covered everything - _ => unreachable!("BUG: missing mapping for {val:?}"), - }) - .collect(), + values: SqliteArgumentsBuffer::new(values), } } diff --git a/sqlx-sqlite/src/arguments.rs b/sqlx-sqlite/src/arguments.rs index 21a166b4f4..3210ee7997 100644 --- a/sqlx-sqlite/src/arguments.rs +++ b/sqlx-sqlite/src/arguments.rs @@ -20,22 +20,25 @@ pub enum SqliteArgumentValue { #[derive(Default, Debug, Clone)] pub struct SqliteArguments { - pub(crate) values: Vec, + pub(crate) values: SqliteArgumentsBuffer, } +#[derive(Default, Debug, Clone)] +pub struct SqliteArgumentsBuffer(Vec); + impl<'q> SqliteArguments { pub(crate) fn add(&mut self, value: T) -> Result<(), BoxDynError> where T: Encode<'q, Sqlite>, { - let value_length_before_encoding = self.values.len(); + let value_length_before_encoding = self.values.0.len(); match value.encode(&mut self.values) { - Ok(IsNull::Yes) => self.values.push(SqliteArgumentValue::Null), + Ok(IsNull::Yes) => self.values.0.push(SqliteArgumentValue::Null), Ok(IsNull::No) => {} Err(error) => { // reset the value buffer to its previous value if encoding failed so we don't leave a half-encoded value behind - self.values.truncate(value_length_before_encoding); + self.values.0.truncate(value_length_before_encoding); return Err(error); } }; @@ -48,7 +51,7 @@ impl<'q> Arguments<'q> for SqliteArguments { type Database = Sqlite; fn reserve(&mut self, len: usize, _size_hint: usize) { - self.values.reserve(len); + self.values.0.reserve(len); } fn add(&mut self, value: T) -> Result<(), BoxDynError> @@ -59,7 +62,7 @@ impl<'q> Arguments<'q> for SqliteArguments { } fn len(&self) -> usize { - self.values.len() + self.values.0.len() } } @@ -92,7 +95,7 @@ impl SqliteArguments { arg_i }; - if n > self.values.len() { + if n > self.values.0.len() { // SQLite treats unbound variables as NULL // we reproduce this here // If you are reading this and think this should be an error, open an issue and we can @@ -102,13 +105,24 @@ impl SqliteArguments { break; } - self.values[n - 1].bind(handle, param_i)?; + self.values.0[n - 1].bind(handle, param_i)?; } Ok(arg_i - offset) } } +impl SqliteArgumentsBuffer { + #[allow(dead_code)] // clippy incorrectly reports this as unused + pub(crate) fn new(values: Vec) -> SqliteArgumentsBuffer { + Self(values) + } + + pub(crate) fn push(&mut self, value: SqliteArgumentValue) { + self.0.push(value); + } +} + impl SqliteArgumentValue { fn bind(&self, handle: &mut StatementHandle, i: usize) -> Result<(), Error> { use SqliteArgumentValue::*; diff --git a/sqlx-sqlite/src/database.rs b/sqlx-sqlite/src/database.rs index 1cc9641d28..2e83880544 100644 --- a/sqlx-sqlite/src/database.rs +++ b/sqlx-sqlite/src/database.rs @@ -1,9 +1,9 @@ pub(crate) use sqlx_core::database::{Database, HasStatementCache}; +use crate::arguments::SqliteArgumentsBuffer; use crate::{ - SqliteArgumentValue, SqliteArguments, SqliteColumn, SqliteConnection, SqliteQueryResult, - SqliteRow, SqliteStatement, SqliteTransactionManager, SqliteTypeInfo, SqliteValue, - SqliteValueRef, + SqliteArguments, SqliteColumn, SqliteConnection, SqliteQueryResult, SqliteRow, SqliteStatement, + SqliteTransactionManager, SqliteTypeInfo, SqliteValue, SqliteValueRef, }; /// Sqlite database driver. @@ -27,7 +27,7 @@ impl Database for Sqlite { type ValueRef<'r> = SqliteValueRef<'r>; type Arguments<'q> = SqliteArguments; - type ArgumentBuffer<'q> = Vec; + type ArgumentBuffer<'q> = SqliteArgumentsBuffer; type Statement = SqliteStatement; diff --git a/sqlx-sqlite/src/lib.rs b/sqlx-sqlite/src/lib.rs index 4efe48e25d..17b4bed1ca 100644 --- a/sqlx-sqlite/src/lib.rs +++ b/sqlx-sqlite/src/lib.rs @@ -74,7 +74,7 @@ extern crate sqlx_core; use std::sync::atomic::AtomicBool; -pub use arguments::{SqliteArgumentValue, SqliteArguments}; +pub use arguments::{SqliteArgumentValue, SqliteArguments, SqliteArgumentsBuffer}; pub use column::SqliteColumn; #[cfg(feature = "deserialize")] #[cfg_attr(docsrs, doc(cfg(feature = "deserialize")))] diff --git a/sqlx-sqlite/src/statement/mod.rs b/sqlx-sqlite/src/statement/mod.rs index 93f28b7dc4..93485397d3 100644 --- a/sqlx-sqlite/src/statement/mod.rs +++ b/sqlx-sqlite/src/statement/mod.rs @@ -57,20 +57,3 @@ impl ColumnIndex for &'_ str { .copied() } } - -// #[cfg(feature = "any")] -// impl<'q> From> for crate::any::AnyStatement<'q> { -// #[inline] -// fn from(statement: SqliteStatement<'q>) -> Self { -// crate::any::AnyStatement::<'q> { -// columns: statement -// .columns -// .iter() -// .map(|col| col.clone().into()) -// .collect(), -// column_names: statement.column_names, -// parameters: Some(Either::Right(statement.parameters)), -// sql: statement.sql, -// } -// } -// } diff --git a/sqlx-sqlite/src/types/bool.rs b/sqlx-sqlite/src/types/bool.rs index b210305ecb..9228eef236 100644 --- a/sqlx-sqlite/src/types/bool.rs +++ b/sqlx-sqlite/src/types/bool.rs @@ -1,3 +1,4 @@ +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -16,7 +17,7 @@ impl Type for bool { } impl Encode<'_, Sqlite> for bool { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int((*self).into())); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/bytes.rs b/sqlx-sqlite/src/types/bytes.rs index 80fd331478..c0ebc30221 100644 --- a/sqlx-sqlite/src/types/bytes.rs +++ b/sqlx-sqlite/src/types/bytes.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::rc::Rc; use std::sync::Arc; +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -20,7 +21,7 @@ impl Type for [u8] { } impl Encode<'_, Sqlite> for &'_ [u8] { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self.to_vec())); Ok(IsNull::No) @@ -34,13 +35,13 @@ impl<'r> Decode<'r, Sqlite> for &'r [u8] { } impl Encode<'_, Sqlite> for Box<[u8]> { - fn encode(self, args: &mut Vec) -> Result { + fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self.into_vec())); Ok(IsNull::No) } - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self.clone().into_vec())); Ok(IsNull::No) @@ -58,13 +59,13 @@ impl Type for Vec { } impl Encode<'_, Sqlite> for Vec { - fn encode(self, args: &mut Vec) -> Result { + fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self)); Ok(IsNull::No) } - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self.clone())); Ok(IsNull::No) @@ -78,13 +79,13 @@ impl<'r> Decode<'r, Sqlite> for Vec { } impl Encode<'_, Sqlite> for Cow<'_, [u8]> { - fn encode(self, args: &mut Vec) -> Result { + fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self.to_vec())); Ok(IsNull::No) } - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self.to_vec())); Ok(IsNull::No) @@ -92,13 +93,13 @@ impl Encode<'_, Sqlite> for Cow<'_, [u8]> { } impl Encode<'_, Sqlite> for Arc<[u8]> { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { as Encode<'_, Sqlite>>::encode(self.to_vec(), args) } } impl Encode<'_, Sqlite> for Rc<[u8]> { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { as Encode<'_, Sqlite>>::encode(self.to_vec(), args) } } diff --git a/sqlx-sqlite/src/types/chrono.rs b/sqlx-sqlite/src/types/chrono.rs index 51e21c0fac..8d987538d0 100644 --- a/sqlx-sqlite/src/types/chrono.rs +++ b/sqlx-sqlite/src/types/chrono.rs @@ -7,7 +7,7 @@ use crate::{ error::BoxDynError, type_info::DataType, types::Type, - Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef, + Sqlite, SqliteArgumentsBuffer, SqliteTypeInfo, SqliteValueRef, }; use chrono::FixedOffset; use chrono::{ @@ -65,25 +65,25 @@ impl Encode<'_, Sqlite> for DateTime where Tz::Offset: Display, { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { Encode::::encode(self.to_rfc3339_opts(SecondsFormat::AutoSi, false), buf) } } impl Encode<'_, Sqlite> for NaiveDateTime { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { Encode::::encode(self.format("%F %T%.f").to_string(), buf) } } impl Encode<'_, Sqlite> for NaiveDate { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { Encode::::encode(self.format("%F").to_string(), buf) } } impl Encode<'_, Sqlite> for NaiveTime { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { Encode::::encode(self.format("%T%.f").to_string(), buf) } } diff --git a/sqlx-sqlite/src/types/float.rs b/sqlx-sqlite/src/types/float.rs index b06a86b4d1..d23b3f3a08 100644 --- a/sqlx-sqlite/src/types/float.rs +++ b/sqlx-sqlite/src/types/float.rs @@ -1,3 +1,4 @@ +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -12,7 +13,7 @@ impl Type for f32 { } impl Encode<'_, Sqlite> for f32 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Double((*self).into())); Ok(IsNull::No) @@ -34,7 +35,7 @@ impl Type for f64 { } impl Encode<'_, Sqlite> for f64 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Double(*self)); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/int.rs b/sqlx-sqlite/src/types/int.rs index 4fcd44a4c0..2cf4209ad6 100644 --- a/sqlx-sqlite/src/types/int.rs +++ b/sqlx-sqlite/src/types/int.rs @@ -1,3 +1,4 @@ +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -16,7 +17,7 @@ impl Type for i8 { } impl Encode<'_, Sqlite> for i8 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -44,7 +45,7 @@ impl Type for i16 { } impl Encode<'_, Sqlite> for i16 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -68,7 +69,7 @@ impl Type for i32 { } impl Encode<'_, Sqlite> for i32 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int(*self)); Ok(IsNull::No) @@ -92,7 +93,7 @@ impl Type for i64 { } impl Encode<'_, Sqlite> for i64 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int64(*self)); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/json.rs b/sqlx-sqlite/src/types/json.rs index a08d45675d..dafd483658 100644 --- a/sqlx-sqlite/src/types/json.rs +++ b/sqlx-sqlite/src/types/json.rs @@ -1,10 +1,11 @@ use serde::{Deserialize, Serialize}; +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::types::{Json, Type}; -use crate::{type_info::DataType, Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef}; +use crate::{type_info::DataType, Sqlite, SqliteTypeInfo, SqliteValueRef}; impl Type for Json { fn type_info() -> SqliteTypeInfo { @@ -20,7 +21,7 @@ impl Encode<'_, Sqlite> for Json where T: Serialize, { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { Encode::::encode(self.encode_to_string()?, buf) } } diff --git a/sqlx-sqlite/src/types/str.rs b/sqlx-sqlite/src/types/str.rs index f0bcfe6bc6..b2a62f730a 100644 --- a/sqlx-sqlite/src/types/str.rs +++ b/sqlx-sqlite/src/types/str.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::rc::Rc; use std::sync::Arc; +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -16,7 +17,7 @@ impl Type for str { } impl Encode<'_, Sqlite> for &'_ str { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) @@ -30,13 +31,13 @@ impl<'r> Decode<'r, Sqlite> for &'r str { } impl Encode<'_, Sqlite> for Box { - fn encode(self, args: &mut Vec) -> Result { + fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.into_string())); Ok(IsNull::No) } - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) @@ -50,13 +51,13 @@ impl Type for String { } impl Encode<'_, Sqlite> for String { - fn encode(self, args: &mut Vec) -> Result { + fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self)); Ok(IsNull::No) } - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.clone())); Ok(IsNull::No) @@ -70,13 +71,13 @@ impl<'r> Decode<'r, Sqlite> for String { } impl Encode<'_, Sqlite> for Cow<'_, str> { - fn encode(self, args: &mut Vec) -> Result { + fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.into())); Ok(IsNull::No) } - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) @@ -84,13 +85,13 @@ impl Encode<'_, Sqlite> for Cow<'_, str> { } impl Encode<'_, Sqlite> for Arc { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { >::encode(self.to_string(), args) } } impl Encode<'_, Sqlite> for Rc { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { >::encode(self.to_string(), args) } } diff --git a/sqlx-sqlite/src/types/text.rs b/sqlx-sqlite/src/types/text.rs index b3459531f4..ef03caf5a0 100644 --- a/sqlx-sqlite/src/types/text.rs +++ b/sqlx-sqlite/src/types/text.rs @@ -1,4 +1,5 @@ -use crate::{Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef}; +use crate::arguments::SqliteArgumentsBuffer; +use crate::{Sqlite, SqliteTypeInfo, SqliteValueRef}; use sqlx_core::decode::Decode; use sqlx_core::encode::{Encode, IsNull}; use sqlx_core::error::BoxDynError; @@ -20,7 +21,7 @@ impl Encode<'_, Sqlite> for Text where T: Display, { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { Encode::::encode(self.0.to_string(), buf) } } diff --git a/sqlx-sqlite/src/types/time.rs b/sqlx-sqlite/src/types/time.rs index 3a8ab62bfb..0e0027882d 100644 --- a/sqlx-sqlite/src/types/time.rs +++ b/sqlx-sqlite/src/types/time.rs @@ -1,3 +1,4 @@ +use crate::arguments::SqliteArgumentsBuffer; use crate::value::ValueRef; use crate::{ decode::Decode, @@ -5,7 +6,7 @@ use crate::{ error::BoxDynError, type_info::DataType, types::Type, - Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef, + Sqlite, SqliteTypeInfo, SqliteValueRef, }; use time::format_description::{well_known::Rfc3339, BorrowedFormatItem}; use time::macros::format_description as fd; @@ -55,27 +56,27 @@ impl Type for Time { } impl Encode<'_, Sqlite> for OffsetDateTime { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { Encode::::encode(self.format(&Rfc3339)?, buf) } } impl Encode<'_, Sqlite> for PrimitiveDateTime { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { let format = fd!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]"); Encode::::encode(self.format(&format)?, buf) } } impl Encode<'_, Sqlite> for Date { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { let format = fd!("[year]-[month]-[day]"); Encode::::encode(self.format(&format)?, buf) } } impl Encode<'_, Sqlite> for Time { - fn encode_by_ref(&self, buf: &mut Vec) -> Result { + fn encode_by_ref(&self, buf: &mut SqliteArgumentsBuffer) -> Result { let format = fd!("[hour]:[minute]:[second].[subsecond]"); Encode::::encode(self.format(&format)?, buf) } diff --git a/sqlx-sqlite/src/types/uint.rs b/sqlx-sqlite/src/types/uint.rs index 42ba323e3e..1e8b1c5392 100644 --- a/sqlx-sqlite/src/types/uint.rs +++ b/sqlx-sqlite/src/types/uint.rs @@ -1,3 +1,4 @@ +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -16,7 +17,7 @@ impl Type for u8 { } impl Encode<'_, Sqlite> for u8 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -44,7 +45,7 @@ impl Type for u16 { } impl Encode<'_, Sqlite> for u16 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int(*self as i32)); Ok(IsNull::No) @@ -68,7 +69,7 @@ impl Type for u32 { } impl Encode<'_, Sqlite> for u32 { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Int64(*self as i64)); Ok(IsNull::No) diff --git a/sqlx-sqlite/src/types/uuid.rs b/sqlx-sqlite/src/types/uuid.rs index d9de26ffbc..13b784bbab 100644 --- a/sqlx-sqlite/src/types/uuid.rs +++ b/sqlx-sqlite/src/types/uuid.rs @@ -1,3 +1,4 @@ +use crate::arguments::SqliteArgumentsBuffer; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -20,7 +21,7 @@ impl Type for Uuid { } impl Encode<'_, Sqlite> for Uuid { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Blob(self.as_bytes().to_vec())); Ok(IsNull::No) @@ -41,7 +42,7 @@ impl Type for Hyphenated { } impl Encode<'_, Sqlite> for Hyphenated { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) @@ -64,7 +65,7 @@ impl Type for Simple { } impl Encode<'_, Sqlite> for Simple { - fn encode_by_ref(&self, args: &mut Vec) -> Result { + fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { args.push(SqliteArgumentValue::Text(self.to_string())); Ok(IsNull::No) From 81ca2ccb15d8bc9196ef321da9043b71185b149a Mon Sep 17 00:00:00 2001 From: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:07:16 -0400 Subject: [PATCH 4/5] refactor(sqlite): Improve cloning of SqliteArgumentValue, SqliteArguments, and SqliteArgumentsBuffer Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> --- sqlx-sqlite/src/any.rs | 5 +++-- sqlx-sqlite/src/arguments.rs | 7 +++++-- sqlx-sqlite/src/types/bytes.rs | 14 +++++++------- sqlx-sqlite/src/types/str.rs | 14 +++++++------- sqlx-sqlite/src/types/uuid.rs | 9 ++++++--- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/sqlx-sqlite/src/any.rs b/sqlx-sqlite/src/any.rs index 5564b9a677..c4bf2e5306 100644 --- a/sqlx-sqlite/src/any.rs +++ b/sqlx-sqlite/src/any.rs @@ -20,6 +20,7 @@ use sqlx_core::describe::Describe; use sqlx_core::executor::Executor; use sqlx_core::transaction::TransactionManager; use std::pin::pin; +use std::sync::Arc; sqlx_core::declare_driver_with_optional_migrate!(DRIVER = Sqlite); @@ -217,8 +218,8 @@ fn map_arguments(args: AnyArguments<'_>) -> SqliteArguments { AnyValueKind::BigInt(i) => SqliteArgumentValue::Int64(i), AnyValueKind::Real(r) => SqliteArgumentValue::Double(r as f64), AnyValueKind::Double(d) => SqliteArgumentValue::Double(d), - AnyValueKind::Text(t) => SqliteArgumentValue::Text(t.to_string()), - AnyValueKind::Blob(b) => SqliteArgumentValue::Blob(b.to_vec()), + AnyValueKind::Text(t) => SqliteArgumentValue::Text(Arc::new(t.to_string())), + AnyValueKind::Blob(b) => SqliteArgumentValue::Blob(Arc::new(b.to_vec())), // AnyValueKind is `#[non_exhaustive]` but we should have covered everything _ => unreachable!("BUG: missing mapping for {val:?}"), }) diff --git a/sqlx-sqlite/src/arguments.rs b/sqlx-sqlite/src/arguments.rs index 3210ee7997..6354cbebc9 100644 --- a/sqlx-sqlite/src/arguments.rs +++ b/sqlx-sqlite/src/arguments.rs @@ -4,6 +4,7 @@ use crate::statement::StatementHandle; use crate::Sqlite; use atoi::atoi; use libsqlite3_sys::SQLITE_OK; +use std::sync::Arc; pub(crate) use sqlx_core::arguments::*; use sqlx_core::error::BoxDynError; @@ -11,8 +12,9 @@ use sqlx_core::error::BoxDynError; #[derive(Debug, Clone)] pub enum SqliteArgumentValue { Null, - Text(String), - Blob(Vec), + Text(Arc), + TextSlice(Arc), + Blob(Arc>), Double(f64), Int(i32), Int64(i64), @@ -129,6 +131,7 @@ impl SqliteArgumentValue { let status = match self { Text(v) => handle.bind_text(i, v), + TextSlice(v) => handle.bind_text(i, v), Blob(v) => handle.bind_blob(i, v), Int(v) => handle.bind_int(i, *v), Int64(v) => handle.bind_int64(i, *v), diff --git a/sqlx-sqlite/src/types/bytes.rs b/sqlx-sqlite/src/types/bytes.rs index c0ebc30221..6453007bc9 100644 --- a/sqlx-sqlite/src/types/bytes.rs +++ b/sqlx-sqlite/src/types/bytes.rs @@ -22,7 +22,7 @@ impl Type for [u8] { impl Encode<'_, Sqlite> for &'_ [u8] { fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self.to_vec())); + args.push(SqliteArgumentValue::Blob(Arc::new(self.to_vec()))); Ok(IsNull::No) } @@ -36,13 +36,13 @@ impl<'r> Decode<'r, Sqlite> for &'r [u8] { impl Encode<'_, Sqlite> for Box<[u8]> { fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self.into_vec())); + args.push(SqliteArgumentValue::Blob(Arc::new(self.into_vec()))); Ok(IsNull::No) } fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self.clone().into_vec())); + args.push(SqliteArgumentValue::Blob(Arc::new(self.clone().into_vec()))); Ok(IsNull::No) } @@ -60,13 +60,13 @@ impl Type for Vec { impl Encode<'_, Sqlite> for Vec { fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self)); + args.push(SqliteArgumentValue::Blob(Arc::new(self))); Ok(IsNull::No) } fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self.clone())); + args.push(SqliteArgumentValue::Blob(Arc::new(self.clone()))); Ok(IsNull::No) } @@ -80,13 +80,13 @@ impl<'r> Decode<'r, Sqlite> for Vec { impl Encode<'_, Sqlite> for Cow<'_, [u8]> { fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self.to_vec())); + args.push(SqliteArgumentValue::Blob(Arc::new(self.into()))); Ok(IsNull::No) } fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self.to_vec())); + args.push(SqliteArgumentValue::Blob(Arc::new(self.to_vec()))); Ok(IsNull::No) } diff --git a/sqlx-sqlite/src/types/str.rs b/sqlx-sqlite/src/types/str.rs index b2a62f730a..c90f9bba55 100644 --- a/sqlx-sqlite/src/types/str.rs +++ b/sqlx-sqlite/src/types/str.rs @@ -18,7 +18,7 @@ impl Type for str { impl Encode<'_, Sqlite> for &'_ str { fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.to_string())); + args.push(SqliteArgumentValue::Text(Arc::new(self.to_string()))); Ok(IsNull::No) } @@ -32,13 +32,13 @@ impl<'r> Decode<'r, Sqlite> for &'r str { impl Encode<'_, Sqlite> for Box { fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.into_string())); + args.push(SqliteArgumentValue::Text(Arc::new(String::from(self)))); Ok(IsNull::No) } fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.to_string())); + args.push(SqliteArgumentValue::Text(Arc::new(self.to_string()))); Ok(IsNull::No) } @@ -52,13 +52,13 @@ impl Type for String { impl Encode<'_, Sqlite> for String { fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self)); + args.push(SqliteArgumentValue::Text(Arc::new(self))); Ok(IsNull::No) } fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.clone())); + args.push(SqliteArgumentValue::Text(Arc::new(self.clone()))); Ok(IsNull::No) } @@ -72,13 +72,13 @@ impl<'r> Decode<'r, Sqlite> for String { impl Encode<'_, Sqlite> for Cow<'_, str> { fn encode(self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.into())); + args.push(SqliteArgumentValue::Text(Arc::new(self.into()))); Ok(IsNull::No) } fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.to_string())); + args.push(SqliteArgumentValue::Text(Arc::new(self.to_string()))); Ok(IsNull::No) } diff --git a/sqlx-sqlite/src/types/uuid.rs b/sqlx-sqlite/src/types/uuid.rs index 13b784bbab..718ca5fb5d 100644 --- a/sqlx-sqlite/src/types/uuid.rs +++ b/sqlx-sqlite/src/types/uuid.rs @@ -5,6 +5,7 @@ use crate::error::BoxDynError; use crate::type_info::DataType; use crate::types::Type; use crate::{Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef}; +use std::sync::Arc; use uuid::{ fmt::{Hyphenated, Simple}, Uuid, @@ -22,7 +23,9 @@ impl Type for Uuid { impl Encode<'_, Sqlite> for Uuid { fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Blob(self.as_bytes().to_vec())); + args.push(SqliteArgumentValue::Blob(Arc::new( + self.as_bytes().to_vec(), + ))); Ok(IsNull::No) } @@ -43,7 +46,7 @@ impl Type for Hyphenated { impl Encode<'_, Sqlite> for Hyphenated { fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.to_string())); + args.push(SqliteArgumentValue::Text(Arc::new(self.to_string()))); Ok(IsNull::No) } @@ -66,7 +69,7 @@ impl Type for Simple { impl Encode<'_, Sqlite> for Simple { fn encode_by_ref(&self, args: &mut SqliteArgumentsBuffer) -> Result { - args.push(SqliteArgumentValue::Text(self.to_string())); + args.push(SqliteArgumentValue::Text(Arc::new(self.to_string()))); Ok(IsNull::No) } From 73ea968629e6f11d418f2b49e237f3725773f0b1 Mon Sep 17 00:00:00 2001 From: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:28:19 -0400 Subject: [PATCH 5/5] refactor(any): Change AnyArguments::convert_to to convert_into Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com> --- sqlx-core/src/any/arguments.rs | 12 ++++++------ sqlx-mysql/src/any.rs | 5 ++--- sqlx-postgres/src/any.rs | 5 ++--- sqlx-sqlite/src/any.rs | 1 + 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sqlx-core/src/any/arguments.rs b/sqlx-core/src/any/arguments.rs index 2c05e3fd5b..5a617c1419 100644 --- a/sqlx-core/src/any/arguments.rs +++ b/sqlx-core/src/any/arguments.rs @@ -42,7 +42,7 @@ impl Default for AnyArguments<'_> { impl<'q> AnyArguments<'q> { #[doc(hidden)] - pub fn convert_to<'a, A: Arguments<'a>>(&'a self) -> Result + pub fn convert_into<'a, A: Arguments<'a>>(self) -> Result where 'q: 'a, Option: Type + Encode<'a, A::Database>, @@ -60,12 +60,12 @@ impl<'q> AnyArguments<'q> { i64: Type + Encode<'a, A::Database>, f32: Type + Encode<'a, A::Database>, f64: Type + Encode<'a, A::Database>, - &'a str: Type + Encode<'a, A::Database>, - &'a [u8]: Type + Encode<'a, A::Database>, + String: Type + Encode<'a, A::Database>, + Vec: Type + Encode<'a, A::Database>, { let mut out = A::default(); - for arg in &self.values.0 { + for arg in self.values.0 { match arg { AnyValueKind::Null(AnyTypeInfoKind::Null) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::Bool) => out.add(Option::::None), @@ -82,8 +82,8 @@ impl<'q> AnyArguments<'q> { AnyValueKind::BigInt(i) => out.add(i), AnyValueKind::Real(r) => out.add(r), AnyValueKind::Double(d) => out.add(d), - AnyValueKind::Text(t) => out.add(&**t), - AnyValueKind::Blob(b) => out.add(&**b), + AnyValueKind::Text(t) => out.add(String::from(t)), + AnyValueKind::Blob(b) => out.add(Vec::from(b)), }? } Ok(out) diff --git a/sqlx-mysql/src/any.rs b/sqlx-mysql/src/any.rs index 028b6c55b8..70b7ad4511 100644 --- a/sqlx-mysql/src/any.rs +++ b/sqlx-mysql/src/any.rs @@ -84,7 +84,7 @@ impl AnyConnectionBackend for MySqlConnection { arguments: Option>, ) -> BoxStream<'q, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); - let arguments = match arguments.as_ref().map(AnyArguments::convert_to).transpose() { + let arguments = match arguments.map(AnyArguments::convert_into).transpose() { Ok(arguments) => arguments, Err(error) => { return stream::once(future::ready(Err(sqlx_core::Error::Encode(error)))).boxed() @@ -111,8 +111,7 @@ impl AnyConnectionBackend for MySqlConnection { ) -> BoxFuture<'q, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); let arguments = arguments - .as_ref() - .map(AnyArguments::convert_to) + .map(AnyArguments::convert_into) .transpose() .map_err(sqlx_core::Error::Encode); diff --git a/sqlx-postgres/src/any.rs b/sqlx-postgres/src/any.rs index 75ee0d73df..d24145637c 100644 --- a/sqlx-postgres/src/any.rs +++ b/sqlx-postgres/src/any.rs @@ -86,7 +86,7 @@ impl AnyConnectionBackend for PgConnection { arguments: Option>, ) -> BoxStream<'q, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); - let arguments = match arguments.as_ref().map(AnyArguments::convert_to).transpose() { + let arguments = match arguments.map(AnyArguments::convert_into).transpose() { Ok(arguments) => arguments, Err(error) => { return stream::once(future::ready(Err(sqlx_core::Error::Encode(error)))).boxed() @@ -113,8 +113,7 @@ impl AnyConnectionBackend for PgConnection { ) -> BoxFuture<'q, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); let arguments = arguments - .as_ref() - .map(AnyArguments::convert_to) + .map(AnyArguments::convert_into) .transpose() .map_err(sqlx_core::Error::Encode); diff --git a/sqlx-sqlite/src/any.rs b/sqlx-sqlite/src/any.rs index c4bf2e5306..636f986bf5 100644 --- a/sqlx-sqlite/src/any.rs +++ b/sqlx-sqlite/src/any.rs @@ -205,6 +205,7 @@ impl<'a> TryFrom<&'a AnyConnectOptions> for SqliteConnectOptions { } } +// Infallible alternative to AnyArguments::convert_into() fn map_arguments(args: AnyArguments<'_>) -> SqliteArguments { let values = args .values