mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-14 00:07:05 +00:00
Clean up SQL type (de)serialize
This commit is contained in:
parent
2d5170d742
commit
b33bc3c017
14 changed files with 173 additions and 211 deletions
|
@ -95,10 +95,10 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
fn fetch<'c, 'q, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend> + Send + Unpin,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(async_stream::try_stream! {
|
||||
let mut conn = self.get().await;
|
||||
|
@ -110,13 +110,13 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch_optional<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(
|
||||
fn fetch_optional<'c, 'q, T: 'c, Q: 'q + 'c>(
|
||||
&'c self,
|
||||
query: Q,
|
||||
) -> BoxFuture<'c, io::Result<Option<T>>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend>,
|
||||
T: FromRow<Self::Backend>,
|
||||
{
|
||||
Box::pin(async move {
|
||||
let mut conn = self.get().await;
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
use crate::{backend::Backend, types::HasSqlType};
|
||||
|
||||
// TODO: Allow from_sql to return an error (that can be unified)
|
||||
// TODO: Consider using a RawValue wrapper type inUead of exposing raw bytes (as different back-ends may want to expose different data here.. maybe?)
|
||||
|
||||
pub trait FromSql<A, DB: Backend> {
|
||||
pub trait FromSql<DB: Backend> {
|
||||
fn from_sql(raw: Option<&[u8]>) -> Self;
|
||||
}
|
||||
|
||||
impl<T, ST, DB> FromSql<ST, DB> for Option<T>
|
||||
impl<T, DB> FromSql<DB> for Option<T>
|
||||
where
|
||||
DB: Backend + HasSqlType<ST>,
|
||||
T: FromSql<ST, DB>,
|
||||
DB: Backend + HasSqlType<T>,
|
||||
T: FromSql<DB>,
|
||||
{
|
||||
#[inline]
|
||||
fn from_sql(raw: Option<&[u8]>) -> Self {
|
||||
|
|
|
@ -9,18 +9,18 @@ pub trait Executor: Send {
|
|||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>;
|
||||
|
||||
fn fetch<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
fn fetch<'c, 'q, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend> + Send + Unpin;
|
||||
T: FromRow<Self::Backend> + Send + Unpin;
|
||||
|
||||
fn fetch_optional<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(
|
||||
fn fetch_optional<'c, 'q, T: 'c, Q: 'q + 'c>(
|
||||
&'c self,
|
||||
query: Q,
|
||||
) -> BoxFuture<'c, io::Result<Option<T>>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend>;
|
||||
T: FromRow<Self::Backend>;
|
||||
}
|
||||
|
||||
impl<'e, E> Executor for &'e E
|
||||
|
@ -37,21 +37,21 @@ where
|
|||
(*self).execute(query)
|
||||
}
|
||||
|
||||
fn fetch<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
fn fetch<'c, 'q, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend> + Send + Unpin,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
(*self).fetch(query)
|
||||
}
|
||||
|
||||
fn fetch_optional<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(
|
||||
fn fetch_optional<'c, 'q, T: 'c, Q: 'q + 'c>(
|
||||
&'c self,
|
||||
query: Q,
|
||||
) -> BoxFuture<'c, io::Result<Option<T>>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend>,
|
||||
T: FromRow<Self::Backend>,
|
||||
{
|
||||
(*self).fetch_optional(query)
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@ impl BackendKeyData {
|
|||
|
||||
impl Decode for BackendKeyData {
|
||||
fn decode(src: &[u8]) -> Self {
|
||||
let process_id = u32::from_be_bytes(src[..4].try_into().unwrap());
|
||||
let secret_key = u32::from_be_bytes(src[4..].try_into().unwrap());
|
||||
debug_assert_eq!(src.len(), 8);
|
||||
|
||||
let process_id = u32::from_be_bytes(src[0..4].try_into().unwrap());
|
||||
let secret_key = u32::from_be_bytes(src[4..8].try_into().unwrap());
|
||||
|
||||
Self {
|
||||
process_id,
|
||||
|
|
|
@ -32,16 +32,16 @@ impl<'q> RawQuery<'q> for PgRawQuery<'q> {
|
|||
}
|
||||
}
|
||||
|
||||
fn bind_as<ST, T>(mut self, value: T) -> Self
|
||||
fn bind<T>(mut self, value: T) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
Self::Backend: HasSqlType<ST>,
|
||||
T: ToSql<ST, Self::Backend>,
|
||||
Self::Backend: HasSqlType<T>,
|
||||
T: ToSql<Self::Backend>,
|
||||
{
|
||||
// TODO: When/if we receive types that do _not_ support BINARY, we need to check here
|
||||
// TODO: There is no need to be explicit unless we are expecting mixed BINARY / TEXT
|
||||
|
||||
self.types.push(<Pg as HasSqlType<ST>>::metadata().oid);
|
||||
self.types.push(<Pg as HasSqlType<T>>::metadata().oid);
|
||||
|
||||
let pos = self.buf.len();
|
||||
self.buf.put_int_32(0);
|
||||
|
|
|
@ -2,12 +2,10 @@ use super::{Pg, PgTypeMetadata};
|
|||
use crate::{
|
||||
deserialize::FromSql,
|
||||
serialize::{IsNull, ToSql},
|
||||
types::{AsSqlType, HasSqlType},
|
||||
types::HasSqlType,
|
||||
};
|
||||
|
||||
pub struct Bool;
|
||||
|
||||
impl HasSqlType<Bool> for Pg {
|
||||
impl HasSqlType<bool> for Pg {
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
PgTypeMetadata {
|
||||
oid: 16,
|
||||
|
@ -16,11 +14,7 @@ impl HasSqlType<Bool> for Pg {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for bool {
|
||||
type SqlType = Bool;
|
||||
}
|
||||
|
||||
impl ToSql<Bool, Pg> for bool {
|
||||
impl ToSql<Pg> for bool {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
buf.push(self as u8);
|
||||
|
@ -29,10 +23,13 @@ impl ToSql<Bool, Pg> for bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromSql<Bool, Pg> for bool {
|
||||
impl FromSql<Pg> for bool {
|
||||
#[inline]
|
||||
fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
// TODO: Handle optionals
|
||||
buf.unwrap()[0] != 0
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: #[derive(SqlType)]
|
||||
// pub struct Bool(pub bool);
|
||||
|
|
|
@ -2,11 +2,12 @@ use super::{Pg, PgTypeMetadata};
|
|||
use crate::{
|
||||
deserialize::FromSql,
|
||||
serialize::{IsNull, ToSql},
|
||||
types::{AsSqlType, HasSqlType, Text},
|
||||
types::HasSqlType,
|
||||
};
|
||||
use std::str;
|
||||
|
||||
impl HasSqlType<Text> for Pg {
|
||||
impl HasSqlType<&'_ str> for Pg {
|
||||
#[inline]
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
PgTypeMetadata {
|
||||
oid: 25,
|
||||
|
@ -15,11 +16,14 @@ impl HasSqlType<Text> for Pg {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for &'_ str {
|
||||
type SqlType = Text;
|
||||
impl HasSqlType<String> for Pg {
|
||||
#[inline]
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
<Pg as HasSqlType<&str>>::metadata()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql<Text, Pg> for &'_ str {
|
||||
impl ToSql<Pg> for &'_ str {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
buf.extend_from_slice(self.as_bytes());
|
||||
|
@ -28,20 +32,14 @@ impl ToSql<Text, Pg> for &'_ str {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for String {
|
||||
type SqlType = Text;
|
||||
}
|
||||
|
||||
impl ToSql<Text, Pg> for String {
|
||||
impl ToSql<Pg> for String {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
buf.extend_from_slice(self.as_bytes());
|
||||
|
||||
IsNull::No
|
||||
self.as_str().to_sql(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql<Text, Pg> for String {
|
||||
impl FromSql<Pg> for String {
|
||||
#[inline]
|
||||
fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
// TODO: Handle nulls
|
||||
|
|
|
@ -5,8 +5,6 @@ mod boolean;
|
|||
mod character;
|
||||
mod numeric;
|
||||
|
||||
pub use self::boolean::Bool;
|
||||
|
||||
pub struct PgTypeMetadata {
|
||||
pub oid: u32,
|
||||
pub array_oid: u32,
|
||||
|
|
|
@ -2,11 +2,12 @@ use super::{Pg, PgTypeMetadata};
|
|||
use crate::{
|
||||
deserialize::FromSql,
|
||||
serialize::{IsNull, ToSql},
|
||||
types::{AsSqlType, BigInt, Double, HasSqlType, Int, Real, SmallInt},
|
||||
types::HasSqlType,
|
||||
};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
impl HasSqlType<SmallInt> for Pg {
|
||||
impl HasSqlType<i16> for Pg {
|
||||
#[inline]
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
PgTypeMetadata {
|
||||
oid: 21,
|
||||
|
@ -15,11 +16,7 @@ impl HasSqlType<SmallInt> for Pg {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for i16 {
|
||||
type SqlType = SmallInt;
|
||||
}
|
||||
|
||||
impl ToSql<SmallInt, Pg> for i16 {
|
||||
impl ToSql<Pg> for i16 {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
buf.extend_from_slice(&self.to_be_bytes());
|
||||
|
@ -28,15 +25,15 @@ impl ToSql<SmallInt, Pg> for i16 {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromSql<SmallInt, Pg> for i16 {
|
||||
impl FromSql<Pg> for i16 {
|
||||
#[inline]
|
||||
fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
// TODO: Handle optionals
|
||||
BigEndian::read_i16(buf.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSqlType<Int> for Pg {
|
||||
impl HasSqlType<i32> for Pg {
|
||||
#[inline]
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
PgTypeMetadata {
|
||||
oid: 23,
|
||||
|
@ -45,11 +42,7 @@ impl HasSqlType<Int> for Pg {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for i32 {
|
||||
type SqlType = Int;
|
||||
}
|
||||
|
||||
impl ToSql<Int, Pg> for i32 {
|
||||
impl ToSql<Pg> for i32 {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
buf.extend_from_slice(&self.to_be_bytes());
|
||||
|
@ -58,15 +51,15 @@ impl ToSql<Int, Pg> for i32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromSql<Int, Pg> for i32 {
|
||||
impl FromSql<Pg> for i32 {
|
||||
#[inline]
|
||||
fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
// TODO: Handle optionals
|
||||
BigEndian::read_i32(buf.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSqlType<BigInt> for Pg {
|
||||
impl HasSqlType<i64> for Pg {
|
||||
#[inline]
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
PgTypeMetadata {
|
||||
oid: 20,
|
||||
|
@ -75,11 +68,7 @@ impl HasSqlType<BigInt> for Pg {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for i64 {
|
||||
type SqlType = BigInt;
|
||||
}
|
||||
|
||||
impl ToSql<BigInt, Pg> for i64 {
|
||||
impl ToSql<Pg> for i64 {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
buf.extend_from_slice(&self.to_be_bytes());
|
||||
|
@ -88,15 +77,15 @@ impl ToSql<BigInt, Pg> for i64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromSql<BigInt, Pg> for i64 {
|
||||
impl FromSql<Pg> for i64 {
|
||||
#[inline]
|
||||
fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
// TODO: Handle optionals
|
||||
BigEndian::read_i64(buf.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSqlType<Real> for Pg {
|
||||
impl HasSqlType<f32> for Pg {
|
||||
#[inline]
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
PgTypeMetadata {
|
||||
oid: 700,
|
||||
|
@ -105,25 +94,22 @@ impl HasSqlType<Real> for Pg {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for f32 {
|
||||
type SqlType = Real;
|
||||
}
|
||||
|
||||
impl ToSql<Real, Pg> for f32 {
|
||||
impl ToSql<Pg> for f32 {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
(self.to_bits() as i32).to_sql(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql<BigInt, Pg> for f32 {
|
||||
impl FromSql<Pg> for f32 {
|
||||
#[inline]
|
||||
fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
f32::from_bits(i32::from_sql(buf) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSqlType<Double> for Pg {
|
||||
impl HasSqlType<f64> for Pg {
|
||||
#[inline]
|
||||
fn metadata() -> PgTypeMetadata {
|
||||
PgTypeMetadata {
|
||||
oid: 701,
|
||||
|
@ -132,18 +118,14 @@ impl HasSqlType<Double> for Pg {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsSqlType<Pg> for f64 {
|
||||
type SqlType = Double;
|
||||
}
|
||||
|
||||
impl ToSql<Double, Pg> for f64 {
|
||||
impl ToSql<Pg> for f64 {
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
(self.to_bits() as i64).to_sql(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql<Double, Pg> for f64 {
|
||||
impl FromSql<Pg> for f64 {
|
||||
#[inline]
|
||||
fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
f64::from_bits(i64::from_sql(buf) as u64)
|
||||
|
|
|
@ -140,10 +140,10 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
fn fetch<'c, 'q, T: 'c, Q: 'q + 'c>(&'c self, query: Q) -> BoxStream<'c, io::Result<T>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend> + Send + Unpin,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(async_stream::try_stream! {
|
||||
let live = self.0.acquire().await?;
|
||||
|
@ -156,13 +156,13 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch_optional<'c, 'q, A: 'c, T: 'c, Q: 'q + 'c>(
|
||||
fn fetch_optional<'c, 'q, T: 'c, Q: 'q + 'c>(
|
||||
&'c self,
|
||||
query: Q,
|
||||
) -> BoxFuture<'c, io::Result<Option<T>>>
|
||||
where
|
||||
Q: RawQuery<'q, Backend = Self::Backend>,
|
||||
T: FromRow<A, Self::Backend>,
|
||||
T: FromRow<Self::Backend>,
|
||||
{
|
||||
Box::pin(async move {
|
||||
let live = self.0.acquire().await?;
|
||||
|
|
36
src/query.rs
36
src/query.rs
|
@ -3,7 +3,7 @@ use crate::{
|
|||
executor::Executor,
|
||||
row::FromRow,
|
||||
serialize::ToSql,
|
||||
types::{AsSqlType, HasSqlType},
|
||||
types::HasSqlType,
|
||||
};
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
use std::io;
|
||||
|
@ -13,10 +13,10 @@ pub trait RawQuery<'q>: Sized + Send + Sync {
|
|||
|
||||
fn new(query: &'q str) -> Self;
|
||||
|
||||
fn bind_as<ST, T>(self, value: T) -> Self
|
||||
fn bind<T>(self, value: T) -> Self
|
||||
where
|
||||
Self::Backend: HasSqlType<ST>,
|
||||
T: ToSql<ST, Self::Backend>;
|
||||
Self::Backend: HasSqlType<T>,
|
||||
T: ToSql<Self::Backend>;
|
||||
|
||||
fn finish(self, conn: &mut <Self::Backend as Backend>::RawConnection);
|
||||
}
|
||||
|
@ -40,21 +40,12 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bind<T>(self, value: T) -> Self
|
||||
pub fn bind<T>(mut self, value: T) -> Self
|
||||
where
|
||||
DB: HasSqlType<<T as AsSqlType<DB>>::SqlType>,
|
||||
T: AsSqlType<DB> + ToSql<<T as AsSqlType<DB>>::SqlType, DB>,
|
||||
DB: HasSqlType<T>,
|
||||
T: ToSql<DB>,
|
||||
{
|
||||
self.bind_as::<T::SqlType, T>(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bind_as<ST, T>(mut self, value: T) -> Self
|
||||
where
|
||||
DB: HasSqlType<ST>,
|
||||
T: ToSql<ST, DB>,
|
||||
{
|
||||
self.inner = self.inner.bind_as::<ST, T>(value);
|
||||
self.inner = self.inner.bind(value);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -70,23 +61,20 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fetch<E, A: 'q, T: 'q>(self, executor: &'q E) -> BoxStream<'q, io::Result<T>>
|
||||
pub fn fetch<E, T: 'q>(self, executor: &'q E) -> BoxStream<'q, io::Result<T>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
T: FromRow<A, DB> + Send + Unpin,
|
||||
T: FromRow<DB> + Send + Unpin,
|
||||
<DB as BackendAssocRawQuery<'q, DB>>::RawQuery: 'q,
|
||||
{
|
||||
executor.fetch(self.inner)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fetch_optional<E, A: 'q, T: 'q>(
|
||||
self,
|
||||
executor: &'q E,
|
||||
) -> BoxFuture<'q, io::Result<Option<T>>>
|
||||
pub fn fetch_optional<E, T: 'q>(self, executor: &'q E) -> BoxFuture<'q, io::Result<Option<T>>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
T: FromRow<A, DB>,
|
||||
T: FromRow<DB>,
|
||||
<DB as BackendAssocRawQuery<'q, DB>>::RawQuery: 'q,
|
||||
{
|
||||
executor.fetch_optional(self.inner)
|
||||
|
|
116
src/row.rs
116
src/row.rs
|
@ -10,41 +10,41 @@ pub trait Row: Send {
|
|||
fn get_raw(&self, index: usize) -> Option<&[u8]>;
|
||||
|
||||
#[inline]
|
||||
fn get<ST, T>(&self, index: usize) -> T
|
||||
fn get<T>(&self, index: usize) -> T
|
||||
where
|
||||
Self::Backend: HasSqlType<ST>,
|
||||
T: FromSql<ST, Self::Backend>,
|
||||
Self::Backend: HasSqlType<T>,
|
||||
T: FromSql<Self::Backend>,
|
||||
{
|
||||
T::from_sql(self.get_raw(index))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FromRow<A, DB: Backend> {
|
||||
pub trait FromRow<DB: Backend> {
|
||||
fn from_row<R: Row<Backend = DB>>(row: R) -> Self;
|
||||
}
|
||||
|
||||
impl<T, ST, DB> FromRow<ST, DB> for T
|
||||
impl<T, DB> FromRow<DB> for T
|
||||
where
|
||||
DB: Backend + HasSqlType<ST>,
|
||||
T: FromSql<ST, DB>,
|
||||
DB: Backend + HasSqlType<T>,
|
||||
T: FromSql<DB>,
|
||||
{
|
||||
#[inline]
|
||||
fn from_row<R: Row<Backend = DB>>(row: R) -> Self {
|
||||
row.get::<ST, T>(0)
|
||||
row.get::<T>(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_from_row_tuple {
|
||||
($B:ident: $( ($idx:tt) -> $T:ident, $ST:ident );+;) => {
|
||||
impl<$($ST,)+ $($T,)+> crate::row::FromRow<($($ST,)+), $B> for ($($T,)+)
|
||||
($B:ident: $( ($idx:tt) -> $T:ident );+;) => {
|
||||
impl<$($T,)+> crate::row::FromRow<$B> for ($($T,)+)
|
||||
where
|
||||
$($B: crate::types::HasSqlType<$ST>,)+
|
||||
$($T: crate::deserialize::FromSql<$ST, $B>,)+
|
||||
$($B: crate::types::HasSqlType<$T>,)+
|
||||
$($T: crate::deserialize::FromSql<$B>,)+
|
||||
{
|
||||
#[inline]
|
||||
fn from_row<R: crate::row::Row<Backend = $B>>(row: R) -> Self {
|
||||
($(row.get::<$ST, $T>($idx),)+)
|
||||
($(row.get($idx),)+)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -54,75 +54,75 @@ macro_rules! impl_from_row_tuple {
|
|||
macro_rules! impl_from_row_tuples_for_backend {
|
||||
($B:ident) => {
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(0) -> T1;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(2) -> ST3, T3;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
(2) -> T3;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(2) -> ST3, T3;
|
||||
(3) -> ST4, T4;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
(2) -> T3;
|
||||
(3) -> T4;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(2) -> ST3, T3;
|
||||
(3) -> ST4, T4;
|
||||
(4) -> ST5, T5;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
(2) -> T3;
|
||||
(3) -> T4;
|
||||
(4) -> T5;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(2) -> ST3, T3;
|
||||
(3) -> ST4, T4;
|
||||
(4) -> ST5, T5;
|
||||
(5) -> ST6, T6;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
(2) -> T3;
|
||||
(3) -> T4;
|
||||
(4) -> T5;
|
||||
(5) -> T6;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(2) -> ST3, T3;
|
||||
(3) -> ST4, T4;
|
||||
(4) -> ST5, T5;
|
||||
(5) -> ST6, T6;
|
||||
(6) -> ST7, T7;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
(2) -> T3;
|
||||
(3) -> T4;
|
||||
(4) -> T5;
|
||||
(5) -> T6;
|
||||
(6) -> T7;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(2) -> ST3, T3;
|
||||
(3) -> ST4, T4;
|
||||
(4) -> ST5, T5;
|
||||
(5) -> ST6, T6;
|
||||
(6) -> ST7, T7;
|
||||
(7) -> ST8, T8;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
(2) -> T3;
|
||||
(3) -> T4;
|
||||
(4) -> T5;
|
||||
(5) -> T6;
|
||||
(6) -> T7;
|
||||
(7) -> T8;
|
||||
);
|
||||
|
||||
impl_from_row_tuple!($B:
|
||||
(0) -> ST1, T1;
|
||||
(1) -> ST2, T2;
|
||||
(2) -> ST3, T3;
|
||||
(3) -> ST4, T4;
|
||||
(4) -> ST5, T5;
|
||||
(5) -> ST6, T6;
|
||||
(6) -> ST7, T7;
|
||||
(7) -> ST8, T8;
|
||||
(8) -> ST9, T9;
|
||||
(0) -> T1;
|
||||
(1) -> T2;
|
||||
(2) -> T3;
|
||||
(3) -> T4;
|
||||
(4) -> T5;
|
||||
(5) -> T6;
|
||||
(6) -> T7;
|
||||
(7) -> T8;
|
||||
(8) -> T9;
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ pub enum IsNull {
|
|||
}
|
||||
|
||||
/// Serializes a single value to be sent to the database.
|
||||
pub trait ToSql<A, DB: Backend> {
|
||||
pub trait ToSql<DB: Backend> {
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull;
|
||||
}
|
||||
|
||||
impl<T, ST, DB> ToSql<ST, DB> for Option<T>
|
||||
impl<T, DB> ToSql<DB> for Option<T>
|
||||
where
|
||||
DB: Backend + HasSqlType<ST>,
|
||||
T: ToSql<ST, DB>,
|
||||
DB: Backend + HasSqlType<T>,
|
||||
T: ToSql<DB>,
|
||||
{
|
||||
#[inline]
|
||||
fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
|
|
64
src/types.rs
64
src/types.rs
|
@ -13,45 +13,43 @@ pub trait HasSqlType<A>: TypeMetadata {
|
|||
fn metadata() -> Self::TypeMetadata;
|
||||
}
|
||||
|
||||
/// Defines the canonical SQL that the implementing Rust type represents.
|
||||
/// This trait is used to map Rust types to SQL types when the explicit mapping is missing.
|
||||
pub trait AsSqlType<DB: Backend>
|
||||
where
|
||||
DB: HasSqlType<Self::SqlType>,
|
||||
{
|
||||
type SqlType;
|
||||
}
|
||||
// TODO: #[derive(SqlType)]
|
||||
// pub struct Text<'a>(Cow<'a, str>);
|
||||
|
||||
impl<T, DB> AsSqlType<DB> for Option<T>
|
||||
where
|
||||
DB: Backend + HasSqlType<<T as AsSqlType<DB>>::SqlType>,
|
||||
T: AsSqlType<DB>,
|
||||
{
|
||||
type SqlType = T::SqlType;
|
||||
}
|
||||
// TODO: #[derive(SqlType)]
|
||||
// pub struct SmallInt(i16);
|
||||
|
||||
// Character types
|
||||
// All character types (VARCHAR, CHAR, TEXT, etc.) are represented equivalently in binary and all fold
|
||||
// to this `Text` type.
|
||||
// TODO: #[derive(SqlType)]
|
||||
// pub struct Int(i32);
|
||||
|
||||
pub struct Text;
|
||||
// TODO: #[derive(SqlType)]
|
||||
// pub struct BigInt(i64);
|
||||
|
||||
// Numeric types
|
||||
// TODO: #[derive(SqlType)]
|
||||
// pub struct Real(f32);
|
||||
|
||||
// i16
|
||||
pub struct SmallInt;
|
||||
// TODO: #[derive(SqlType)]
|
||||
// pub struct Double(f64);
|
||||
|
||||
// i32
|
||||
pub struct Int;
|
||||
// Example of what that derive should generate
|
||||
|
||||
// i64
|
||||
pub struct BigInt;
|
||||
// impl HasSqlType<Bool> for Pg {
|
||||
// #[inline]
|
||||
// fn metadata() -> PgTypeMetadata {
|
||||
// <Pg as HasSqlType<bool>>::metadata()
|
||||
// }
|
||||
// }
|
||||
|
||||
// decimal?
|
||||
// TODO pub struct Decimal;
|
||||
// impl ToSql<Pg> for Bool {
|
||||
// #[inline]
|
||||
// fn to_sql(self, buf: &mut Vec<u8>) -> IsNull {
|
||||
// self.0.to_sql(buf)
|
||||
// }
|
||||
// }
|
||||
|
||||
// f32
|
||||
pub struct Real;
|
||||
|
||||
// f64
|
||||
pub struct Double;
|
||||
// impl FromSql<Pg> for bool {
|
||||
// #[inline]
|
||||
// fn from_sql(buf: Option<&[u8]>) -> Self {
|
||||
// Self(bool::from_sql(buf))
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in a new issue