Skip to content

Commit

Permalink
Generic Associated Types in Database, replacing HasValueRef, HasArgum…
Browse files Browse the repository at this point in the history
…ents, HasStatement (#2973)

* HasValueRef, HasArguments, HasStatement -> Database GATs

replace the associated types from the generic traits
`HasValueRef<'r>`, `HasArguments<'q>` and `HasStatement<'q>`
with generic associated types in `Database`

* fixup after rebase

---------

Co-authored-by: Austin Bonander <austin.bonander@gmail.com>
  • Loading branch information
nitn3lav and abonander authored Mar 14, 2024
1 parent 936744d commit 9ba488c
Show file tree
Hide file tree
Showing 33 changed files with 171 additions and 282 deletions.
27 changes: 7 additions & 20 deletions sqlx-core/src/any/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::any::{
AnyArgumentBuffer, AnyArguments, AnyColumn, AnyConnection, AnyQueryResult, AnyRow,
AnyStatement, AnyTransactionManager, AnyTypeInfo, AnyValue, AnyValueRef,
};
use crate::database::{Database, HasArguments, HasStatement, HasStatementCache, HasValueRef};
use crate::database::{Database, HasStatementCache};

/// Opaque database driver. Capable of being used in place of any SQLx database driver. The actual
/// driver used will be selected at runtime, from the connection url.
Expand All @@ -23,29 +23,16 @@ impl Database for Any {
type TypeInfo = AnyTypeInfo;

type Value = AnyValue;
const NAME: &'static str = "Any";

const URL_SCHEMES: &'static [&'static str] = &[];
}

impl<'r> HasValueRef<'r> for Any {
type Database = Any;
type ValueRef<'r> = AnyValueRef<'r>;

type ValueRef = AnyValueRef<'r>;
}
type Arguments<'q> = AnyArguments<'q>;
type ArgumentBuffer<'q> = AnyArgumentBuffer<'q>;

impl<'q> HasStatement<'q> for Any {
type Database = Any;
type Statement<'q> = AnyStatement<'q>;

type Statement = AnyStatement<'q>;
}

impl<'q> HasArguments<'q> for Any {
type Database = Any;

type Arguments = AnyArguments<'q>;
const NAME: &'static str = "Any";

type ArgumentBuffer = AnyArgumentBuffer<'q>;
const URL_SCHEMES: &'static [&'static str] = &[];
}

// This _may_ be true, depending on the selected database
Expand Down
9 changes: 3 additions & 6 deletions sqlx-core/src/any/row.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::any::error::mismatched_types;
use crate::any::{Any, AnyColumn, AnyTypeInfo, AnyTypeInfoKind, AnyValue, AnyValueKind};
use crate::column::{Column, ColumnIndex};
use crate::database::{Database, HasValueRef};
use crate::database::Database;
use crate::decode::Decode;
use crate::error::Error;
use crate::ext::ustr::UStr;
Expand All @@ -28,10 +28,7 @@ impl Row for AnyRow {
&self.columns
}

fn try_get_raw<I>(
&self,
index: I,
) -> Result<<Self::Database as HasValueRef<'_>>::ValueRef, Error>
fn try_get_raw<I>(&self, index: I) -> Result<<Self::Database as Database>::ValueRef<'_>, Error>
where
I: ColumnIndex<Self>,
{
Expand Down Expand Up @@ -141,7 +138,7 @@ impl AnyRow {
}

fn decode<'r, DB: Database, T: Decode<'r, DB>>(
valueref: <DB as HasValueRef<'r>>::ValueRef,
valueref: <DB as Database>::ValueRef<'r>,
) -> crate::Result<T> {
Decode::decode(valueref).map_err(Error::decode)
}
10 changes: 5 additions & 5 deletions sqlx-core/src/any/types/blob.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind, AnyValueKind};
use crate::database::{HasArguments, HasValueRef};
use crate::database::Database;
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
Expand All @@ -15,14 +15,14 @@ impl Type<Any> for [u8] {
}

impl<'q> Encode<'q, Any> for &'q [u8] {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::Blob((*self).into()));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for &'r [u8] {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
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`
Expand All @@ -42,14 +42,14 @@ impl Type<Any> for Vec<u8> {
}

impl<'q> Encode<'q, Any> for Vec<u8> {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::Blob(Cow::Owned(self.clone())));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for Vec<u8> {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
AnyValueKind::Blob(blob) => Ok(blob.into_owned()),
other => other.unexpected(),
Expand Down
6 changes: 3 additions & 3 deletions sqlx-core/src/any/types/bool.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind, AnyValueKind};
use crate::database::{HasArguments, HasValueRef};
use crate::database::Database;
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
Expand All @@ -14,14 +14,14 @@ impl Type<Any> for bool {
}

impl<'q> Encode<'q, Any> for bool {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::Bool(*self));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for bool {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
AnyValueKind::Bool(b) => Ok(b),
other => other.unexpected(),
Expand Down
6 changes: 3 additions & 3 deletions sqlx-core/src/any/types/float.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::any::{Any, AnyArgumentBuffer, AnyTypeInfo, AnyTypeInfoKind, AnyValueKind, AnyValueRef};
use crate::database::{HasArguments, HasValueRef};
use crate::database::Database;
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
Expand Down Expand Up @@ -38,14 +38,14 @@ impl Type<Any> for f64 {
}

impl<'q> Encode<'q, Any> for f64 {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::Double(*self));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for f64 {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
// Widening is safe
AnyValueKind::Real(r) => Ok(r as f64),
Expand Down
14 changes: 7 additions & 7 deletions sqlx-core/src/any/types/int.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind, AnyValueKind};
use crate::database::{HasArguments, HasValueRef};
use crate::database::Database;
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
Expand All @@ -18,14 +18,14 @@ impl Type<Any> for i16 {
}

impl<'q> Encode<'q, Any> for i16 {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::SmallInt(*self));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for i16 {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
value.kind.try_integer()
}
}
Expand All @@ -43,14 +43,14 @@ impl Type<Any> for i32 {
}

impl<'q> Encode<'q, Any> for i32 {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::Integer(*self));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for i32 {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
value.kind.try_integer()
}
}
Expand All @@ -68,14 +68,14 @@ impl Type<Any> for i64 {
}

impl<'q> Encode<'q, Any> for i64 {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::BigInt(*self));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for i64 {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
value.kind.try_integer()
}
}
12 changes: 6 additions & 6 deletions sqlx-core/src/any/types/str.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::any::types::str;
use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind, AnyValueKind};
use crate::database::{HasArguments, HasValueRef};
use crate::database::Database;
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
Expand All @@ -16,21 +16,21 @@ impl Type<Any> for str {
}

impl<'a> Encode<'a, Any> for &'a str {
fn encode(self, buf: &mut <Any as HasArguments<'a>>::ArgumentBuffer) -> IsNull
fn encode(self, buf: &mut <Any as Database>::ArgumentBuffer<'a>) -> IsNull
where
Self: Sized,
{
buf.0.push(AnyValueKind::Text(self.into()));
IsNull::No
}

fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'a>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'a>) -> IsNull {
(*self).encode(buf)
}
}

impl<'a> Decode<'a, Any> for &'a str {
fn decode(value: <Any as HasValueRef<'a>>::ValueRef) -> Result<Self, BoxDynError> {
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`
Expand All @@ -50,14 +50,14 @@ impl Type<Any> for String {
}

impl<'q> Encode<'q, Any> for String {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
fn encode_by_ref(&self, buf: &mut <Any as Database>::ArgumentBuffer<'q>) -> IsNull {
buf.0.push(AnyValueKind::Text(Cow::Owned(self.clone())));
IsNull::No
}
}

impl<'r> Decode<'r, Any> for String {
fn decode(value: <Any as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
fn decode(value: <Any as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
match value.kind {
AnyValueKind::Text(text) => Ok(text.into_owned()),
other => other.unexpected(),
Expand Down
4 changes: 2 additions & 2 deletions sqlx-core/src/any/value.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::borrow::Cow;

use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind};
use crate::database::{Database, HasValueRef};
use crate::database::Database;
use crate::error::BoxDynError;
use crate::types::Type;
use crate::value::{Value, ValueRef};
Expand Down Expand Up @@ -71,7 +71,7 @@ pub struct AnyValueRef<'a> {
impl Value for AnyValue {
type Database = Any;

fn as_ref(&self) -> <Self::Database as HasValueRef<'_>>::ValueRef {
fn as_ref(&self) -> <Self::Database as Database>::ValueRef<'_> {
AnyValueRef {
kind: match &self.kind {
AnyValueKind::Null => AnyValueKind::Null,
Expand Down
12 changes: 6 additions & 6 deletions sqlx-core/src/arguments.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Types and traits for passing arguments to SQL queries.
use crate::database::{Database, HasArguments};
use crate::database::Database;
use crate::encode::Encode;
use crate::types::Type;
use std::fmt::{self, Write};
Expand All @@ -23,8 +23,8 @@ pub trait Arguments<'q>: Send + Sized + Default {
}
}

pub trait IntoArguments<'q, DB: HasArguments<'q>>: Sized + Send {
fn into_arguments(self) -> <DB as HasArguments<'q>>::Arguments;
pub trait IntoArguments<'q, DB: Database>: Sized + Send {
fn into_arguments(self) -> <DB as Database>::Arguments<'q>;
}

// NOTE: required due to lack of lazy normalization
Expand All @@ -45,10 +45,10 @@ macro_rules! impl_into_arguments_for_arguments {
}

/// used by the query macros to prevent supernumerary `.bind()` calls
pub struct ImmutableArguments<'q, DB: HasArguments<'q>>(pub <DB as HasArguments<'q>>::Arguments);
pub struct ImmutableArguments<'q, DB: Database>(pub <DB as Database>::Arguments<'q>);

impl<'q, DB: HasArguments<'q>> IntoArguments<'q, DB> for ImmutableArguments<'q, DB> {
fn into_arguments(self) -> <DB as HasArguments<'q>>::Arguments {
impl<'q, DB: Database> IntoArguments<'q, DB> for ImmutableArguments<'q, DB> {
fn into_arguments(self) -> <DB as Database>::Arguments<'q> {
self.0
}
}
Expand Down
Loading

0 comments on commit 9ba488c

Please sign in to comment.