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;
|
2014-11-20 04:54:32 +00:00
|
|
|
use std::io::{ByRefReader, BufReader};
|
2014-12-14 23:07:48 +00:00
|
|
|
use std::io::util::LimitReader;
|
2014-12-14 19:39:26 +00:00
|
|
|
use std::io::net::ip::IpAddr;
|
2013-08-28 04:36:27 +00:00
|
|
|
|
2014-11-01 23:12:05 +00:00
|
|
|
use Result;
|
2014-11-21 05:47:13 +00:00
|
|
|
use error::Error;
|
2014-12-14 23:07:48 +00:00
|
|
|
use types::range::{Range, RangeBound, BoundSided, BoundType, Normalizable};
|
2014-12-15 00:43:17 +00:00
|
|
|
use types::array::{Array, ArrayBase};
|
2013-10-29 06:55:11 +00:00
|
|
|
|
2014-11-17 17:43:10 +00:00
|
|
|
macro_rules! check_types(
|
|
|
|
($($expected:pat)|+, $actual:ident) => (
|
|
|
|
match $actual {
|
|
|
|
$(&$expected)|+ => {}
|
2014-11-21 05:47:13 +00:00
|
|
|
actual => return Err(::Error::WrongType(actual.clone()))
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! raw_from_impl(
|
|
|
|
($t:ty, $f:ident) => (
|
|
|
|
impl RawFromSql for $t {
|
|
|
|
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<$t> {
|
|
|
|
Ok(try!(raw.$f()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
macro_rules! from_option_impl(
|
|
|
|
($t:ty $(, $a:meta)*) => {
|
2014-11-17 17:43:10 +00:00
|
|
|
$(#[$a])*
|
2014-11-18 03:11:32 +00:00
|
|
|
impl ::types::FromSql for $t {
|
|
|
|
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>) -> Result<$t> {
|
|
|
|
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),
|
2014-11-21 05:47:13 +00:00
|
|
|
Ok(None) => Err(Error::WasNull),
|
2014-11-17 17:43:10 +00:00
|
|
|
Err(err) => Err(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! from_map_impl(
|
|
|
|
($($expected:pat)|+, $t:ty, $blk:expr $(, $a:meta)*) => (
|
|
|
|
$(#[$a])*
|
|
|
|
impl ::types::FromSql for Option<$t> {
|
|
|
|
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>) -> Result<Option<$t>> {
|
|
|
|
check_types!($($expected)|+, ty)
|
|
|
|
match *raw {
|
|
|
|
Some(ref buf) => ($blk)(buf).map(|ok| Some(ok)),
|
|
|
|
None => Ok(None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
from_option_impl!($t $(, $a)*)
|
2014-11-17 17:43:10 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! from_raw_from_impl(
|
|
|
|
($($expected:pat)|+, $t:ty $(, $a:meta)*) => (
|
|
|
|
from_map_impl!($($expected)|+, $t, |buf: &Vec<u8>| {
|
2014-11-18 03:11:32 +00:00
|
|
|
use std::io::BufReader;
|
|
|
|
use types::RawFromSql;
|
|
|
|
|
2014-12-03 05:44:34 +00:00
|
|
|
let mut reader = BufReader::new(&**buf);
|
2014-11-17 17:43:10 +00:00
|
|
|
RawFromSql::raw_from_sql(&mut reader)
|
|
|
|
} $(, $a)*)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! from_array_impl(
|
|
|
|
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
2014-11-18 03:11:32 +00:00
|
|
|
from_map_impl!($($oid)|+, ::types::array::ArrayBase<Option<$t>>, |buf: &Vec<u8>| {
|
|
|
|
use std::io::{BufReader, ByRefReader};
|
|
|
|
use std::io::util::LimitReader;
|
2014-11-25 06:42:49 +00:00
|
|
|
use std::iter::MultiplicativeIterator;
|
2014-11-18 03:11:32 +00:00
|
|
|
use types::{Oid, RawFromSql};
|
|
|
|
use types::array::{ArrayBase, DimensionInfo};
|
2014-11-24 18:12:35 +00:00
|
|
|
use Error;
|
2014-11-18 03:11:32 +00:00
|
|
|
|
2014-12-03 05:44:34 +00:00
|
|
|
let mut rdr = BufReader::new(&**buf);
|
2014-11-17 17:43:10 +00:00
|
|
|
|
|
|
|
let ndim = try!(rdr.read_be_i32()) as uint;
|
|
|
|
let _has_null = try!(rdr.read_be_i32()) == 1;
|
|
|
|
let _element_type: Oid = try!(rdr.read_be_u32());
|
|
|
|
|
|
|
|
let mut dim_info = Vec::with_capacity(ndim);
|
|
|
|
for _ in range(0, ndim) {
|
|
|
|
dim_info.push(DimensionInfo {
|
|
|
|
len: try!(rdr.read_be_i32()) as uint,
|
|
|
|
lower_bound: try!(rdr.read_be_i32()) as int
|
|
|
|
});
|
|
|
|
}
|
2014-11-25 06:42:49 +00:00
|
|
|
let nele = dim_info.iter().map(|info| info.len).product();
|
2014-11-17 17:43:10 +00:00
|
|
|
|
|
|
|
let mut elements = Vec::with_capacity(nele);
|
|
|
|
for _ in range(0, nele) {
|
|
|
|
let len = try!(rdr.read_be_i32());
|
|
|
|
if len < 0 {
|
|
|
|
elements.push(None);
|
|
|
|
} else {
|
|
|
|
let mut limit = LimitReader::new(rdr.by_ref(), len as uint);
|
|
|
|
elements.push(Some(try!(RawFromSql::raw_from_sql(&mut limit))));
|
2014-11-24 18:12:35 +00:00
|
|
|
if limit.limit() != 0 {
|
|
|
|
return Err(Error::BadData);
|
|
|
|
}
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(ArrayBase::from_raw(elements, dim_info))
|
|
|
|
} $(, $a)*)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! raw_to_impl(
|
|
|
|
($t:ty, $f:ident) => (
|
|
|
|
impl RawToSql for $t {
|
|
|
|
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
|
|
|
|
Ok(try!(w.$f(*self)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! to_option_impl(
|
|
|
|
($($oid:pat)|+, $t:ty $(,$a:meta)*) => (
|
|
|
|
$(#[$a])*
|
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>>> {
|
|
|
|
check_types!($($oid)|+, ty)
|
|
|
|
|
|
|
|
match *self {
|
|
|
|
None => Ok(None),
|
|
|
|
Some(ref val) => val.to_sql(ty)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! to_option_impl_lifetime(
|
|
|
|
($($oid:pat)|+, $t:ty) => (
|
|
|
|
impl<'a> ToSql for Option<$t> {
|
|
|
|
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
|
|
|
check_types!($($oid)|+, ty)
|
|
|
|
|
|
|
|
match *self {
|
|
|
|
None => Ok(None),
|
|
|
|
Some(ref val) => val.to_sql(ty)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! to_raw_to_impl(
|
|
|
|
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
|
|
|
$(#[$a])*
|
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>>> {
|
|
|
|
check_types!($($oid)|+, ty)
|
|
|
|
|
2014-11-20 04:54:32 +00:00
|
|
|
let mut writer = vec![];
|
2014-11-17 17:43:10 +00:00
|
|
|
try!(self.raw_to_sql(&mut writer));
|
2014-11-20 04:54:32 +00:00
|
|
|
Ok(Some(writer))
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
to_option_impl!($($oid)|+, $t $(, $a)*)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! to_array_impl(
|
|
|
|
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
|
|
|
$(#[$a])*
|
2014-11-18 03:11:32 +00:00
|
|
|
impl ::types::ToSql for ::types::array::ArrayBase<Option<$t>> {
|
2014-11-17 17:43:10 +00:00
|
|
|
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
2014-12-15 00:43:17 +00:00
|
|
|
check_types!($($oid)|+, ty);
|
|
|
|
Ok(Some(::types::raw_to_array(self, ty)))
|
|
|
|
}
|
|
|
|
}
|
2014-11-18 03:11:32 +00:00
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
to_option_impl!($($oid)|+, ::types::array::ArrayBase<Option<$t>> $(, $a)*)
|
|
|
|
)
|
|
|
|
)
|
2014-11-17 17:43:10 +00:00
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
fn raw_to_array<T>(array: &ArrayBase<Option<T>>, ty: &Type) -> Vec<u8> where T: RawToSql {
|
|
|
|
let mut buf = vec![];
|
2014-11-17 17:43:10 +00:00
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
let _ = buf.write_be_i32(array.dimension_info().len() as i32);
|
|
|
|
let _ = buf.write_be_i32(1);
|
|
|
|
let _ = buf.write_be_u32(ty.member_type().to_oid());
|
2014-11-17 17:43:10 +00:00
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
for info in array.dimension_info().iter() {
|
|
|
|
let _ = buf.write_be_i32(info.len as i32);
|
|
|
|
let _ = buf.write_be_i32(info.lower_bound as i32);
|
|
|
|
}
|
2014-11-17 17:43:10 +00:00
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
for v in array.values() {
|
|
|
|
match *v {
|
|
|
|
Some(ref val) => {
|
|
|
|
let mut inner_buf = vec![];
|
|
|
|
let _ = val.raw_to_sql(&mut inner_buf);
|
|
|
|
let _ = buf.write_be_i32(inner_buf.len() as i32);
|
|
|
|
let _ = buf.write(&*inner_buf);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
let _ = buf.write_be_i32(-1);
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
2014-11-17 17:43:10 +00:00
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
buf
|
|
|
|
}
|
2014-11-17 17:43:10 +00:00
|
|
|
|
2014-09-12 04:40:52 +00:00
|
|
|
pub mod array;
|
2013-10-29 05:35:52 +00:00
|
|
|
pub mod range;
|
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;
|
2013-08-30 05:58:26 +00:00
|
|
|
|
2013-08-30 06:28:46 +00:00
|
|
|
// 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;
|
2014-12-15 00:43:17 +00:00
|
|
|
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;
|
2014-12-14 19:39:26 +00:00
|
|
|
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-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;
|
2013-08-30 06:28:46 +00:00
|
|
|
|
2014-10-10 04:50:40 +00:00
|
|
|
const RANGE_UPPER_UNBOUNDED: i8 = 0b0001_0000;
|
|
|
|
const RANGE_LOWER_UNBOUNDED: i8 = 0b0000_1000;
|
|
|
|
const RANGE_UPPER_INCLUSIVE: i8 = 0b0000_0100;
|
|
|
|
const RANGE_LOWER_INCLUSIVE: i8 = 0b0000_0010;
|
|
|
|
const RANGE_EMPTY: i8 = 0b0000_0001;
|
2013-10-29 06:55:11 +00:00
|
|
|
|
2013-12-08 03:34:48 +00:00
|
|
|
macro_rules! make_postgres_type(
|
2014-03-29 21:33:11 +00:00
|
|
|
($(#[$doc:meta] $oid:ident => $variant:ident $(member $member:ident)*),+) => (
|
2013-12-08 03:34:48 +00:00
|
|
|
/// A Postgres type
|
2014-06-02 02:57:27 +00:00
|
|
|
#[deriving(PartialEq, Eq, Clone, Show)]
|
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
|
2014-11-04 05:29:16 +00:00
|
|
|
Unknown {
|
2013-12-08 03:34:48 +00:00
|
|
|
/// The name of the type
|
2014-11-17 16:56:25 +00:00
|
|
|
name: String,
|
2013-12-08 03:34:48 +00:00
|
|
|
/// The OID of the type
|
2014-11-17 16:56:25 +00:00
|
|
|
oid: Oid
|
2013-12-08 03:34:48 +00:00
|
|
|
}
|
2013-09-05 04:26:43 +00:00
|
|
|
}
|
|
|
|
|
2014-11-04 05:29:16 +00:00
|
|
|
impl Type {
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc(hidden)]
|
2014-11-04 05:29:16 +00:00
|
|
|
pub fn from_oid(oid: Oid) -> Type {
|
2013-12-08 03:34:48 +00:00
|
|
|
match oid {
|
2014-11-04 05:29:16 +00:00
|
|
|
$($oid => Type::$variant,)+
|
2013-12-08 03:34:48 +00:00
|
|
|
// We have to load an empty string now, it'll get filled in later
|
2014-11-04 05:29:16 +00:00
|
|
|
oid => Type::Unknown { name: String::new(), oid: oid }
|
2013-12-08 03:34:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-08 19:44:37 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn to_oid(&self) -> Oid {
|
|
|
|
match *self {
|
2014-11-04 05:29:16 +00:00
|
|
|
$(Type::$variant => $oid,)+
|
|
|
|
Type::Unknown { oid, .. } => oid
|
2013-12-08 19:44:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-04 05:29:16 +00:00
|
|
|
fn member_type(&self) -> Type {
|
2013-12-08 19:44:37 +00:00
|
|
|
match *self {
|
|
|
|
$(
|
2014-11-04 05:29:16 +00:00
|
|
|
$(Type::$variant => Type::$member,)*
|
2013-12-08 19:44:37 +00:00
|
|
|
)+
|
|
|
|
_ => unreachable!()
|
|
|
|
}
|
|
|
|
}
|
2013-09-05 04:26:43 +00:00
|
|
|
}
|
2013-12-08 03:34:48 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
make_postgres_type!(
|
|
|
|
#[doc="BOOL"]
|
2014-11-04 05:29:16 +00:00
|
|
|
BOOLOID => Bool,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="BYTEA"]
|
2014-11-04 05:29:16 +00:00
|
|
|
BYTEAOID => ByteA,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="\"char\""]
|
2014-11-04 05:29:16 +00:00
|
|
|
CHAROID => Char,
|
2014-05-02 23:38:06 +00:00
|
|
|
#[doc="NAME"]
|
2014-11-04 05:29:16 +00:00
|
|
|
NAMEOID => Name,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT8/BIGINT"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT8OID => Int8,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT2/SMALLINT"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT2OID => Int2,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT4/INT"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT4OID => Int4,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="TEXT"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TEXTOID => Text,
|
2014-12-15 00:43:17 +00:00
|
|
|
#[doc="OID"]
|
|
|
|
OIDOID => Oid,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="JSON"]
|
2014-11-04 05:29:16 +00:00
|
|
|
JSONOID => Json,
|
2014-12-14 20:27:02 +00:00
|
|
|
#[doc="CIDR"]
|
|
|
|
CIDROID => Cidr,
|
2013-12-09 00:00:33 +00:00
|
|
|
#[doc="JSON[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
JSONARRAYOID => JsonArray member Json,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="FLOAT4/REAL"]
|
2014-11-04 05:29:16 +00:00
|
|
|
FLOAT4OID => Float4,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="FLOAT8/DOUBLE PRECISION"]
|
2014-11-04 05:29:16 +00:00
|
|
|
FLOAT8OID => Float8,
|
2014-12-14 19:39:26 +00:00
|
|
|
#[doc="INET"]
|
|
|
|
INETOID => Inet,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="BOOL[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
BOOLARRAYOID => BoolArray member Bool,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="BYTEA[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
BYTEAARRAYOID => ByteAArray member ByteA,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="\"char\"[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
CHARARRAYOID => CharArray member Char,
|
2014-05-02 23:38:06 +00:00
|
|
|
#[doc="NAME[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
NAMEARRAYOID => NameArray member Name,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT2[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT2ARRAYOID => Int2Array member Int2,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT4[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT4ARRAYOID => Int4Array member Int4,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="TEXT[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TEXTARRAYOID => TextArray member Text,
|
2013-12-08 19:44:37 +00:00
|
|
|
#[doc="CHAR(n)[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
BPCHARARRAYOID => CharNArray member CharN,
|
2013-12-08 21:58:41 +00:00
|
|
|
#[doc="VARCHAR[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
VARCHARARRAYOID => VarcharArray member Varchar,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT8[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT8ARRAYOID => Int8Array member Int8,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="FLOAT4[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
FLOAT4ARRAYOID => Float4Array member Float4,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="FLOAT8[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
FLAOT8ARRAYOID => Float8Array member Float8,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="TIMESTAMP"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TIMESTAMPOID => Timestamp,
|
2013-12-08 22:04:26 +00:00
|
|
|
#[doc="TIMESTAMP[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TIMESTAMPARRAYOID => TimestampArray member Timestamp,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="TIMESTAMP WITH TIME ZONE"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TIMESTAMPZOID => TimestampTZ,
|
2013-12-08 22:08:35 +00:00
|
|
|
#[doc="TIMESTAMP WITH TIME ZONE[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TIMESTAMPZARRAYOID => TimestampTZArray member TimestampTZ,
|
2014-11-06 15:53:16 +00:00
|
|
|
#[doc="UUID"]
|
|
|
|
UUIDOID => Uuid,
|
|
|
|
#[doc="UUID[]"]
|
|
|
|
UUIDARRAYOID => UuidArray member Uuid,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="CHAR(n)/CHARACTER(n)"]
|
2014-11-04 05:29:16 +00:00
|
|
|
BPCHAROID => CharN,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="VARCHAR/CHARACTER VARYING"]
|
2014-11-04 05:29:16 +00:00
|
|
|
VARCHAROID => Varchar,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT4RANGE"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT4RANGEOID => Int4Range,
|
2013-12-08 22:37:31 +00:00
|
|
|
#[doc="INT4RANGE[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT4RANGEARRAYOID => Int4RangeArray member Int4Range,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="TSRANGE"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TSRANGEOID => TsRange,
|
2013-12-08 23:02:38 +00:00
|
|
|
#[doc="TSRANGE[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TSRANGEARRAYOID => TsRangeArray member TsRange,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="TSTZRANGE"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TSTZRANGEOID => TstzRange,
|
2013-12-08 23:02:38 +00:00
|
|
|
#[doc="TSTZRANGE[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
TSTZRANGEARRAYOID => TstzRangeArray member TstzRange,
|
2013-12-08 23:07:11 +00:00
|
|
|
#[doc="INT8RANGE"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT8RANGEOID => Int8Range,
|
2013-12-08 23:07:11 +00:00
|
|
|
#[doc="INT8RANGE[]"]
|
2014-11-04 05:29:16 +00:00
|
|
|
INT8RANGEARRAYOID => Int8RangeArray member Int8Range
|
2013-12-08 03:34:48 +00:00
|
|
|
)
|
2013-09-02 19:42:24 +00:00
|
|
|
|
2013-09-30 05:22:10 +00:00
|
|
|
/// A trait for types that can be created from a Postgres value
|
2013-08-28 04:36:27 +00:00
|
|
|
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-11-04 05:29:16 +00:00
|
|
|
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>) -> Result<Self>;
|
2013-08-28 04:36:27 +00:00
|
|
|
}
|
|
|
|
|
2014-01-24 07:25:57 +00:00
|
|
|
#[doc(hidden)]
|
2013-10-31 02:55:25 +00:00
|
|
|
trait RawFromSql {
|
2014-11-01 23:12:05 +00:00
|
|
|
fn raw_from_sql<R: Reader>(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 {
|
2014-11-01 23:12:05 +00:00
|
|
|
fn raw_from_sql<R: Reader>(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> {
|
2014-11-17 17:43:10 +00:00
|
|
|
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<Vec<u8>> {
|
|
|
|
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>(raw: &mut R) -> Result<String> {
|
2014-11-21 05:47:13 +00:00
|
|
|
String::from_utf8(try!(raw.read_to_end())).map_err(|_| Error::BadData)
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
raw_from_impl!(i8, read_i8)
|
|
|
|
raw_from_impl!(i16, read_be_i16)
|
|
|
|
raw_from_impl!(i32, read_be_i32)
|
2014-12-15 00:43:17 +00:00
|
|
|
raw_from_impl!(u32, read_be_u32)
|
2014-11-17 17:43:10 +00:00
|
|
|
raw_from_impl!(i64, read_be_i64)
|
|
|
|
raw_from_impl!(f32, read_be_f32)
|
|
|
|
raw_from_impl!(f64, read_be_f64)
|
|
|
|
|
2014-11-04 05:29:16 +00:00
|
|
|
impl RawFromSql for json::Json {
|
|
|
|
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<json::Json> {
|
2014-11-21 05:47:13 +00:00
|
|
|
json::from_reader(raw).map_err(|_| Error::BadData)
|
2013-12-09 00:00:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-14 19:39:26 +00:00
|
|
|
impl RawFromSql for IpAddr {
|
|
|
|
fn raw_from_sql<R: Reader>(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());
|
2014-12-14 19:50:14 +00:00
|
|
|
if nb > 16 {
|
|
|
|
return Err(Error::BadData);
|
|
|
|
}
|
2014-12-14 23:07:48 +00:00
|
|
|
let mut buf = [0u8, ..16];
|
|
|
|
try!(raw.read_at_least(nb as uint, &mut buf));
|
|
|
|
let mut buf: &[u8] = &buf;
|
2014-12-14 19:39:26 +00:00
|
|
|
|
|
|
|
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),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-14 23:07:48 +00:00
|
|
|
impl<T> RawFromSql for Range<T> where T: PartialOrd+Normalizable+RawFromSql {
|
|
|
|
fn raw_from_sql<R: Reader>(rdr: &mut R) -> Result<Range<T>> {
|
|
|
|
let t = try!(rdr.read_i8());
|
|
|
|
|
|
|
|
if t & RANGE_EMPTY != 0 {
|
|
|
|
return Ok(Range::empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn make_bound<S, T, R>(rdr: &mut R, tag: i8, bound_flag: i8, inclusive_flag: i8)
|
|
|
|
-> Result<Option<RangeBound<S, T>>>
|
|
|
|
where S: BoundSided, T: PartialOrd+Normalizable+RawFromSql, R: Reader {
|
|
|
|
match tag & bound_flag {
|
|
|
|
0 => {
|
|
|
|
let type_ = match tag & inclusive_flag {
|
|
|
|
0 => BoundType::Exclusive,
|
|
|
|
_ => BoundType::Inclusive,
|
|
|
|
};
|
|
|
|
let len = try!(rdr.read_be_i32()) as uint;
|
|
|
|
let mut limit = LimitReader::new(rdr.by_ref(), len);
|
|
|
|
let bound = try!(RawFromSql::raw_from_sql(&mut limit));
|
|
|
|
if limit.limit() != 0 {
|
|
|
|
return Err(Error::BadData);
|
|
|
|
}
|
|
|
|
Ok(Some(RangeBound::new(bound, type_)))
|
|
|
|
}
|
|
|
|
_ => Ok(None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let lower = try!(make_bound(rdr, t, RANGE_LOWER_UNBOUNDED, RANGE_LOWER_INCLUSIVE));
|
|
|
|
let upper = try!(make_bound(rdr, t, RANGE_UPPER_UNBOUNDED, RANGE_UPPER_INCLUSIVE));
|
|
|
|
Ok(Range::new(lower, upper))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-15 00:43:17 +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, json::Json)
|
|
|
|
from_raw_from_impl!(Type::Inet | Type::Cidr, IpAddr)
|
|
|
|
|
|
|
|
from_raw_from_impl!(Type::Int4Range, Range<i32>)
|
|
|
|
from_raw_from_impl!(Type::Int8Range, Range<i64>)
|
|
|
|
|
|
|
|
from_array_impl!(Type::BoolArray, bool)
|
|
|
|
from_array_impl!(Type::ByteAArray, Vec<u8>)
|
|
|
|
from_array_impl!(Type::CharArray, i8)
|
|
|
|
from_array_impl!(Type::Int2Array, i16)
|
|
|
|
from_array_impl!(Type::Int4Array, i32)
|
|
|
|
from_array_impl!(Type::TextArray | Type::CharNArray | Type::VarcharArray | Type::NameArray, String)
|
|
|
|
from_array_impl!(Type::Int8Array, i64)
|
|
|
|
from_array_impl!(Type::JsonArray, json::Json)
|
|
|
|
from_array_impl!(Type::Float4Array, f32)
|
|
|
|
from_array_impl!(Type::Float8Array, f64)
|
|
|
|
from_array_impl!(Type::Int4RangeArray, Range<i32>)
|
|
|
|
from_array_impl!(Type::Int8RangeArray, Range<i64>)
|
|
|
|
|
|
|
|
impl FromSql for Option<String> {
|
|
|
|
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>) -> Result<Option<String>> {
|
|
|
|
match *ty {
|
|
|
|
Type::Varchar | Type::Text | Type::CharN | Type::Name => {}
|
|
|
|
Type::Unknown { ref name, .. } if "citext" == *name => {}
|
|
|
|
_ => return Err(Error::WrongType(ty.clone()))
|
|
|
|
}
|
|
|
|
|
|
|
|
match *raw {
|
|
|
|
Some(ref buf) => {
|
|
|
|
let mut rdr = &**buf;
|
|
|
|
Ok(Some(try!(RawFromSql::raw_from_sql(&mut rdr))))
|
|
|
|
}
|
|
|
|
None => Ok(None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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-11-04 05:29:16 +00:00
|
|
|
fn from_sql(ty: &Type, raw: &Option<Vec<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 {
|
2014-12-06 21:30:37 +00:00
|
|
|
Type::Unknown { ref name, .. } if "hstore" == *name => {}
|
2014-11-21 05:47:13 +00:00
|
|
|
_ => return Err(Error::WrongType(ty.clone()))
|
2014-03-13 06:50:10 +00:00
|
|
|
}
|
|
|
|
|
2014-03-28 05:43:10 +00:00
|
|
|
match *raw {
|
|
|
|
Some(ref buf) => {
|
2014-12-03 05:44:34 +00:00
|
|
|
let mut rdr = BufReader::new(&**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 uint));
|
2014-07-07 04:34:27 +00:00
|
|
|
let key = match String::from_utf8(key) {
|
|
|
|
Ok(key) => key,
|
2014-11-21 05:47:13 +00:00
|
|
|
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 {
|
2014-11-17 06:54:57 +00:00
|
|
|
let val = try!(rdr.read_exact(val_len as uint));
|
2014-07-07 04:34:27 +00:00
|
|
|
match String::from_utf8(val) {
|
|
|
|
Ok(val) => Some(val),
|
2014-11-21 05:47:13 +00:00
|
|
|
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-15 00:43:17 +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
|
2014-10-26 03:24:08 +00:00
|
|
|
pub trait ToSql {
|
2014-09-30 06:41:13 +00:00
|
|
|
/// 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>>>;
|
2013-08-28 04:36:27 +00:00
|
|
|
}
|
|
|
|
|
2014-01-24 07:25:57 +00:00
|
|
|
#[doc(hidden)]
|
2014-10-26 03:24:08 +00:00
|
|
|
trait RawToSql {
|
2014-11-01 23:12:05 +00:00
|
|
|
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()>;
|
2013-10-31 02:55:25 +00:00
|
|
|
}
|
|
|
|
|
2013-12-07 23:39:44 +00:00
|
|
|
impl RawToSql for bool {
|
2014-11-01 23:12:05 +00:00
|
|
|
fn raw_to_sql<W: Writer>(&self, 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> {
|
2014-11-01 23:12:05 +00:00
|
|
|
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
|
2014-12-03 05:44:34 +00:00
|
|
|
Ok(try!(w.write(&**self)))
|
2014-03-15 06:01:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-26 03:38:40 +00:00
|
|
|
impl RawToSql for String {
|
2014-11-01 23:12:05 +00:00
|
|
|
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
|
2014-11-17 06:54:57 +00:00
|
|
|
Ok(try!(w.write(self.as_bytes())))
|
2013-12-08 03:13:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-08 02:49:55 +00:00
|
|
|
raw_to_impl!(i8, write_i8)
|
2013-12-08 02:58:40 +00:00
|
|
|
raw_to_impl!(i16, write_be_i16)
|
2013-10-31 02:55:25 +00:00
|
|
|
raw_to_impl!(i32, write_be_i32)
|
2014-12-15 00:43:17 +00:00
|
|
|
raw_to_impl!(u32, write_be_u32)
|
2013-10-31 02:55:25 +00:00
|
|
|
raw_to_impl!(i64, write_be_i64)
|
2013-12-06 05:51:09 +00:00
|
|
|
raw_to_impl!(f32, write_be_f32)
|
2013-12-06 05:58:22 +00:00
|
|
|
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 {
|
2014-11-01 23:12:05 +00:00
|
|
|
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> Result<()> {
|
2014-11-17 06:54:57 +00:00
|
|
|
Ok(try!(self.to_writer(raw as &mut Writer)))
|
2013-12-09 00:00:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-14 19:39:26 +00:00
|
|
|
impl RawToSql for IpAddr {
|
|
|
|
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> Result<()> {
|
|
|
|
match *self {
|
|
|
|
IpAddr::Ipv4Addr(a, b, c, d) => {
|
2014-12-18 17:07:15 +00:00
|
|
|
try!(raw.write(&[2, // family
|
|
|
|
32, // bits
|
|
|
|
0, // is_cidr
|
|
|
|
4, // nb
|
|
|
|
a, b, c, d // addr
|
|
|
|
]));
|
2014-12-14 19:39:26 +00:00
|
|
|
}
|
|
|
|
IpAddr::Ipv6Addr(a, b, c, d, e, f, g, h) => {
|
2014-12-18 17:07:15 +00:00
|
|
|
try!(raw.write(&[3, // family
|
|
|
|
128, // bits
|
|
|
|
0, // is_cidr
|
|
|
|
16, // nb
|
|
|
|
]));
|
2014-12-14 19:39:26 +00:00
|
|
|
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(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-14 23:07:48 +00:00
|
|
|
impl<T> RawToSql for Range<T> where T: PartialOrd+Normalizable+RawToSql {
|
|
|
|
fn raw_to_sql<W: Writer>(&self, buf: &mut W) -> Result<()> {
|
|
|
|
let mut tag = 0;
|
|
|
|
if self.is_empty() {
|
|
|
|
tag |= RANGE_EMPTY;
|
|
|
|
} else {
|
|
|
|
fn make_tag<S, T>(bound: Option<&RangeBound<S, T>>, unbounded_tag: i8,
|
|
|
|
inclusive_tag: i8) -> i8 where S: BoundSided {
|
|
|
|
match bound {
|
|
|
|
None => unbounded_tag,
|
|
|
|
Some(&RangeBound { type_: BoundType::Inclusive, .. }) => inclusive_tag,
|
|
|
|
_ => 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tag |= make_tag(self.lower(), RANGE_LOWER_UNBOUNDED, RANGE_LOWER_INCLUSIVE);
|
|
|
|
tag |= make_tag(self.upper(), RANGE_UPPER_UNBOUNDED, RANGE_UPPER_INCLUSIVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
try!(buf.write_i8(tag));
|
|
|
|
|
|
|
|
fn write_value<S, T, W>(buf: &mut W, v: Option<&RangeBound<S, T>>) -> Result<()>
|
|
|
|
where S: BoundSided, T: RawToSql, W: Writer {
|
|
|
|
if let Some(bound) = v {
|
|
|
|
let mut inner_buf = vec![];
|
|
|
|
try!(bound.value.raw_to_sql(&mut inner_buf));
|
|
|
|
try!(buf.write_be_u32(inner_buf.len() as u32));
|
|
|
|
try!(buf.write(&*inner_buf));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
try!(write_value(buf, self.lower()));
|
|
|
|
try!(write_value(buf, self.upper()));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
to_raw_to_impl!(Type::Bool, bool)
|
|
|
|
to_raw_to_impl!(Type::ByteA, Vec<u8>)
|
|
|
|
to_raw_to_impl!(Type::Json, json::Json)
|
|
|
|
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)
|
|
|
|
to_raw_to_impl!(Type::Int4Range, Range<i32>)
|
|
|
|
to_raw_to_impl!(Type::Int8Range, Range<i64>)
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
2014-12-14 23:07:48 +00:00
|
|
|
|
2014-10-26 03:24:08 +00:00
|
|
|
impl<'a> ToSql for &'a str {
|
2014-11-04 05:29:16 +00:00
|
|
|
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
2014-12-15 00:43:17 +00:00
|
|
|
match *ty {
|
|
|
|
Type::Varchar | Type::Text | Type::CharN | Type::Name => {}
|
|
|
|
Type::Unknown { ref name, .. } if *name == "citext" => {}
|
|
|
|
_ => return Err(Error::WrongType(ty.clone()))
|
|
|
|
}
|
2014-09-30 06:41:13 +00:00
|
|
|
Ok(Some(self.as_bytes().to_vec()))
|
2013-08-28 04:36:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
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 name, .. } if *name == "citext" => {}
|
|
|
|
_ => return Err(Error::WrongType(ty.clone()))
|
|
|
|
}
|
|
|
|
match *self {
|
|
|
|
Some(ref val) => val.to_sql(ty),
|
|
|
|
None => Ok(None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-02 19:42:24 +00:00
|
|
|
|
2014-10-26 03:24:08 +00:00
|
|
|
impl<'a> ToSql for &'a [u8] {
|
2014-11-04 05:29:16 +00:00
|
|
|
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
2014-12-15 00:43:17 +00:00
|
|
|
check_types!(Type::ByteA, ty)
|
2014-09-30 06:41:13 +00:00
|
|
|
Ok(Some(self.to_vec()))
|
2013-09-02 19:42:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-15 00:43:17 +00:00
|
|
|
to_option_impl_lifetime!(Type::ByteA, &'a [u8])
|
|
|
|
|
|
|
|
to_array_impl!(Type::BoolArray, bool)
|
|
|
|
to_array_impl!(Type::ByteAArray, Vec<u8>)
|
|
|
|
to_array_impl!(Type::CharArray, i8)
|
|
|
|
to_array_impl!(Type::Int2Array, i16)
|
|
|
|
to_array_impl!(Type::Int4Array, i32)
|
|
|
|
to_array_impl!(Type::Int8Array, i64)
|
|
|
|
to_array_impl!(Type::TextArray | Type::CharNArray | Type::VarcharArray | Type::NameArray, String)
|
|
|
|
to_array_impl!(Type::Float4Array, f32)
|
|
|
|
to_array_impl!(Type::Float8Array, f64)
|
|
|
|
to_array_impl!(Type::Int4RangeArray, Range<i32>)
|
|
|
|
to_array_impl!(Type::Int8RangeArray, Range<i64>)
|
|
|
|
to_array_impl!(Type::JsonArray, json::Json)
|
2013-12-06 05:58:22 +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 {
|
2014-12-06 21:30:37 +00:00
|
|
|
Type::Unknown { ref name, .. } if "hstore" == *name => {}
|
2014-11-21 05:47:13 +00:00
|
|
|
_ => 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));
|
|
|
|
try!(buf.write(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));
|
|
|
|
try!(buf.write(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 {
|
2014-12-06 21:30:37 +00:00
|
|
|
Type::Unknown { ref name, .. } if "hstore" == *name => {}
|
2014-11-21 05:47:13 +00:00
|
|
|
_ => return Err(Error::WrongType(ty.clone()))
|
2014-03-13 06:50:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
match *self {
|
|
|
|
Some(ref inner) => inner.to_sql(ty),
|
2014-09-30 06:41:13 +00:00
|
|
|
None => Ok(None)
|
2014-03-13 06:50:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|