use crate::error::DrizzleError;
use crate::row::{FromDrizzleRow, NullProbeRow};
#[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
pub use ::postgres::types::FromSql;
#[cfg(feature = "tokio-postgres")]
pub use ::tokio_postgres::types::FromSql;
pub trait PostgresValueRow {
fn try_get_from_sql<'a, T>(&'a self, offset: usize) -> Result<T, DrizzleError>
where
T: FromSql<'a>;
}
macro_rules! postgres_leaf_impls {
($row_ty:ty; $($ty:ty),* $(,)?) => { $(
impl FromDrizzleRow<$row_ty> for $ty {
const COLUMN_COUNT: usize = 1;
fn from_row_at(row: &$row_ty, offset: usize) -> Result<Self, DrizzleError> {
<$row_ty as PostgresValueRow>::try_get_from_sql(row, offset)
}
}
impl FromDrizzleRow<$row_ty> for Option<$ty> {
const COLUMN_COUNT: usize = 1;
fn from_row_at(row: &$row_ty, offset: usize) -> Result<Self, DrizzleError> {
<$row_ty as PostgresValueRow>::try_get_from_sql(row, offset)
}
}
)* };
}
macro_rules! impl_postgres_value_row {
($row_ty:ty) => {
postgres_leaf_impls!(
$row_ty;
i8, i16, i32, i64, f32, f64, bool, String,
Vec<u8>,
Vec<i16>, Vec<i32>, Vec<i64>, Vec<f32>, Vec<f64>,
Vec<bool>, Vec<String>,
);
#[cfg(feature = "uuid")]
postgres_leaf_impls!($row_ty; uuid::Uuid, Vec<uuid::Uuid>);
#[cfg(feature = "chrono")]
postgres_leaf_impls!(
$row_ty;
chrono::NaiveDate, chrono::NaiveTime, chrono::NaiveDateTime,
chrono::DateTime<chrono::Utc>,
Vec<chrono::NaiveDate>, Vec<chrono::NaiveTime>,
Vec<chrono::NaiveDateTime>, Vec<chrono::DateTime<chrono::Utc>>,
);
#[cfg(feature = "serde")]
postgres_leaf_impls!($row_ty; serde_json::Value, Vec<serde_json::Value>);
#[cfg(feature = "rust-decimal")]
postgres_leaf_impls!($row_ty; rust_decimal::Decimal);
#[cfg(feature = "cidr")]
postgres_leaf_impls!($row_ty; cidr::IpInet, cidr::IpCidr);
#[cfg(feature = "geo-types")]
postgres_leaf_impls!(
$row_ty;
geo_types::Point<f64>,
geo_types::LineString<f64>,
geo_types::Rect<f64>,
);
#[cfg(feature = "bit-vec")]
postgres_leaf_impls!($row_ty; bit_vec::BitVec);
impl<T> FromDrizzleRow<$row_ty> for Option<T>
where
T: NullProbeRow<$row_ty>,
{
const COLUMN_COUNT: usize = T::COLUMN_COUNT;
fn from_row_at(row: &$row_ty, offset: usize) -> Result<Self, DrizzleError> {
if T::is_null_at(row, offset)? {
return Ok(None);
}
T::from_row_at(row, offset).map(Some)
}
}
};
}
#[cfg(feature = "tokio-postgres")]
impl PostgresValueRow for ::tokio_postgres::Row {
fn try_get_from_sql<'a, T>(&'a self, offset: usize) -> Result<T, DrizzleError>
where
T: FromSql<'a>,
{
self.try_get(offset)
.map_err(|e| DrizzleError::ConversionError(e.to_string().into()))
}
}
#[cfg(feature = "tokio-postgres")]
impl_postgres_value_row!(::tokio_postgres::Row);
#[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
impl PostgresValueRow for ::postgres::Row {
fn try_get_from_sql<'a, T>(&'a self, offset: usize) -> Result<T, DrizzleError>
where
T: FromSql<'a>,
{
self.try_get(offset)
.map_err(|e| DrizzleError::ConversionError(e.to_string().into()))
}
}
#[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
impl_postgres_value_row!(::postgres::Row);