Skip to content

refactor(any): Remove lifetime parameter from AnyArguments #3958

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
36 changes: 16 additions & 20 deletions sqlx-core/src/any/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -30,21 +32,13 @@ impl<'q> Arguments<'q> for AnyArguments<'q> {
}
}

pub struct AnyArgumentBuffer<'q>(#[doc(hidden)] pub Vec<AnyValueKind<'q>>);
#[derive(Default)]
pub struct AnyArgumentBuffer(#[doc(hidden)] pub Vec<AnyValueKind>);

impl Default for AnyArguments<'_> {
fn default() -> Self {
AnyArguments {
values: AnyArgumentBuffer(vec![]),
}
}
}

impl<'q> AnyArguments<'q> {
impl AnyArguments {
#[doc(hidden)]
pub fn convert_to<'a, A: Arguments<'a>>(&'a self) -> Result<A, BoxDynError>
pub fn convert_into<'a, A: Arguments<'a>>(self) -> Result<A, BoxDynError>
where
'q: 'a,
Option<i32>: Type<A::Database> + Encode<'a, A::Database>,
Option<bool>: Type<A::Database> + Encode<'a, A::Database>,
Option<i16>: Type<A::Database> + Encode<'a, A::Database>,
Expand All @@ -60,12 +54,13 @@ impl<'q> AnyArguments<'q> {
i64: Type<A::Database> + Encode<'a, A::Database>,
f32: Type<A::Database> + Encode<'a, A::Database>,
f64: Type<A::Database> + Encode<'a, A::Database>,
&'a str: Type<A::Database> + Encode<'a, A::Database>,
&'a [u8]: Type<A::Database> + Encode<'a, A::Database>,
Arc<String>: Type<A::Database> + Encode<'a, A::Database>,
Arc<str>: Type<A::Database> + Encode<'a, A::Database>,
Arc<Vec<u8>>: Type<A::Database> + 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::<i32>::None),
AnyValueKind::Null(AnyTypeInfoKind::Bool) => out.add(Option::<bool>::None),
Expand All @@ -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(&**t),
AnyValueKind::Blob(b) => out.add(&**b),
AnyValueKind::Text(t) => out.add(t),
AnyValueKind::TextSlice(t) => out.add(t),
AnyValueKind::Blob(b) => out.add(b),
}?
}
Ok(out)
Expand Down
16 changes: 8 additions & 8 deletions sqlx-core/src/any/connection/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AnyArguments<'q>>,
) -> BoxStream<'q, crate::Result<Either<AnyQueryResult, AnyRow>>>;
arguments: Option<AnyArguments>,
) -> BoxStream<'_, crate::Result<Either<AnyQueryResult, AnyRow>>>;

fn fetch_optional<'q>(
&'q mut self,
fn fetch_optional(
&mut self,
query: SqlStr,
persistent: bool,
arguments: Option<AnyArguments<'q>>,
) -> BoxFuture<'q, crate::Result<Option<AnyRow>>>;
arguments: Option<AnyArguments>,
) -> BoxFuture<'_, crate::Result<Option<AnyRow>>>;

fn prepare_with<'c, 'q: 'c>(
&'c mut self,
Expand Down
4 changes: 2 additions & 2 deletions sqlx-core/src/any/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions sqlx-core/src/any/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -71,7 +71,7 @@ where
{
fn encode_by_ref(
&self,
buf: &mut AnyArgumentBuffer<'q>,
buf: &mut AnyArgumentBuffer,
) -> Result<crate::encode::IsNull, crate::error::BoxDynError> {
if let Some(value) = self {
value.encode_by_ref(buf)
Expand Down
2 changes: 1 addition & 1 deletion sqlx-core/src/any/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Statement for AnyStatement {
&self.columns
}

impl_statement_query!(AnyArguments<'_>);
impl_statement_query!(AnyArguments);
}

impl ColumnIndex<AnyStatement> for &'_ str {
Expand Down
15 changes: 5 additions & 10 deletions sqlx-core/src/any/types/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Any> for [u8] {
fn type_info() -> AnyTypeInfo {
Expand All @@ -19,20 +19,15 @@ impl<'q> Encode<'q, Any> for &'q [u8] {
&self,
buf: &mut <Any as Database>::ArgumentBuffer<'q>,
) -> Result<IsNull, BoxDynError> {
buf.0.push(AnyValueKind::Blob((*self).into()));
buf.0.push(AnyValueKind::Blob(Arc::new(self.to_vec())));
Ok(IsNull::No)
}
}

impl<'r> Decode<'r, Any> for &'r [u8] {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
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<u8>` 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(),
}
}
Expand All @@ -49,15 +44,15 @@ impl<'q> Encode<'q, Any> for Vec<u8> {
&self,
buf: &mut <Any as Database>::ArgumentBuffer<'q>,
) -> Result<IsNull, BoxDynError> {
buf.0.push(AnyValueKind::Blob(Cow::Owned(self.clone())));
buf.0.push(AnyValueKind::Blob(Arc::new(self.clone())));
Ok(IsNull::No)
}
}

impl<'r> Decode<'r, Any> for Vec<u8> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
AnyValueKind::Blob(blob) => Ok(blob.into_owned()),
AnyValueKind::Blob(blob) => Ok(blob.as_ref().clone()),
other => other.unexpected(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion sqlx-core/src/any/types/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl<'q> Encode<'q, Any> for bool {
impl<'r> Decode<'r, Any> for bool {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
AnyValueKind::Bool(b) => Ok(b),
AnyValueKind::Bool(b) => Ok(*b),
other => other.unexpected(),
}
}
Expand Down
10 changes: 5 additions & 5 deletions sqlx-core/src/any/types/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ impl Type<Any> for f32 {
}
}

impl<'q> Encode<'q, Any> for f32 {
fn encode_by_ref(&self, buf: &mut AnyArgumentBuffer<'q>) -> Result<IsNull, BoxDynError> {
impl Encode<'_, Any> for f32 {
fn encode_by_ref(&self, buf: &mut AnyArgumentBuffer) -> Result<IsNull, BoxDynError> {
buf.0.push(AnyValueKind::Real(*self));
Ok(IsNull::No)
}
Expand All @@ -23,7 +23,7 @@ impl<'q> Encode<'q, Any> for f32 {
impl<'r> Decode<'r, Any> for f32 {
fn decode(value: AnyValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
AnyValueKind::Real(r) => Ok(r),
AnyValueKind::Real(r) => Ok(*r),
other => other.unexpected(),
}
}
Expand Down Expand Up @@ -51,8 +51,8 @@ impl<'r> Decode<'r, Any> for f64 {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
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(),
}
}
Expand Down
23 changes: 13 additions & 10 deletions sqlx-core/src/any/types/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Any> for str {
fn type_info() -> AnyTypeInfo {
Expand All @@ -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)
}

Expand All @@ -35,12 +35,7 @@ impl<'a> Encode<'a, Any> for &'a str {
impl<'a> Decode<'a, Any> for &'a str {
fn decode(value: <Any as Database>::ValueRef<'a>) -> Result<Self, BoxDynError> {
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(),
}
}
Expand All @@ -53,19 +48,27 @@ impl Type<Any> for String {
}

impl<'q> Encode<'q, Any> for String {
fn encode(
self,
buf: &mut <Any as Database>::ArgumentBuffer<'q>,
) -> Result<IsNull, BoxDynError> {
buf.0.push(AnyValueKind::Text(Arc::new(self)));
Ok(IsNull::No)
}

fn encode_by_ref(
&self,
buf: &mut <Any as Database>::ArgumentBuffer<'q>,
) -> Result<IsNull, BoxDynError> {
buf.0.push(AnyValueKind::Text(Cow::Owned(self.clone())));
buf.0.push(AnyValueKind::Text(Arc::new(self.clone())));
Ok(IsNull::No)
}
}

impl<'r> Decode<'r, Any> for String {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
AnyValueKind::Text(text) => Ok(text.into_owned()),
AnyValueKind::Text(text) => Ok(text.to_string()),
other => other.unexpected(),
}
}
Expand Down
44 changes: 12 additions & 32 deletions sqlx-core/src/any/value.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
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),
Integer(i32),
BigInt(i64),
Real(f32),
Double(f64),
Text(Cow<'a, str>),
Blob(Cow<'a, [u8]>),
Text(Arc<String>),
TextSlice(Arc<str>),
Blob(Arc<Vec<u8>>),
}

impl AnyValueKind<'_> {
impl AnyValueKind {
fn type_info(&self) -> AnyTypeInfo {
AnyTypeInfo {
kind: match self {
Expand All @@ -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,
},
}
Expand Down Expand Up @@ -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) -> <Self::Database as Database>::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<'_, <Self::Database as Database>::TypeInfo> {
Expand All @@ -101,17 +91,7 @@ impl<'a> ValueRef<'a> for AnyValueRef<'a> {

fn to_owned(&self) -> <Self::Database as Database>::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(),
}
}

Expand Down
Loading
Loading