diff --git a/sqlx-core/src/any/arguments.rs b/sqlx-core/src/any/arguments.rs index 5a617c1419..28dadaa757 100644 --- a/sqlx-core/src/any/arguments.rs +++ b/sqlx-core/src/any/arguments.rs @@ -4,13 +4,15 @@ use crate::arguments::Arguments; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::types::Type; +use std::sync::Arc; -pub struct AnyArguments<'q> { +#[derive(Default)] +pub struct AnyArguments { #[doc(hidden)] - pub values: AnyArgumentBuffer<'q>, + pub values: AnyArgumentBuffer, } -impl<'q> Arguments<'q> for AnyArguments<'q> { +impl<'q> Arguments<'q> for AnyArguments { type Database = Any; fn reserve(&mut self, additional: usize, _size: usize) { @@ -30,21 +32,13 @@ impl<'q> Arguments<'q> for AnyArguments<'q> { } } -pub struct AnyArgumentBuffer<'q>(#[doc(hidden)] pub Vec>); +#[derive(Default)] +pub struct AnyArgumentBuffer(#[doc(hidden)] pub Vec); -impl Default for AnyArguments<'_> { - fn default() -> Self { - AnyArguments { - values: AnyArgumentBuffer(vec![]), - } - } -} - -impl<'q> AnyArguments<'q> { +impl AnyArguments { #[doc(hidden)] pub fn convert_into<'a, A: Arguments<'a>>(self) -> Result where - 'q: 'a, Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, @@ -60,8 +54,9 @@ impl<'q> AnyArguments<'q> { i64: Type + Encode<'a, A::Database>, f32: Type + Encode<'a, A::Database>, f64: Type + Encode<'a, A::Database>, - String: Type + Encode<'a, A::Database>, - Vec: Type + Encode<'a, A::Database>, + Arc: Type + Encode<'a, A::Database>, + Arc: Type + Encode<'a, A::Database>, + Arc>: Type + Encode<'a, A::Database>, { let mut out = A::default(); @@ -82,8 +77,9 @@ 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(String::from(t)), - AnyValueKind::Blob(b) => out.add(Vec::from(b)), + AnyValueKind::Text(t) => out.add(t), + AnyValueKind::TextSlice(t) => out.add(t), + AnyValueKind::Blob(b) => out.add(b), }? } Ok(out) diff --git a/sqlx-core/src/any/connection/backend.rs b/sqlx-core/src/any/connection/backend.rs index e59b345ed9..5b3ea7bf2d 100644 --- a/sqlx-core/src/any/connection/backend.rs +++ b/sqlx-core/src/any/connection/backend.rs @@ -94,19 +94,19 @@ pub trait AnyConnectionBackend: std::any::Any + Debug + Send + 'static { )) } - fn fetch_many<'q>( - &'q mut self, + fn fetch_many( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxStream<'q, crate::Result>>; + arguments: Option, + ) -> BoxStream<'_, crate::Result>>; - fn fetch_optional<'q>( - &'q mut self, + fn fetch_optional( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxFuture<'q, crate::Result>>; + arguments: Option, + ) -> BoxFuture<'_, crate::Result>>; fn prepare_with<'c, 'q: 'c>( &'c mut self, diff --git a/sqlx-core/src/any/database.rs b/sqlx-core/src/any/database.rs index 6e8343e928..6e7a5f5ea8 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<'q>; - type ArgumentBuffer<'q> = AnyArgumentBuffer<'q>; + type Arguments<'q> = AnyArguments; + type ArgumentBuffer<'q> = AnyArgumentBuffer; type Statement = AnyStatement; diff --git a/sqlx-core/src/any/mod.rs b/sqlx-core/src/any/mod.rs index 032f4dda03..9d37bbf5ab 100644 --- a/sqlx-core/src/any/mod.rs +++ b/sqlx-core/src/any/mod.rs @@ -56,7 +56,7 @@ pub trait AnyExecutor<'c>: Executor<'c, Database = Any> {} impl<'c, T: Executor<'c, Database = Any>> AnyExecutor<'c> for T {} // NOTE: required due to the lack of lazy normalization -impl_into_arguments_for_arguments!(AnyArguments<'q>); +impl_into_arguments_for_arguments!(AnyArguments); // impl_executor_for_pool_connection!(Any, AnyConnection, AnyRow); // impl_executor_for_transaction!(Any, AnyRow); impl_acquire!(Any, AnyConnection); @@ -71,7 +71,7 @@ where { fn encode_by_ref( &self, - buf: &mut AnyArgumentBuffer<'q>, + buf: &mut AnyArgumentBuffer, ) -> Result { if let Some(value) = self { value.encode_by_ref(buf) diff --git a/sqlx-core/src/any/statement.rs b/sqlx-core/src/any/statement.rs index 98b28c2c32..42c7255736 100644 --- a/sqlx-core/src/any/statement.rs +++ b/sqlx-core/src/any/statement.rs @@ -44,7 +44,7 @@ impl Statement for AnyStatement { &self.columns } - impl_statement_query!(AnyArguments<'_>); + impl_statement_query!(AnyArguments); } impl ColumnIndex for &'_ str { diff --git a/sqlx-core/src/any/types/blob.rs b/sqlx-core/src/any/types/blob.rs index 851c93bf5a..21379a6429 100644 --- a/sqlx-core/src/any/types/blob.rs +++ b/sqlx-core/src/any/types/blob.rs @@ -4,7 +4,7 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::types::Type; -use std::borrow::Cow; +use std::sync::Arc; impl Type for [u8] { fn type_info() -> AnyTypeInfo { @@ -19,7 +19,7 @@ impl<'q> Encode<'q, Any> for &'q [u8] { &self, buf: &mut ::ArgumentBuffer<'q>, ) -> Result { - buf.0.push(AnyValueKind::Blob((*self).into())); + buf.0.push(AnyValueKind::Blob(Arc::new(self.to_vec()))); Ok(IsNull::No) } } @@ -27,12 +27,7 @@ impl<'q> Encode<'q, Any> for &'q [u8] { impl<'r> Decode<'r, Any> for &'r [u8] { fn decode(value: ::ValueRef<'r>) -> Result { match value.kind { - AnyValueKind::Blob(Cow::Borrowed(blob)) => Ok(blob), - // This shouldn't happen in practice, it means the user got an `AnyValueRef` - // constructed from an owned `Vec` which shouldn't be allowed by the API. - AnyValueKind::Blob(Cow::Owned(_text)) => { - panic!("attempting to return a borrow that outlives its buffer") - } + AnyValueKind::Blob(blob) => Ok(blob.as_slice()), other => other.unexpected(), } } @@ -49,7 +44,7 @@ impl<'q> Encode<'q, Any> for Vec { &self, buf: &mut ::ArgumentBuffer<'q>, ) -> Result { - buf.0.push(AnyValueKind::Blob(Cow::Owned(self.clone()))); + buf.0.push(AnyValueKind::Blob(Arc::new(self.clone()))); Ok(IsNull::No) } } @@ -57,7 +52,7 @@ impl<'q> Encode<'q, Any> for Vec { impl<'r> Decode<'r, Any> for Vec { fn decode(value: ::ValueRef<'r>) -> Result { match value.kind { - AnyValueKind::Blob(blob) => Ok(blob.into_owned()), + AnyValueKind::Blob(blob) => Ok(blob.as_ref().clone()), other => other.unexpected(), } } diff --git a/sqlx-core/src/any/types/bool.rs b/sqlx-core/src/any/types/bool.rs index fb7ee9d5dd..ff915c5bfd 100644 --- a/sqlx-core/src/any/types/bool.rs +++ b/sqlx-core/src/any/types/bool.rs @@ -26,7 +26,7 @@ impl<'q> Encode<'q, Any> for bool { impl<'r> Decode<'r, Any> for bool { fn decode(value: ::ValueRef<'r>) -> Result { match value.kind { - AnyValueKind::Bool(b) => Ok(b), + AnyValueKind::Bool(b) => Ok(*b), other => other.unexpected(), } } diff --git a/sqlx-core/src/any/types/float.rs b/sqlx-core/src/any/types/float.rs index 01d6073a2f..36ee38a05f 100644 --- a/sqlx-core/src/any/types/float.rs +++ b/sqlx-core/src/any/types/float.rs @@ -13,8 +13,8 @@ impl Type for f32 { } } -impl<'q> Encode<'q, Any> for f32 { - fn encode_by_ref(&self, buf: &mut AnyArgumentBuffer<'q>) -> Result { +impl Encode<'_, Any> for f32 { + fn encode_by_ref(&self, buf: &mut AnyArgumentBuffer) -> Result { buf.0.push(AnyValueKind::Real(*self)); Ok(IsNull::No) } @@ -23,7 +23,7 @@ impl<'q> Encode<'q, Any> for f32 { impl<'r> Decode<'r, Any> for f32 { fn decode(value: AnyValueRef<'r>) -> Result { match value.kind { - AnyValueKind::Real(r) => Ok(r), + AnyValueKind::Real(r) => Ok(*r), other => other.unexpected(), } } @@ -51,8 +51,8 @@ impl<'r> Decode<'r, Any> for f64 { fn decode(value: ::ValueRef<'r>) -> Result { match value.kind { // Widening is safe - AnyValueKind::Real(r) => Ok(r as f64), - AnyValueKind::Double(d) => Ok(d), + AnyValueKind::Real(r) => Ok(*r as f64), + AnyValueKind::Double(d) => Ok(*d), other => other.unexpected(), } } diff --git a/sqlx-core/src/any/types/str.rs b/sqlx-core/src/any/types/str.rs index 4c00832690..3faf6a1708 100644 --- a/sqlx-core/src/any/types/str.rs +++ b/sqlx-core/src/any/types/str.rs @@ -5,7 +5,7 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::types::Type; -use std::borrow::Cow; +use std::sync::Arc; impl Type for str { fn type_info() -> AnyTypeInfo { @@ -20,7 +20,7 @@ impl<'a> Encode<'a, Any> for &'a str { where Self: Sized, { - buf.0.push(AnyValueKind::Text(self.into())); + buf.0.push(AnyValueKind::Text(Arc::new(self.into()))); Ok(IsNull::No) } @@ -35,12 +35,7 @@ impl<'a> Encode<'a, Any> for &'a str { impl<'a> Decode<'a, Any> for &'a str { fn decode(value: ::ValueRef<'a>) -> Result { match value.kind { - AnyValueKind::Text(Cow::Borrowed(text)) => Ok(text), - // This shouldn't happen in practice, it means the user got an `AnyValueRef` - // constructed from an owned `String` which shouldn't be allowed by the API. - AnyValueKind::Text(Cow::Owned(_text)) => { - panic!("attempting to return a borrow that outlives its buffer") - } + AnyValueKind::Text(text) => Ok(text.as_str()), other => other.unexpected(), } } @@ -53,11 +48,19 @@ impl Type for String { } impl<'q> Encode<'q, Any> for String { + fn encode( + self, + buf: &mut ::ArgumentBuffer<'q>, + ) -> Result { + buf.0.push(AnyValueKind::Text(Arc::new(self))); + Ok(IsNull::No) + } + fn encode_by_ref( &self, buf: &mut ::ArgumentBuffer<'q>, ) -> Result { - buf.0.push(AnyValueKind::Text(Cow::Owned(self.clone()))); + buf.0.push(AnyValueKind::Text(Arc::new(self.clone()))); Ok(IsNull::No) } } @@ -65,7 +68,7 @@ impl<'q> Encode<'q, Any> for String { impl<'r> Decode<'r, Any> for String { fn decode(value: ::ValueRef<'r>) -> Result { match value.kind { - AnyValueKind::Text(text) => Ok(text.into_owned()), + AnyValueKind::Text(text) => Ok(text.to_string()), other => other.unexpected(), } } diff --git a/sqlx-core/src/any/value.rs b/sqlx-core/src/any/value.rs index 9917b39f4f..a85c1dc69c 100644 --- a/sqlx-core/src/any/value.rs +++ b/sqlx-core/src/any/value.rs @@ -1,14 +1,14 @@ -use std::borrow::Cow; - use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind}; use crate::database::Database; use crate::error::BoxDynError; use crate::types::Type; use crate::value::{Value, ValueRef}; +use std::borrow::Cow; +use std::sync::Arc; #[derive(Clone, Debug)] #[non_exhaustive] -pub enum AnyValueKind<'a> { +pub enum AnyValueKind { Null(AnyTypeInfoKind), Bool(bool), SmallInt(i16), @@ -16,11 +16,12 @@ pub enum AnyValueKind<'a> { BigInt(i64), Real(f32), Double(f64), - Text(Cow<'a, str>), - Blob(Cow<'a, [u8]>), + Text(Arc), + TextSlice(Arc), + Blob(Arc>), } -impl AnyValueKind<'_> { +impl AnyValueKind { fn type_info(&self) -> AnyTypeInfo { AnyTypeInfo { kind: match self { @@ -32,6 +33,7 @@ impl AnyValueKind<'_> { AnyValueKind::Real(_) => AnyTypeInfoKind::Real, AnyValueKind::Double(_) => AnyTypeInfoKind::Double, AnyValueKind::Text(_) => AnyTypeInfoKind::Text, + AnyValueKind::TextSlice(_) => AnyTypeInfoKind::Text, AnyValueKind::Blob(_) => AnyTypeInfoKind::Blob, }, } @@ -60,31 +62,19 @@ impl AnyValueKind<'_> { #[derive(Clone, Debug)] pub struct AnyValue { #[doc(hidden)] - pub kind: AnyValueKind<'static>, + pub kind: AnyValueKind, } #[derive(Clone, Debug)] pub struct AnyValueRef<'a> { - pub(crate) kind: AnyValueKind<'a>, + pub(crate) kind: &'a AnyValueKind, } impl Value for AnyValue { type Database = Any; fn as_ref(&self) -> ::ValueRef<'_> { - AnyValueRef { - kind: match &self.kind { - AnyValueKind::Null(k) => AnyValueKind::Null(*k), - AnyValueKind::Bool(b) => AnyValueKind::Bool(*b), - AnyValueKind::SmallInt(i) => AnyValueKind::SmallInt(*i), - AnyValueKind::Integer(i) => AnyValueKind::Integer(*i), - AnyValueKind::BigInt(i) => AnyValueKind::BigInt(*i), - AnyValueKind::Real(r) => AnyValueKind::Real(*r), - AnyValueKind::Double(d) => AnyValueKind::Double(*d), - AnyValueKind::Text(t) => AnyValueKind::Text(Cow::Borrowed(t)), - AnyValueKind::Blob(b) => AnyValueKind::Blob(Cow::Borrowed(b)), - }, - } + AnyValueRef { kind: &self.kind } } fn type_info(&self) -> Cow<'_, ::TypeInfo> { @@ -101,17 +91,7 @@ impl<'a> ValueRef<'a> for AnyValueRef<'a> { fn to_owned(&self) -> ::Value { AnyValue { - kind: match &self.kind { - AnyValueKind::Null(k) => AnyValueKind::Null(*k), - AnyValueKind::Bool(b) => AnyValueKind::Bool(*b), - AnyValueKind::SmallInt(i) => AnyValueKind::SmallInt(*i), - AnyValueKind::Integer(i) => AnyValueKind::Integer(*i), - AnyValueKind::BigInt(i) => AnyValueKind::BigInt(*i), - AnyValueKind::Real(r) => AnyValueKind::Real(*r), - AnyValueKind::Double(d) => AnyValueKind::Double(*d), - AnyValueKind::Text(t) => AnyValueKind::Text(Cow::Owned(t.to_string())), - AnyValueKind::Blob(b) => AnyValueKind::Blob(Cow::Owned(b.to_vec())), - }, + kind: self.kind.clone(), } } diff --git a/sqlx-mysql/src/any.rs b/sqlx-mysql/src/any.rs index 70b7ad4511..241900560e 100644 --- a/sqlx-mysql/src/any.rs +++ b/sqlx-mysql/src/any.rs @@ -77,12 +77,12 @@ impl AnyConnectionBackend for MySqlConnection { Ok(self) } - fn fetch_many<'q>( - &'q mut self, + fn fetch_many( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxStream<'q, sqlx_core::Result>> { + arguments: Option, + ) -> BoxStream<'_, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); let arguments = match arguments.map(AnyArguments::convert_into).transpose() { Ok(arguments) => arguments, @@ -103,12 +103,12 @@ impl AnyConnectionBackend for MySqlConnection { ) } - fn fetch_optional<'q>( - &'q mut self, + fn fetch_optional( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxFuture<'q, sqlx_core::Result>> { + arguments: Option, + ) -> BoxFuture<'_, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); let arguments = arguments .map(AnyArguments::convert_into) diff --git a/sqlx-postgres/src/any.rs b/sqlx-postgres/src/any.rs index d24145637c..51eb15d2a7 100644 --- a/sqlx-postgres/src/any.rs +++ b/sqlx-postgres/src/any.rs @@ -79,12 +79,12 @@ impl AnyConnectionBackend for PgConnection { Ok(self) } - fn fetch_many<'q>( - &'q mut self, + fn fetch_many( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxStream<'q, sqlx_core::Result>> { + arguments: Option, + ) -> BoxStream>> { let persistent = persistent && arguments.is_some(); let arguments = match arguments.map(AnyArguments::convert_into).transpose() { Ok(arguments) => arguments, @@ -105,12 +105,12 @@ impl AnyConnectionBackend for PgConnection { ) } - fn fetch_optional<'q>( - &'q mut self, + fn fetch_optional( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxFuture<'q, sqlx_core::Result>> { + arguments: Option, + ) -> BoxFuture>> { let persistent = persistent && arguments.is_some(); let arguments = arguments .map(AnyArguments::convert_into) diff --git a/sqlx-sqlite/src/any.rs b/sqlx-sqlite/src/any.rs index 636f986bf5..83b141decd 100644 --- a/sqlx-sqlite/src/any.rs +++ b/sqlx-sqlite/src/any.rs @@ -80,12 +80,12 @@ impl AnyConnectionBackend for SqliteConnection { Ok(self) } - fn fetch_many<'q>( - &'q mut self, + fn fetch_many( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxStream<'q, sqlx_core::Result>> { + arguments: Option, + ) -> BoxStream<'_, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); let args = arguments.map(map_arguments); @@ -103,12 +103,12 @@ impl AnyConnectionBackend for SqliteConnection { ) } - fn fetch_optional<'q>( - &'q mut self, + fn fetch_optional( + &mut self, query: SqlStr, persistent: bool, - arguments: Option>, - ) -> BoxFuture<'q, sqlx_core::Result>> { + arguments: Option, + ) -> BoxFuture<'_, sqlx_core::Result>> { let persistent = persistent && arguments.is_some(); let args = arguments.map(map_arguments); @@ -206,7 +206,7 @@ impl<'a> TryFrom<&'a AnyConnectOptions> for SqliteConnectOptions { } // Infallible alternative to AnyArguments::convert_into() -fn map_arguments(args: AnyArguments<'_>) -> SqliteArguments { +fn map_arguments(args: AnyArguments) -> SqliteArguments { let values = args .values .0