rust-postgres/src/types/mod.rs

677 lines
20 KiB
Rust
Raw Normal View History

2013-10-20 21:34:50 +00:00
//! Traits dealing with Postgres data types
2014-02-26 08:40:57 +00:00
use serialize::json;
2014-06-06 03:50:23 +00:00
use std::collections::HashMap;
2015-01-28 16:52:33 +00:00
use std::old_io::net::ip::IpAddr;
use std::fmt;
2014-11-01 23:12:05 +00:00
use Result;
use error::Error;
pub use ugh_privacy::Unknown;
2014-12-19 18:43:42 +00:00
macro_rules! check_types {
2015-01-09 18:26:24 +00:00
($($expected:pat),+; $actual:ident) => (
2014-11-17 17:43:10 +00:00
match $actual {
$(&$expected)|+ => {}
actual => return Err(::Error::WrongType(actual.clone()))
2014-11-17 17:43:10 +00:00
}
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
2014-12-19 18:43:42 +00:00
macro_rules! raw_from_impl {
2014-11-17 17:43:10 +00:00
($t:ty, $f:ident) => (
impl RawFromSql for $t {
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<$t> {
2014-11-17 17:43:10 +00:00
Ok(try!(raw.$f()))
}
}
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
2014-12-19 18:43:42 +00:00
macro_rules! from_option_impl {
2015-01-09 18:26:24 +00:00
($t:ty) => {
2014-11-18 03:11:32 +00:00
impl ::types::FromSql for $t {
2014-12-23 02:45:09 +00:00
fn from_sql(ty: &Type, raw: Option<&[u8]>) -> Result<$t> {
2014-11-18 03:11:32 +00:00
use Error;
use types::FromSql;
2014-11-17 17:43:10 +00:00
// FIXME when you can specify Self types properly
let ret: Result<Option<$t>> = FromSql::from_sql(ty, raw);
match ret {
Ok(Some(val)) => Ok(val),
Ok(None) => Err(Error::WasNull),
2014-11-17 17:43:10 +00:00
Err(err) => Err(err)
}
}
}
}
2014-12-19 18:43:42 +00:00
}
2014-12-19 18:43:42 +00:00
macro_rules! from_map_impl {
2015-01-09 18:26:24 +00:00
($($expected:pat),+; $t:ty, $blk:expr) => (
impl ::types::FromSql for Option<$t> {
2014-12-23 02:45:09 +00:00
fn from_sql(ty: &Type, raw: Option<&[u8]>) -> Result<Option<$t>> {
2015-01-09 18:26:24 +00:00
check_types!($($expected),+; ty);
2014-12-23 02:45:09 +00:00
match raw {
Some(buf) => ($blk)(ty, buf).map(|ok| Some(ok)),
None => Ok(None)
}
}
}
2015-01-09 18:26:24 +00:00
from_option_impl!($t);
2014-11-17 17:43:10 +00:00
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
2014-12-19 18:43:42 +00:00
macro_rules! from_raw_from_impl {
2015-01-09 18:26:24 +00:00
($($expected:pat),+; $t:ty) => (
2015-02-06 16:56:23 +00:00
from_map_impl!($($expected),+; $t, |ty, mut buf: &[u8]| {
2014-11-18 03:11:32 +00:00
use types::RawFromSql;
RawFromSql::raw_from_sql(ty, &mut buf)
2015-01-09 18:26:24 +00:00
});
2014-11-17 17:43:10 +00:00
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
2014-12-19 18:43:42 +00:00
macro_rules! raw_to_impl {
2014-11-17 17:43:10 +00:00
($t:ty, $f:ident) => (
impl RawToSql for $t {
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
2014-11-17 17:43:10 +00:00
Ok(try!(w.$f(*self)))
}
}
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
2014-12-19 18:43:42 +00:00
macro_rules! to_option_impl {
2015-01-09 18:26:24 +00:00
($($oid:pat),+; $t:ty) => (
2014-11-18 03:11:32 +00:00
impl ::types::ToSql for Option<$t> {
2014-11-17 17:43:10 +00:00
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
2015-01-09 18:26:24 +00:00
check_types!($($oid),+; ty);
2014-11-17 17:43:10 +00:00
match *self {
None => Ok(None),
Some(ref val) => val.to_sql(ty)
}
}
}
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
2014-12-19 18:43:42 +00:00
macro_rules! to_option_impl_lifetime {
2015-01-09 18:26:24 +00:00
($($oid:pat),+; $t:ty) => (
2014-11-17 17:43:10 +00:00
impl<'a> ToSql for Option<$t> {
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
2015-01-09 18:26:24 +00:00
check_types!($($oid),+; ty);
2014-11-17 17:43:10 +00:00
match *self {
None => Ok(None),
Some(ref val) => val.to_sql(ty)
}
}
}
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
2014-12-19 18:43:42 +00:00
macro_rules! to_raw_to_impl {
2015-01-09 18:26:24 +00:00
($($oid:pat),+; $t:ty) => (
2014-11-18 03:11:32 +00:00
impl ::types::ToSql for $t {
2014-11-17 17:43:10 +00:00
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
2015-01-09 18:26:24 +00:00
check_types!($($oid),+; ty);
2014-11-17 17:43:10 +00:00
2014-11-20 04:54:32 +00:00
let mut writer = vec![];
try!(self.raw_to_sql(ty, &mut writer));
2014-11-20 04:54:32 +00:00
Ok(Some(writer))
2014-11-17 17:43:10 +00:00
}
}
2015-01-09 18:26:24 +00:00
to_option_impl!($($oid),+; $t);
2014-11-17 17:43:10 +00:00
)
2014-12-19 18:43:42 +00:00
}
2014-11-17 17:43:10 +00:00
#[cfg(feature = "uuid")]
mod uuid;
2014-11-18 03:11:32 +00:00
mod time;
2013-10-29 05:35:52 +00:00
2013-09-30 02:47:30 +00:00
/// A Postgres OID
2014-01-03 07:10:26 +00:00
pub type Oid = u32;
// Values from pg_type.h
2014-10-10 04:50:40 +00:00
const BOOLOID: Oid = 16;
const BYTEAOID: Oid = 17;
const CHAROID: Oid = 18;
const NAMEOID: Oid = 19;
const INT8OID: Oid = 20;
const INT2OID: Oid = 21;
const INT4OID: Oid = 23;
const TEXTOID: Oid = 25;
const OIDOID: Oid = 26;
2014-10-10 04:50:40 +00:00
const JSONOID: Oid = 114;
const JSONARRAYOID: Oid = 199;
2014-12-14 20:27:02 +00:00
const CIDROID: Oid = 650;
2014-10-10 04:50:40 +00:00
const FLOAT4OID: Oid = 700;
const FLOAT8OID: Oid = 701;
const INETOID: Oid = 869;
2014-10-10 04:50:40 +00:00
const BOOLARRAYOID: Oid = 1000;
const BYTEAARRAYOID: Oid = 1001;
const CHARARRAYOID: Oid = 1002;
const NAMEARRAYOID: Oid = 1003;
const INT2ARRAYOID: Oid = 1005;
const INT4ARRAYOID: Oid = 1007;
const TEXTARRAYOID: Oid = 1009;
const BPCHARARRAYOID: Oid = 1014;
const VARCHARARRAYOID: Oid = 1015;
const INT8ARRAYOID: Oid = 1016;
const FLOAT4ARRAYOID: Oid = 1021;
const FLAOT8ARRAYOID: Oid = 1022;
const BPCHAROID: Oid = 1042;
const VARCHAROID: Oid = 1043;
const TIMESTAMPOID: Oid = 1114;
const TIMESTAMPARRAYOID: Oid = 1115;
const TIMESTAMPZOID: Oid = 1184;
const TIMESTAMPZARRAYOID: Oid = 1185;
2014-11-06 15:53:16 +00:00
const UUIDOID: Oid = 2950;
const UUIDARRAYOID: Oid = 2951;
2014-12-23 02:04:13 +00:00
const JSONBOID: Oid = 3802;
const JSONBARRAYOID: Oid = 3807;
2014-10-10 04:50:40 +00:00
const INT4RANGEOID: Oid = 3904;
const INT4RANGEARRAYOID: Oid = 3905;
const TSRANGEOID: Oid = 3908;
const TSRANGEARRAYOID: Oid = 3909;
const TSTZRANGEOID: Oid = 3910;
const TSTZRANGEARRAYOID: Oid = 3911;
const INT8RANGEOID: Oid = 3926;
const INT8RANGEARRAYOID: Oid = 3927;
2014-12-19 18:43:42 +00:00
macro_rules! make_postgres_type {
2015-01-09 18:26:24 +00:00
($(#[$doc:meta] $oid:ident => $variant:ident: $(member $member:ident)*),+) => (
2013-12-08 03:34:48 +00:00
/// A Postgres type
2015-01-10 21:58:46 +00:00
#[derive(PartialEq, Eq, Clone)]
2014-11-04 05:29:16 +00:00
pub enum Type {
2013-12-08 03:34:48 +00:00
$(
2014-03-29 21:33:11 +00:00
#[$doc]
2013-12-08 03:34:48 +00:00
$variant,
)+
/// An unknown type
2015-02-06 07:37:27 +00:00
Unknown(Box<Unknown>),
}
2015-01-23 18:44:15 +00:00
impl fmt::Debug for Type {
2015-01-10 21:58:46 +00:00
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
$(Type::$variant => stringify!($variant),)+
Type::Unknown(ref u) => return fmt::Debug::fmt(u, fmt),
2015-01-10 21:58:46 +00:00
};
fmt.write_str(s)
}
}
2014-11-04 05:29:16 +00:00
impl Type {
/// Creates a `Type` from an OID.
///
2015-01-22 06:11:43 +00:00
/// If the OID is unknown, `None` is returned.
pub fn from_oid(oid: Oid) -> Option<Type> {
2013-12-08 03:34:48 +00:00
match oid {
2015-01-22 06:11:43 +00:00
$($oid => Some(Type::$variant),)+
_ => None
2013-12-08 03:34:48 +00:00
}
}
/// Returns the OID of the `Type`.
2013-12-08 19:44:37 +00:00
pub fn to_oid(&self) -> Oid {
match *self {
2014-11-04 05:29:16 +00:00
$(Type::$variant => $oid,)+
Type::Unknown(ref u) => u.oid(),
2013-12-08 19:44:37 +00:00
}
}
/// If this `Type` is an array or range, returns the type of its elements
2015-01-22 06:11:43 +00:00
pub fn element_type(&self) -> Option<Type> {
2013-12-08 19:44:37 +00:00
match *self {
$(
2015-01-10 21:51:53 +00:00
$(Type::$variant => Some(Type::$member),)*
2013-12-08 19:44:37 +00:00
)+
Type::Unknown(ref u) => u.element_type().cloned(),
2015-01-10 21:51:53 +00:00
_ => None
2013-12-08 19:44:37 +00:00
}
}
}
2013-12-08 03:34:48 +00:00
)
2014-12-19 18:43:42 +00:00
}
2013-12-08 03:34:48 +00:00
2014-12-19 18:43:42 +00:00
make_postgres_type! {
2013-12-08 03:34:48 +00:00
#[doc="BOOL"]
2015-01-09 18:26:24 +00:00
BOOLOID => Bool:,
2013-12-08 03:34:48 +00:00
#[doc="BYTEA"]
2015-01-09 18:26:24 +00:00
BYTEAOID => ByteA:,
2013-12-08 03:34:48 +00:00
#[doc="\"char\""]
2015-01-09 18:26:24 +00:00
CHAROID => Char:,
#[doc="NAME"]
2015-01-09 18:26:24 +00:00
NAMEOID => Name:,
2013-12-08 03:34:48 +00:00
#[doc="INT8/BIGINT"]
2015-01-09 18:26:24 +00:00
INT8OID => Int8:,
2013-12-08 03:34:48 +00:00
#[doc="INT2/SMALLINT"]
2015-01-09 18:26:24 +00:00
INT2OID => Int2:,
2013-12-08 03:34:48 +00:00
#[doc="INT4/INT"]
2015-01-09 18:26:24 +00:00
INT4OID => Int4:,
2013-12-08 03:34:48 +00:00
#[doc="TEXT"]
2015-01-09 18:26:24 +00:00
TEXTOID => Text:,
#[doc="OID"]
2015-01-09 18:26:24 +00:00
OIDOID => Oid:,
2013-12-08 03:34:48 +00:00
#[doc="JSON"]
2015-01-09 18:26:24 +00:00
JSONOID => Json:,
2014-12-14 20:27:02 +00:00
#[doc="CIDR"]
2015-01-09 18:26:24 +00:00
CIDROID => Cidr:,
2013-12-09 00:00:33 +00:00
#[doc="JSON[]"]
2015-01-09 18:26:24 +00:00
JSONARRAYOID => JsonArray: member Json,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT4/REAL"]
2015-01-09 18:26:24 +00:00
FLOAT4OID => Float4:,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT8/DOUBLE PRECISION"]
2015-01-09 18:26:24 +00:00
FLOAT8OID => Float8:,
#[doc="INET"]
2015-01-09 18:26:24 +00:00
INETOID => Inet:,
2013-12-08 03:34:48 +00:00
#[doc="BOOL[]"]
2015-01-09 18:26:24 +00:00
BOOLARRAYOID => BoolArray: member Bool,
2013-12-08 03:34:48 +00:00
#[doc="BYTEA[]"]
2015-01-09 18:26:24 +00:00
BYTEAARRAYOID => ByteAArray: member ByteA,
2013-12-08 03:34:48 +00:00
#[doc="\"char\"[]"]
2015-01-09 18:26:24 +00:00
CHARARRAYOID => CharArray: member Char,
#[doc="NAME[]"]
2015-01-09 18:26:24 +00:00
NAMEARRAYOID => NameArray: member Name,
2013-12-08 03:34:48 +00:00
#[doc="INT2[]"]
2015-01-09 18:26:24 +00:00
INT2ARRAYOID => Int2Array: member Int2,
2013-12-08 03:34:48 +00:00
#[doc="INT4[]"]
2015-01-09 18:26:24 +00:00
INT4ARRAYOID => Int4Array: member Int4,
2013-12-08 03:34:48 +00:00
#[doc="TEXT[]"]
2015-01-09 18:26:24 +00:00
TEXTARRAYOID => TextArray: member Text,
2013-12-08 19:44:37 +00:00
#[doc="CHAR(n)[]"]
2015-01-09 18:26:24 +00:00
BPCHARARRAYOID => CharNArray: member CharN,
2013-12-08 21:58:41 +00:00
#[doc="VARCHAR[]"]
2015-01-09 18:26:24 +00:00
VARCHARARRAYOID => VarcharArray: member Varchar,
2013-12-08 03:34:48 +00:00
#[doc="INT8[]"]
2015-01-09 18:26:24 +00:00
INT8ARRAYOID => Int8Array: member Int8,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT4[]"]
2015-01-09 18:26:24 +00:00
FLOAT4ARRAYOID => Float4Array: member Float4,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT8[]"]
2015-01-09 18:26:24 +00:00
FLAOT8ARRAYOID => Float8Array: member Float8,
2013-12-08 03:34:48 +00:00
#[doc="TIMESTAMP"]
2015-01-09 18:26:24 +00:00
TIMESTAMPOID => Timestamp:,
2013-12-08 22:04:26 +00:00
#[doc="TIMESTAMP[]"]
2015-01-09 18:26:24 +00:00
TIMESTAMPARRAYOID => TimestampArray: member Timestamp,
2013-12-08 03:34:48 +00:00
#[doc="TIMESTAMP WITH TIME ZONE"]
2015-01-09 18:26:24 +00:00
TIMESTAMPZOID => TimestampTZ:,
2013-12-08 22:08:35 +00:00
#[doc="TIMESTAMP WITH TIME ZONE[]"]
2015-01-09 18:26:24 +00:00
TIMESTAMPZARRAYOID => TimestampTZArray: member TimestampTZ,
2014-11-06 15:53:16 +00:00
#[doc="UUID"]
2015-01-09 18:26:24 +00:00
UUIDOID => Uuid:,
2014-11-06 15:53:16 +00:00
#[doc="UUID[]"]
2015-01-09 18:26:24 +00:00
UUIDARRAYOID => UuidArray: member Uuid,
2014-12-23 02:04:13 +00:00
#[doc="JSONB"]
2015-01-09 18:26:24 +00:00
JSONBOID => Jsonb:,
2014-12-23 02:04:13 +00:00
#[doc="JSONB[]"]
2015-01-09 18:26:24 +00:00
JSONBARRAYOID => JsonbArray: member Jsonb,
2013-12-08 03:34:48 +00:00
#[doc="CHAR(n)/CHARACTER(n)"]
2015-01-09 18:26:24 +00:00
BPCHAROID => CharN:,
2013-12-08 03:34:48 +00:00
#[doc="VARCHAR/CHARACTER VARYING"]
2015-01-09 18:26:24 +00:00
VARCHAROID => Varchar:,
2013-12-08 03:34:48 +00:00
#[doc="INT4RANGE"]
INT4RANGEOID => Int4Range: member Int4,
2013-12-08 22:37:31 +00:00
#[doc="INT4RANGE[]"]
2015-01-09 18:26:24 +00:00
INT4RANGEARRAYOID => Int4RangeArray: member Int4Range,
2013-12-08 03:34:48 +00:00
#[doc="TSRANGE"]
TSRANGEOID => TsRange: member Timestamp,
2013-12-08 23:02:38 +00:00
#[doc="TSRANGE[]"]
2015-01-09 18:26:24 +00:00
TSRANGEARRAYOID => TsRangeArray: member TsRange,
2013-12-08 03:34:48 +00:00
#[doc="TSTZRANGE"]
TSTZRANGEOID => TstzRange: member TimestampTZ,
2013-12-08 23:02:38 +00:00
#[doc="TSTZRANGE[]"]
2015-01-09 18:26:24 +00:00
TSTZRANGEARRAYOID => TstzRangeArray: member TstzRange,
2013-12-08 23:07:11 +00:00
#[doc="INT8RANGE"]
INT8RANGEOID => Int8Range: member Int8,
2013-12-08 23:07:11 +00:00
#[doc="INT8RANGE[]"]
2015-01-09 18:26:24 +00:00
INT8RANGEARRAYOID => Int8RangeArray: member Int8Range
2014-12-19 18:43:42 +00:00
}
2013-09-30 05:22:10 +00:00
/// A trait for types that can be created from a Postgres value
pub trait FromSql {
2013-09-30 02:47:30 +00:00
/// Creates a new value of this type from a buffer of Postgres data.
///
/// If the value was `NULL`, the buffer will be `None`.
2014-12-23 02:45:09 +00:00
fn from_sql(ty: &Type, raw: Option<&[u8]>) -> Result<Self>;
}
/// A utility trait used by `FromSql` implementations
pub trait RawFromSql {
/// Creates a new value of this type from a `Reader` of Postgres data.
///
/// It is the caller's responsibility to ensure that Postgres data of this
/// type can be turned in to this type.
fn raw_from_sql<R: Reader>(ty: &Type, raw: &mut R) -> Result<Self>;
2013-10-31 02:55:25 +00:00
}
2013-12-07 23:39:44 +00:00
impl RawFromSql for bool {
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<bool> {
2014-11-17 06:54:57 +00:00
Ok((try!(raw.read_u8())) != 0)
2013-12-07 23:39:44 +00:00
}
}
2014-04-08 03:02:05 +00:00
impl RawFromSql for Vec<u8> {
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<Vec<u8>> {
2014-11-17 17:43:10 +00:00
Ok(try!(raw.read_to_end()))
}
}
2013-12-08 22:37:31 +00:00
2014-11-17 17:43:10 +00:00
impl RawFromSql for String {
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<String> {
String::from_utf8(try!(raw.read_to_end())).map_err(|_| Error::BadData)
2014-11-17 17:43:10 +00:00
}
}
2014-12-19 18:43:42 +00:00
raw_from_impl!(i8, read_i8);
raw_from_impl!(i16, read_be_i16);
raw_from_impl!(i32, read_be_i32);
raw_from_impl!(u32, read_be_u32);
raw_from_impl!(i64, read_be_i64);
raw_from_impl!(f32, read_be_f32);
raw_from_impl!(f64, read_be_f64);
2014-11-17 17:43:10 +00:00
2014-11-04 05:29:16 +00:00
impl RawFromSql for json::Json {
fn raw_from_sql<R: Reader>(ty: &Type, raw: &mut R) -> Result<json::Json> {
if let Type::Jsonb = *ty {
// We only support version 1 of the jsonb binary format
if try!(raw.read_u8()) != 1 {
return Err(Error::BadData);
}
}
2015-01-03 21:23:11 +00:00
json::Json::from_reader(raw).map_err(|_| Error::BadData)
2013-12-09 00:00:33 +00:00
}
}
impl RawFromSql for IpAddr {
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<IpAddr> {
let family = try!(raw.read_u8());
let _bits = try!(raw.read_u8());
let _is_cidr = try!(raw.read_u8());
let nb = try!(raw.read_u8());
if nb > 16 {
return Err(Error::BadData);
}
2015-01-03 21:23:11 +00:00
let mut buf = [0u8; 16];
try!(raw.read_at_least(nb as usize, &mut buf));
let mut buf: &[u8] = &buf;
match family {
2 if nb == 4 => Ok(IpAddr::Ipv4Addr(buf[0], buf[1], buf[2], buf[3])),
3 if nb == 16 => Ok(IpAddr::Ipv6Addr(try!(buf.read_be_u16()),
try!(buf.read_be_u16()),
try!(buf.read_be_u16()),
try!(buf.read_be_u16()),
try!(buf.read_be_u16()),
try!(buf.read_be_u16()),
try!(buf.read_be_u16()),
try!(buf.read_be_u16()))),
_ => Err(Error::BadData),
}
}
}
2015-01-09 18:26:24 +00:00
from_raw_from_impl!(Type::Bool; bool);
from_raw_from_impl!(Type::ByteA; Vec<u8>);
from_raw_from_impl!(Type::Char; i8);
from_raw_from_impl!(Type::Int2; i16);
from_raw_from_impl!(Type::Int4; i32);
from_raw_from_impl!(Type::Oid; u32);
from_raw_from_impl!(Type::Int8; i64);
from_raw_from_impl!(Type::Float4; f32);
from_raw_from_impl!(Type::Float8; f64);
from_raw_from_impl!(Type::Json, Type::Jsonb; json::Json);
2015-01-09 18:26:24 +00:00
from_raw_from_impl!(Type::Inet, Type::Cidr; IpAddr);
2014-12-19 18:43:42 +00:00
impl FromSql for Option<String> {
2014-12-23 02:45:09 +00:00
fn from_sql(ty: &Type, raw: Option<&[u8]>) -> Result<Option<String>> {
match *ty {
Type::Varchar | Type::Text | Type::CharN | Type::Name => {}
Type::Unknown(ref u) if u.name() == "citext" => {}
_ => return Err(Error::WrongType(ty.clone()))
}
2014-12-23 02:45:09 +00:00
match raw {
Some(mut buf) => {
Ok(Some(try!(RawFromSql::raw_from_sql(ty, &mut buf))))
}
None => Ok(None)
}
}
}
2014-12-19 18:43:42 +00:00
from_option_impl!(String);
2013-12-06 05:58:22 +00:00
2014-05-26 03:38:40 +00:00
impl FromSql for Option<HashMap<String, Option<String>>> {
2014-12-23 02:45:09 +00:00
fn from_sql(ty: &Type, raw: Option<&[u8]>)
2014-11-01 23:12:05 +00:00
-> Result<Option<HashMap<String, Option<String>>>> {
2014-03-13 06:50:10 +00:00
match *ty {
Type::Unknown(ref u) if u.name() == "hstore" => {}
_ => return Err(Error::WrongType(ty.clone()))
2014-03-13 06:50:10 +00:00
}
2014-12-23 02:45:09 +00:00
match raw {
Some(buf) => {
let mut rdr = buf;
2014-03-28 05:43:10 +00:00
let mut map = HashMap::new();
2013-12-05 05:20:48 +00:00
2014-11-17 06:54:57 +00:00
let count = try!(rdr.read_be_i32());
2013-12-05 05:20:48 +00:00
2014-03-28 05:43:10 +00:00
for _ in range(0, count) {
2014-11-17 06:54:57 +00:00
let key_len = try!(rdr.read_be_i32());
let key = try!(rdr.read_exact(key_len as usize));
2014-07-07 04:34:27 +00:00
let key = match String::from_utf8(key) {
Ok(key) => key,
Err(_) => return Err(Error::BadData),
2014-07-07 04:34:27 +00:00
};
2014-03-13 06:50:10 +00:00
2014-11-17 06:54:57 +00:00
let val_len = try!(rdr.read_be_i32());
2014-03-28 05:43:10 +00:00
let val = if val_len < 0 {
None
} else {
let val = try!(rdr.read_exact(val_len as usize));
2014-07-07 04:34:27 +00:00
match String::from_utf8(val) {
Ok(val) => Some(val),
Err(_) => return Err(Error::BadData),
2014-07-07 04:34:27 +00:00
}
2014-03-28 05:43:10 +00:00
};
2013-12-05 05:20:48 +00:00
2014-03-28 05:43:10 +00:00
map.insert(key, val);
}
Ok(Some(map))
2014-03-13 06:50:10 +00:00
}
2014-03-28 05:43:10 +00:00
None => Ok(None)
}
2013-12-05 05:20:48 +00:00
}
2014-03-13 06:50:10 +00:00
}
2013-12-05 05:20:48 +00:00
2014-12-19 18:43:42 +00:00
from_option_impl!(HashMap<String, Option<String>>);
2013-12-05 05:20:48 +00:00
2013-09-30 02:47:30 +00:00
/// A trait for types that can be converted into Postgres values
pub trait ToSql {
/// Converts the value of `self` into the binary format appropriate for the
/// Postgres backend.
2014-11-04 05:29:16 +00:00
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>>;
}
/// A utility trait used by `ToSql` implementations.
pub trait RawToSql {
/// Converts the value of `self` into the binary format of the specified
/// Postgres type, writing it to `w`.
///
/// It is the caller's responsibility to make sure that this type can be
/// converted to the specified Postgres type.
fn raw_to_sql<W: Writer>(&self, ty: &Type, w: &mut W) -> Result<()>;
2013-10-31 02:55:25 +00:00
}
2013-12-07 23:39:44 +00:00
impl RawToSql for bool {
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
2014-11-17 06:54:57 +00:00
Ok(try!(w.write_u8(*self as u8)))
2013-12-07 23:39:44 +00:00
}
}
2014-03-15 06:01:46 +00:00
impl RawToSql for Vec<u8> {
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
2015-01-28 16:52:33 +00:00
Ok(try!(w.write_all(&**self)))
2014-03-15 06:01:46 +00:00
}
}
2014-05-26 03:38:40 +00:00
impl RawToSql for String {
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
2015-01-28 16:52:33 +00:00
Ok(try!(w.write_all(self.as_bytes())))
2013-12-08 03:13:21 +00:00
}
}
2014-12-19 18:43:42 +00:00
raw_to_impl!(i8, write_i8);
raw_to_impl!(i16, write_be_i16);
raw_to_impl!(i32, write_be_i32);
raw_to_impl!(u32, write_be_u32);
raw_to_impl!(i64, write_be_i64);
raw_to_impl!(f32, write_be_f32);
raw_to_impl!(f64, write_be_f64);
2013-10-31 02:55:25 +00:00
2014-11-04 05:29:16 +00:00
impl RawToSql for json::Json {
fn raw_to_sql<W: Writer>(&self, ty: &Type, raw: &mut W) -> Result<()> {
if let Type::Jsonb = *ty {
try!(raw.write_u8(1));
}
2015-01-03 21:23:11 +00:00
Ok(try!(write!(raw, "{}", self)))
2013-12-09 00:00:33 +00:00
}
}
impl RawToSql for IpAddr {
fn raw_to_sql<W: Writer>(&self, _: &Type, raw: &mut W) -> Result<()> {
match *self {
IpAddr::Ipv4Addr(a, b, c, d) => {
2015-01-28 16:52:33 +00:00
try!(raw.write_all(&[2, // family
2014-12-18 17:07:15 +00:00
32, // bits
0, // is_cidr
4, // nb
a, b, c, d // addr
]));
}
IpAddr::Ipv6Addr(a, b, c, d, e, f, g, h) => {
2015-01-28 16:52:33 +00:00
try!(raw.write_all(&[3, // family
2014-12-18 17:07:15 +00:00
128, // bits
0, // is_cidr
16, // nb
]));
try!(raw.write_be_u16(a));
try!(raw.write_be_u16(b));
try!(raw.write_be_u16(c));
try!(raw.write_be_u16(d));
try!(raw.write_be_u16(e));
try!(raw.write_be_u16(f));
try!(raw.write_be_u16(g));
try!(raw.write_be_u16(h));
}
}
Ok(())
}
}
2015-01-09 18:26:24 +00:00
to_raw_to_impl!(Type::Bool; bool);
to_raw_to_impl!(Type::ByteA; Vec<u8>);
to_raw_to_impl!(Type::Json, Type::Jsonb; json::Json);
2015-01-09 18:26:24 +00:00
to_raw_to_impl!(Type::Inet, Type::Cidr; IpAddr);
to_raw_to_impl!(Type::Char; i8);
to_raw_to_impl!(Type::Int2; i16);
to_raw_to_impl!(Type::Int4; i32);
to_raw_to_impl!(Type::Oid; u32);
to_raw_to_impl!(Type::Int8; i64);
to_raw_to_impl!(Type::Float4; f32);
to_raw_to_impl!(Type::Float8; f64);
impl ToSql for String {
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
(&**self).to_sql(ty)
}
}
impl ToSql for Option<String> {
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
self.as_ref().map(|s| &**s).to_sql(ty)
}
}
impl<'a> ToSql for &'a str {
2014-11-04 05:29:16 +00:00
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
match *ty {
Type::Varchar | Type::Text | Type::CharN | Type::Name => {}
Type::Unknown(ref u) if u.name() == "citext" => {}
_ => return Err(Error::WrongType(ty.clone()))
}
Ok(Some(self.as_bytes().to_vec()))
}
}
impl<'a> ToSql for Option<&'a str> {
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
match *ty {
Type::Varchar | Type::Text | Type::CharN | Type::Name => {}
Type::Unknown(ref u) if u.name() == "citext" => {}
_ => return Err(Error::WrongType(ty.clone()))
}
match *self {
Some(ref val) => val.to_sql(ty),
None => Ok(None)
}
}
}
impl<'a> ToSql for &'a [u8] {
2014-11-04 05:29:16 +00:00
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
2015-01-09 18:26:24 +00:00
check_types!(Type::ByteA; ty);
Ok(Some(self.to_vec()))
}
}
2015-01-09 18:26:24 +00:00
to_option_impl_lifetime!(Type::ByteA; &'a [u8]);
2014-12-19 18:43:42 +00:00
2014-05-26 03:38:40 +00:00
impl ToSql for HashMap<String, Option<String>> {
2014-11-04 05:29:16 +00:00
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
2014-03-13 06:50:10 +00:00
match *ty {
Type::Unknown(ref u) if u.name() == "hstore" => {}
_ => return Err(Error::WrongType(ty.clone()))
2014-03-13 06:50:10 +00:00
}
2014-11-20 04:54:32 +00:00
let mut buf = vec![];
2013-12-05 05:20:48 +00:00
2014-11-17 06:54:57 +00:00
try!(buf.write_be_i32(self.len() as i32));
2013-12-05 05:20:48 +00:00
for (key, val) in self.iter() {
2014-11-17 06:54:57 +00:00
try!(buf.write_be_i32(key.len() as i32));
2015-01-28 16:52:33 +00:00
try!(buf.write_all(key.as_bytes()));
2013-12-05 05:20:48 +00:00
match *val {
Some(ref val) => {
2014-11-17 06:54:57 +00:00
try!(buf.write_be_i32(val.len() as i32));
2015-01-28 16:52:33 +00:00
try!(buf.write_all(val.as_bytes()));
2013-12-05 05:20:48 +00:00
}
2014-11-17 06:54:57 +00:00
None => try!(buf.write_be_i32(-1))
2013-12-05 05:20:48 +00:00
}
}
2014-11-20 04:54:32 +00:00
Ok(Some(buf))
2013-12-05 05:20:48 +00:00
}
}
2014-03-13 06:50:10 +00:00
2014-05-26 03:38:40 +00:00
impl ToSql for Option<HashMap<String, Option<String>>> {
2014-11-04 05:29:16 +00:00
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
2014-03-13 06:50:10 +00:00
match *ty {
Type::Unknown(ref u) if u.name() == "hstore" => {}
_ => return Err(Error::WrongType(ty.clone()))
2014-03-13 06:50:10 +00:00
}
match *self {
Some(ref inner) => inner.to_sql(ty),
None => Ok(None)
2014-03-13 06:50:10 +00:00
}
}
}