rust-postgres/src/types/mod.rs

829 lines
26 KiB
Rust
Raw Normal View History

2013-10-20 21:34:50 +00:00
//! Traits dealing with Postgres data types
2014-03-29 21:33:11 +00:00
#![macro_escape]
2013-10-20 21:34:50 +00:00
2014-02-24 06:32:14 +00:00
use collections::HashMap;
use uuid::Uuid;
2014-02-26 08:40:57 +00:00
use serialize::json;
use serialize::json::Json;
2014-01-18 05:45:59 +00:00
use std::io::{MemWriter, BufReader};
2013-12-15 20:42:07 +00:00
use std::io::util::LimitReader;
2014-02-24 06:32:14 +00:00
use time::Timespec;
2014-04-26 22:07:40 +00:00
use PostgresResult;
use error::{PgWrongType, PgStreamError, PgWasNull};
2014-03-28 05:43:10 +00:00
use types::array::{Array, ArrayBase, DimensionInfo};
use types::range::{RangeBound, Inclusive, Exclusive, Range};
2013-12-02 05:09:31 +00:00
pub mod array;
2013-10-29 05:35:52 +00:00
pub mod range;
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
static BOOLOID: Oid = 16;
static BYTEAOID: Oid = 17;
2013-09-02 22:14:22 +00:00
static CHAROID: Oid = 18;
static NAMEOID: Oid = 19;
static INT8OID: Oid = 20;
static INT2OID: Oid = 21;
static INT4OID: Oid = 23;
2013-09-02 20:07:57 +00:00
static TEXTOID: Oid = 25;
2013-09-02 20:54:02 +00:00
static JSONOID: Oid = 114;
2013-12-09 00:00:33 +00:00
static JSONARRAYOID: Oid = 199;
static FLOAT4OID: Oid = 700;
static FLOAT8OID: Oid = 701;
2013-12-07 23:39:44 +00:00
static BOOLARRAYOID: Oid = 1000;
static BYTEAARRAYOID: Oid = 1001;
2013-12-08 02:49:55 +00:00
static CHARARRAYOID: Oid = 1002;
static NAMEARRAYOID: Oid = 1003;
2013-12-08 02:58:40 +00:00
static INT2ARRAYOID: Oid = 1005;
2013-12-02 05:09:31 +00:00
static INT4ARRAYOID: Oid = 1007;
2013-12-08 03:13:21 +00:00
static TEXTARRAYOID: Oid = 1009;
2013-12-08 19:44:37 +00:00
static BPCHARARRAYOID: Oid = 1014;
2013-12-08 21:58:41 +00:00
static VARCHARARRAYOID: Oid = 1015;
2013-12-04 06:32:54 +00:00
static INT8ARRAYOID: Oid = 1016;
2013-12-06 05:51:09 +00:00
static FLOAT4ARRAYOID: Oid = 1021;
2013-12-06 05:58:22 +00:00
static FLAOT8ARRAYOID: Oid = 1022;
2013-09-02 21:52:23 +00:00
static BPCHAROID: Oid = 1042;
2013-09-02 17:27:09 +00:00
static VARCHAROID: Oid = 1043;
2013-09-09 04:33:41 +00:00
static TIMESTAMPOID: Oid = 1114;
2013-12-08 22:04:26 +00:00
static TIMESTAMPARRAYOID: Oid = 1115;
2013-09-09 04:33:41 +00:00
static TIMESTAMPZOID: Oid = 1184;
2013-12-08 22:08:35 +00:00
static TIMESTAMPZARRAYOID: Oid = 1185;
2013-09-02 20:54:02 +00:00
static UUIDOID: Oid = 2950;
2013-12-08 22:16:37 +00:00
static UUIDARRAYOID: Oid = 2951;
static INT4RANGEOID: Oid = 3904;
2013-12-08 22:37:31 +00:00
static INT4RANGEARRAYOID: Oid = 3905;
2013-10-31 02:55:25 +00:00
static TSRANGEOID: Oid = 3908;
2013-12-08 23:02:38 +00:00
static TSRANGEARRAYOID: Oid = 3909;
2013-10-31 02:55:25 +00:00
static TSTZRANGEOID: Oid = 3910;
2013-12-08 23:02:38 +00:00
static TSTZRANGEARRAYOID: Oid = 3911;
static INT8RANGEOID: Oid = 3926;
2013-12-08 23:07:11 +00:00
static INT8RANGEARRAYOID: Oid = 3927;
2013-09-08 20:27:15 +00:00
static USEC_PER_SEC: i64 = 1_000_000;
static NSEC_PER_USEC: i64 = 1_000;
// Number of seconds from 1970-01-01 to 2000-01-01
static TIME_SEC_CONVERSION: i64 = 946684800;
2013-10-31 02:55:25 +00:00
static RANGE_UPPER_UNBOUNDED: i8 = 0b0001_0000;
static RANGE_LOWER_UNBOUNDED: i8 = 0b0000_1000;
static RANGE_UPPER_INCLUSIVE: i8 = 0b0000_0100;
static RANGE_LOWER_INCLUSIVE: i8 = 0b0000_0010;
2013-10-31 07:04:45 +00:00
static RANGE_EMPTY: i8 = 0b0000_0001;
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-03-28 05:43:10 +00:00
#[deriving(Eq, Clone, Show)]
2013-12-08 03:34:48 +00:00
pub enum PostgresType {
$(
2014-03-29 21:33:11 +00:00
#[$doc]
2013-12-08 03:34:48 +00:00
$variant,
)+
/// An unknown type
PgUnknownType {
/// The name of the type
2014-05-16 02:27:19 +00:00
pub name: StrBuf,
2013-12-08 03:34:48 +00:00
/// The OID of the type
pub oid: Oid
2013-12-08 03:34:48 +00:00
}
}
2013-12-08 03:34:48 +00:00
impl PostgresType {
#[doc(hidden)]
pub fn from_oid(oid: Oid) -> PostgresType {
match oid {
$($oid => $variant,)+
// We have to load an empty string now, it'll get filled in later
2014-05-25 03:42:07 +00:00
oid => PgUnknownType { name: "".to_owned(), 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 {
$($variant => $oid,)+
PgUnknownType { oid, .. } => oid
}
}
fn member_type(&self) -> PostgresType {
match *self {
$(
$($variant => $member,)*
)+
_ => unreachable!()
}
}
2013-12-08 03:34:48 +00:00
/// Returns the wire format needed for the value of `self`.
pub fn result_format(&self) -> Format {
match *self {
2014-05-16 02:27:19 +00:00
PgUnknownType { name: ref name, .. }
if "hstore" == name.as_slice() => Binary,
2013-12-08 03:34:48 +00:00
PgUnknownType { .. } => Text,
_ => Binary
}
}
}
2013-12-08 03:34:48 +00:00
)
)
make_postgres_type!(
#[doc="BOOL"]
2013-12-08 21:46:17 +00:00
BOOLOID => PgBool,
2013-12-08 03:34:48 +00:00
#[doc="BYTEA"]
2013-12-08 21:46:17 +00:00
BYTEAOID => PgByteA,
2013-12-08 03:34:48 +00:00
#[doc="\"char\""]
2013-12-08 21:46:17 +00:00
CHAROID => PgChar,
#[doc="NAME"]
NAMEOID => PgName,
2013-12-08 03:34:48 +00:00
#[doc="INT8/BIGINT"]
2013-12-08 21:46:17 +00:00
INT8OID => PgInt8,
2013-12-08 03:34:48 +00:00
#[doc="INT2/SMALLINT"]
2013-12-08 21:46:17 +00:00
INT2OID => PgInt2,
2013-12-08 03:34:48 +00:00
#[doc="INT4/INT"]
2013-12-08 21:46:17 +00:00
INT4OID => PgInt4,
2013-12-08 03:34:48 +00:00
#[doc="TEXT"]
2013-12-08 21:46:17 +00:00
TEXTOID => PgText,
2013-12-08 03:34:48 +00:00
#[doc="JSON"]
2013-12-08 21:46:17 +00:00
JSONOID => PgJson,
2013-12-09 00:00:33 +00:00
#[doc="JSON[]"]
JSONARRAYOID => PgJsonArray member PgJson,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT4/REAL"]
2013-12-08 21:46:17 +00:00
FLOAT4OID => PgFloat4,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT8/DOUBLE PRECISION"]
2013-12-08 21:46:17 +00:00
FLOAT8OID => PgFloat8,
2013-12-08 03:34:48 +00:00
#[doc="BOOL[]"]
2013-12-08 21:46:17 +00:00
BOOLARRAYOID => PgBoolArray member PgBool,
2013-12-08 03:34:48 +00:00
#[doc="BYTEA[]"]
2013-12-08 21:46:17 +00:00
BYTEAARRAYOID => PgByteAArray member PgByteA,
2013-12-08 03:34:48 +00:00
#[doc="\"char\"[]"]
2013-12-08 21:46:17 +00:00
CHARARRAYOID => PgCharArray member PgChar,
#[doc="NAME[]"]
NAMEARRAYOID => PgNameArray member PgName,
2013-12-08 03:34:48 +00:00
#[doc="INT2[]"]
2013-12-08 21:46:17 +00:00
INT2ARRAYOID => PgInt2Array member PgInt2,
2013-12-08 03:34:48 +00:00
#[doc="INT4[]"]
2013-12-08 21:46:17 +00:00
INT4ARRAYOID => PgInt4Array member PgInt4,
2013-12-08 03:34:48 +00:00
#[doc="TEXT[]"]
2013-12-08 21:46:17 +00:00
TEXTARRAYOID => PgTextArray member PgText,
2013-12-08 19:44:37 +00:00
#[doc="CHAR(n)[]"]
2013-12-08 21:46:17 +00:00
BPCHARARRAYOID => PgCharNArray member PgCharN,
2013-12-08 21:58:41 +00:00
#[doc="VARCHAR[]"]
VARCHARARRAYOID => PgVarcharArray member PgVarchar,
2013-12-08 03:34:48 +00:00
#[doc="INT8[]"]
2013-12-08 21:46:17 +00:00
INT8ARRAYOID => PgInt8Array member PgInt8,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT4[]"]
2013-12-08 21:46:17 +00:00
FLOAT4ARRAYOID => PgFloat4Array member PgFloat4,
2013-12-08 03:34:48 +00:00
#[doc="FLOAT8[]"]
2013-12-08 21:46:17 +00:00
FLAOT8ARRAYOID => PgFloat8Array member PgFloat8,
2013-12-08 03:34:48 +00:00
#[doc="TIMESTAMP"]
2013-12-08 21:46:17 +00:00
TIMESTAMPOID => PgTimestamp,
2013-12-08 22:04:26 +00:00
#[doc="TIMESTAMP[]"]
TIMESTAMPARRAYOID => PgTimestampArray member PgTimestamp,
2013-12-08 03:34:48 +00:00
#[doc="TIMESTAMP WITH TIME ZONE"]
2013-12-08 22:08:35 +00:00
TIMESTAMPZOID => PgTimestampTZ,
#[doc="TIMESTAMP WITH TIME ZONE[]"]
TIMESTAMPZARRAYOID => PgTimestampTZArray member PgTimestampTZ,
2013-12-08 03:34:48 +00:00
#[doc="CHAR(n)/CHARACTER(n)"]
2013-12-08 21:46:17 +00:00
BPCHAROID => PgCharN,
2013-12-08 03:34:48 +00:00
#[doc="VARCHAR/CHARACTER VARYING"]
2013-12-08 21:46:17 +00:00
VARCHAROID => PgVarchar,
2013-12-08 03:34:48 +00:00
#[doc="UUID"]
2013-12-08 21:46:17 +00:00
UUIDOID => PgUuid,
2013-12-08 22:16:37 +00:00
#[doc="UUID[]"]
UUIDARRAYOID => PgUuidArray member PgUuid,
2013-12-08 03:34:48 +00:00
#[doc="INT4RANGE"]
2013-12-08 21:46:17 +00:00
INT4RANGEOID => PgInt4Range,
2013-12-08 22:37:31 +00:00
#[doc="INT4RANGE[]"]
INT4RANGEARRAYOID => PgInt4RangeArray member PgInt4Range,
2013-12-08 03:34:48 +00:00
#[doc="TSRANGE"]
2013-12-08 21:46:17 +00:00
TSRANGEOID => PgTsRange,
2013-12-08 23:02:38 +00:00
#[doc="TSRANGE[]"]
TSRANGEARRAYOID => PgTsRangeArray member PgTsRange,
2013-12-08 03:34:48 +00:00
#[doc="TSTZRANGE"]
2013-12-08 23:02:38 +00:00
TSTZRANGEOID => PgTstzRange,
#[doc="TSTZRANGE[]"]
2013-12-08 23:07:11 +00:00
TSTZRANGEARRAYOID => PgTstzRangeArray member PgTstzRange,
#[doc="INT8RANGE"]
INT8RANGEOID => PgInt8Range,
#[doc="INT8RANGE[]"]
INT8RANGEARRAYOID => PgInt8RangeArray member PgInt8Range
2013-12-08 03:34:48 +00:00
)
2013-09-30 02:47:30 +00:00
/// The wire format of a Postgres value
pub enum Format {
/// A user-readable string format
Text = 0,
/// A machine-readable binary format
Binary = 1
}
2013-09-05 04:30:20 +00:00
macro_rules! check_types(
($($expected:pat)|+, $actual:ident) => (
2013-09-02 20:07:57 +00:00
match $actual {
2014-03-28 05:43:10 +00:00
$(&$expected)|+ => {}
actual => return Err(PgWrongType(actual.clone()))
}
)
)
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-04-08 03:02:05 +00:00
fn from_sql(ty: &PostgresType, raw: &Option<Vec<u8>>)
2014-04-26 22:07:40 +00:00
-> PostgresResult<Self>;
}
#[doc(hidden)]
2013-10-31 02:55:25 +00:00
trait RawFromSql {
2014-04-26 22:07:40 +00:00
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<Self>;
2013-10-31 02:55:25 +00:00
}
macro_rules! raw_from_impl(
($t:ty, $f:ident) => (
impl RawFromSql for $t {
2014-04-26 22:07:40 +00:00
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<$t> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(raw.$f()))
2013-10-31 02:55:25 +00:00
}
}
)
)
2013-12-07 23:39:44 +00:00
impl RawFromSql for bool {
2014-04-26 22:07:40 +00:00
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<bool> {
2014-03-28 05:43:10 +00:00
Ok((try_pg!(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-04-26 22:07:40 +00:00
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<Vec<u8>> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(raw.read_to_end()))
2013-12-08 02:38:53 +00:00
}
}
2014-05-12 04:52:59 +00:00
impl RawFromSql for StrBuf {
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<StrBuf> {
Ok(StrBuf::from_utf8(try_pg!(raw.read_to_end())).unwrap())
2013-12-08 03:13:21 +00:00
}
}
2013-12-08 02:49:55 +00:00
raw_from_impl!(i8, read_i8)
2013-12-08 02:58:40 +00:00
raw_from_impl!(i16, read_be_i16)
2013-10-31 02:55:25 +00:00
raw_from_impl!(i32, read_be_i32)
raw_from_impl!(i64, read_be_i64)
2013-12-06 05:51:09 +00:00
raw_from_impl!(f32, read_be_f32)
2013-12-06 05:58:22 +00:00
raw_from_impl!(f64, read_be_f64)
2013-10-31 02:55:25 +00:00
impl RawFromSql for Timespec {
2014-04-26 22:07:40 +00:00
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<Timespec> {
2014-03-28 05:43:10 +00:00
let t = try_pg!(raw.read_be_i64());
2013-10-31 02:55:25 +00:00
let mut sec = t / USEC_PER_SEC + TIME_SEC_CONVERSION;
let mut usec = t % USEC_PER_SEC;
if usec < 0 {
sec -= 1;
usec = USEC_PER_SEC + usec;
}
2014-03-28 05:43:10 +00:00
Ok(Timespec::new(sec, (usec * NSEC_PER_USEC) as i32))
2013-10-31 02:55:25 +00:00
}
}
2013-12-08 22:16:37 +00:00
impl RawFromSql for Uuid {
2014-04-26 22:07:40 +00:00
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<Uuid> {
2014-04-08 03:02:05 +00:00
Ok(Uuid::from_bytes(try_pg!(raw.read_to_end()).as_slice()).unwrap())
2013-12-08 22:16:37 +00:00
}
}
2013-12-08 22:37:31 +00:00
macro_rules! from_range_impl(
2014-04-23 06:02:56 +00:00
($t:ty) => (
2013-12-08 22:37:31 +00:00
impl RawFromSql for Range<$t> {
2014-03-28 05:43:10 +00:00
fn raw_from_sql<R: Reader>(rdr: &mut R)
2014-04-26 22:07:40 +00:00
-> PostgresResult<Range<$t>> {
2014-03-28 05:43:10 +00:00
let t = try_pg!(rdr.read_i8());
2013-12-08 22:37:31 +00:00
if t & RANGE_EMPTY != 0 {
2014-03-28 05:43:10 +00:00
Ok(Range::empty())
2013-12-08 22:37:31 +00:00
} else {
let lower = match t & RANGE_LOWER_UNBOUNDED {
0 => {
let type_ = match t & RANGE_LOWER_INCLUSIVE {
0 => Exclusive,
_ => Inclusive
};
2014-03-28 05:43:10 +00:00
let len = try_pg!(rdr.read_be_i32()) as uint;
2014-02-15 21:44:48 +00:00
let mut limit = LimitReader::new(rdr.by_ref(), len);
2014-04-26 22:07:40 +00:00
let lower = try!(RawFromSql::raw_from_sql(&mut limit));
let lower = Some(RangeBound::new(lower, type_));
2014-02-17 04:35:40 +00:00
assert!(limit.limit() == 0);
lower
2013-12-08 22:37:31 +00:00
}
_ => None
};
let upper = match t & RANGE_UPPER_UNBOUNDED {
0 => {
let type_ = match t & RANGE_UPPER_INCLUSIVE {
0 => Exclusive,
_ => Inclusive
};
2014-03-28 05:43:10 +00:00
let len = try_pg!(rdr.read_be_i32()) as uint;
2014-02-15 21:44:48 +00:00
let mut limit = LimitReader::new(rdr.by_ref(), len);
2014-04-26 22:07:40 +00:00
let upper = try!(RawFromSql::raw_from_sql(&mut limit));
let upper = Some(RangeBound::new(upper, type_));
2014-02-17 04:35:40 +00:00
assert!(limit.limit() == 0);
upper
2013-12-08 22:37:31 +00:00
}
_ => None
};
2014-03-28 05:43:10 +00:00
Ok(Range::new(lower, upper))
2013-12-08 22:37:31 +00:00
}
}
}
)
)
2014-04-23 06:02:56 +00:00
from_range_impl!(i32)
from_range_impl!(i64)
from_range_impl!(Timespec)
2013-12-08 22:37:31 +00:00
2013-12-09 00:00:33 +00:00
impl RawFromSql for Json {
2014-04-26 22:07:40 +00:00
fn raw_from_sql<R: Reader>(raw: &mut R) -> PostgresResult<Json> {
2014-03-28 05:43:10 +00:00
Ok(json::from_reader(raw as &mut Reader).unwrap())
2013-12-09 00:00:33 +00:00
}
}
2013-09-02 21:06:22 +00:00
macro_rules! from_map_impl(
2013-09-05 04:30:20 +00:00
($($expected:pat)|+, $t:ty, $blk:expr) => (
impl FromSql for Option<$t> {
2014-04-08 03:02:05 +00:00
fn from_sql(ty: &PostgresType, raw: &Option<Vec<u8>>)
2014-04-26 22:07:40 +00:00
-> PostgresResult<Option<$t>> {
2013-09-05 04:30:20 +00:00
check_types!($($expected)|+, ty)
2014-03-28 05:43:10 +00:00
match *raw {
Some(ref buf) => ($blk)(buf).map(|ok| Some(ok)),
None => Ok(None)
}
}
}
impl FromSql for $t {
2014-04-08 03:02:05 +00:00
fn from_sql(ty: &PostgresType, raw: &Option<Vec<u8>>)
2014-04-26 22:07:40 +00:00
-> PostgresResult<$t> {
// FIXME when you can specify Self types properly
2014-04-26 22:07:40 +00:00
let ret: PostgresResult<Option<$t>> = FromSql::from_sql(ty, raw);
2014-03-30 02:01:23 +00:00
match ret {
Ok(Some(val)) => Ok(val),
Ok(None) => Err(PgWasNull),
Err(err) => Err(err)
}
}
}
)
)
2013-10-31 02:55:25 +00:00
macro_rules! from_raw_from_impl(
($($expected:pat)|+, $t:ty) => (
2014-04-08 03:02:05 +00:00
from_map_impl!($($expected)|+, $t, |buf: &Vec<u8>| {
2013-10-31 02:55:25 +00:00
let mut reader = BufReader::new(buf.as_slice());
2014-02-15 21:44:48 +00:00
RawFromSql::raw_from_sql(&mut reader)
2013-10-31 02:55:25 +00:00
})
)
)
2013-12-07 23:39:44 +00:00
from_raw_from_impl!(PgBool, bool)
2014-04-08 03:02:05 +00:00
from_raw_from_impl!(PgByteA, Vec<u8>)
2014-05-12 04:52:59 +00:00
from_raw_from_impl!(PgVarchar | PgText | PgCharN | PgName, StrBuf)
2013-12-08 02:49:55 +00:00
from_raw_from_impl!(PgChar, i8)
2013-12-08 02:58:40 +00:00
from_raw_from_impl!(PgInt2, i16)
2013-10-31 02:55:25 +00:00
from_raw_from_impl!(PgInt4, i32)
from_raw_from_impl!(PgInt8, i64)
2013-12-06 05:51:09 +00:00
from_raw_from_impl!(PgFloat4, f32)
2013-12-06 05:58:22 +00:00
from_raw_from_impl!(PgFloat8, f64)
2013-12-08 22:16:37 +00:00
from_raw_from_impl!(PgUuid, Uuid)
2013-12-09 00:00:33 +00:00
from_raw_from_impl!(PgJson, Json)
2013-09-02 20:54:02 +00:00
2013-12-08 22:08:35 +00:00
from_raw_from_impl!(PgTimestamp | PgTimestampTZ, Timespec)
2013-12-08 22:37:31 +00:00
from_raw_from_impl!(PgInt4Range, Range<i32>)
from_raw_from_impl!(PgInt8Range, Range<i64>)
from_raw_from_impl!(PgTsRange | PgTstzRange, Range<Timespec>)
2013-10-31 02:55:25 +00:00
2013-12-02 05:09:31 +00:00
macro_rules! from_array_impl(
($($oid:ident)|+, $t:ty) => (
2014-04-08 03:02:05 +00:00
from_map_impl!($($oid)|+, ArrayBase<Option<$t>>, |buf: &Vec<u8>| {
2013-12-02 05:09:31 +00:00
let mut rdr = BufReader::new(buf.as_slice());
2014-03-28 05:43:10 +00:00
let ndim = try_pg!(rdr.read_be_i32()) as uint;
let _has_null = try_pg!(rdr.read_be_i32()) == 1;
let _element_type: Oid = try_pg!(rdr.read_be_u32());
2013-12-02 05:09:31 +00:00
2014-03-19 06:07:12 +00:00
let mut dim_info = Vec::with_capacity(ndim);
2013-12-02 05:09:31 +00:00
for _ in range(0, ndim) {
dim_info.push(DimensionInfo {
2014-03-28 05:43:10 +00:00
len: try_pg!(rdr.read_be_i32()) as uint,
lower_bound: try_pg!(rdr.read_be_i32()) as int
2013-12-02 05:09:31 +00:00
});
}
let nele = dim_info.iter().fold(1, |acc, info| acc * info.len);
2014-03-19 06:07:12 +00:00
let mut elements = Vec::with_capacity(nele);
2013-12-02 05:09:31 +00:00
for _ in range(0, nele) {
2014-03-28 05:43:10 +00:00
let len = try_pg!(rdr.read_be_i32());
2013-12-02 05:09:31 +00:00
if len < 0 {
elements.push(None);
} else {
2014-02-15 21:44:48 +00:00
let mut limit = LimitReader::new(rdr.by_ref(), len as uint);
2014-03-28 05:43:10 +00:00
elements.push(Some(try!(RawFromSql::raw_from_sql(&mut limit))));
2014-02-17 04:35:40 +00:00
assert!(limit.limit() == 0);
2013-12-02 05:09:31 +00:00
}
}
2014-03-28 05:43:10 +00:00
Ok(ArrayBase::from_raw(elements, dim_info))
2013-12-02 05:09:31 +00:00
})
)
)
2013-12-07 23:39:44 +00:00
from_array_impl!(PgBoolArray, bool)
2014-04-08 03:02:05 +00:00
from_array_impl!(PgByteAArray, Vec<u8>)
2013-12-08 02:49:55 +00:00
from_array_impl!(PgCharArray, i8)
2013-12-08 02:58:40 +00:00
from_array_impl!(PgInt2Array, i16)
2013-12-02 05:09:31 +00:00
from_array_impl!(PgInt4Array, i32)
2014-05-12 04:52:59 +00:00
from_array_impl!(PgTextArray | PgCharNArray | PgVarcharArray | PgNameArray, StrBuf)
2013-12-04 06:32:54 +00:00
from_array_impl!(PgInt8Array, i64)
2013-12-08 22:08:35 +00:00
from_array_impl!(PgTimestampArray | PgTimestampTZArray, Timespec)
2013-12-09 00:00:33 +00:00
from_array_impl!(PgJsonArray, Json)
2013-12-06 05:51:09 +00:00
from_array_impl!(PgFloat4Array, f32)
2013-12-06 05:58:22 +00:00
from_array_impl!(PgFloat8Array, f64)
2013-12-08 22:16:37 +00:00
from_array_impl!(PgUuidArray, Uuid)
2013-12-08 22:37:31 +00:00
from_array_impl!(PgInt4RangeArray, Range<i32>)
2013-12-08 23:02:38 +00:00
from_array_impl!(PgTsRangeArray | PgTstzRangeArray, Range<Timespec>)
2013-12-08 23:07:11 +00:00
from_array_impl!(PgInt8RangeArray, Range<i64>)
2013-12-06 05:58:22 +00:00
2014-05-16 02:59:01 +00:00
impl FromSql for Option<HashMap<StrBuf, Option<StrBuf>>> {
2014-04-08 03:02:05 +00:00
fn from_sql(ty: &PostgresType, raw: &Option<Vec<u8>>)
2014-05-16 02:59:01 +00:00
-> PostgresResult<Option<HashMap<StrBuf, Option<StrBuf>>>> {
2014-03-13 06:50:10 +00:00
match *ty {
2014-05-16 02:27:19 +00:00
PgUnknownType { name: ref name, .. }
if "hstore" == name.as_slice() => {}
2014-03-28 05:43:10 +00:00
_ => return Err(PgWrongType(ty.clone()))
2014-03-13 06:50:10 +00:00
}
2014-03-28 05:43:10 +00:00
match *raw {
Some(ref buf) => {
let mut rdr = BufReader::new(buf.as_slice());
let mut map = HashMap::new();
2013-12-05 05:20:48 +00:00
2014-03-28 05:43:10 +00:00
let count = try_pg!(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) {
let key_len = try_pg!(rdr.read_be_i32());
2014-04-26 21:46:38 +00:00
let key = try_pg!(rdr.read_exact(key_len as uint));
2014-05-16 02:59:01 +00:00
let key = StrBuf::from_utf8(key).unwrap();
2014-03-13 06:50:10 +00:00
2014-03-28 05:43:10 +00:00
let val_len = try_pg!(rdr.read_be_i32());
let val = if val_len < 0 {
None
} else {
2014-04-26 21:46:38 +00:00
let val = try_pg!(rdr.read_exact(val_len as uint));
2014-05-16 02:59:01 +00:00
Some(StrBuf::from_utf8(val).unwrap())
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-05-16 02:59:01 +00:00
impl FromSql for HashMap<StrBuf, Option<StrBuf>> {
2014-04-08 03:02:05 +00:00
fn from_sql(ty: &PostgresType, raw: &Option<Vec<u8>>)
2014-05-16 02:59:01 +00:00
-> PostgresResult<HashMap<StrBuf, Option<StrBuf>>> {
2014-03-13 06:50:10 +00:00
// FIXME when you can specify Self types properly
2014-05-16 02:59:01 +00:00
let ret: PostgresResult<Option<HashMap<StrBuf, Option<StrBuf>>>> =
2014-04-26 22:07:40 +00:00
FromSql::from_sql(ty, raw);
2014-03-30 02:01:23 +00:00
match ret {
Ok(Some(val)) => Ok(val),
Ok(None) => Err(PgWasNull),
Err(err) => Err(err)
}
2014-03-13 06:50:10 +00:00
}
}
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 {
2013-09-30 02:47:30 +00:00
/// Converts the value of `self` into a format appropriate for the Postgres
/// backend.
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)>;
}
#[doc(hidden)]
2013-10-31 02:55:25 +00:00
trait RawToSql {
2014-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> PostgresResult<()>;
2013-10-31 02:55:25 +00:00
}
macro_rules! raw_to_impl(
($t:ty, $f:ident) => (
impl RawToSql for $t {
2014-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> PostgresResult<()> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(w.$f(*self)))
2013-10-31 02:55:25 +00:00
}
}
)
)
2013-12-07 23:39:44 +00:00
impl RawToSql for bool {
2014-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> PostgresResult<()> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(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-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> PostgresResult<()> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(w.write(self.as_slice())))
2014-03-15 06:01:46 +00:00
}
}
2014-05-16 02:59:01 +00:00
impl RawToSql for StrBuf {
2014-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> PostgresResult<()> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(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)
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
impl RawToSql for Timespec {
2014-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> PostgresResult<()> {
2014-04-02 02:50:26 +00:00
let t = (self.sec - TIME_SEC_CONVERSION) * USEC_PER_SEC
+ self.nsec as i64 / NSEC_PER_USEC;
2014-03-28 05:43:10 +00:00
Ok(try_pg!(w.write_be_i64(t)))
2013-10-31 02:55:25 +00:00
}
}
2013-12-08 22:16:37 +00:00
impl RawToSql for Uuid {
2014-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> PostgresResult<()> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(w.write(self.as_bytes())))
2013-12-08 22:16:37 +00:00
}
}
2013-12-08 22:37:31 +00:00
macro_rules! to_range_impl(
2014-04-23 06:02:56 +00:00
($t:ty) => (
2013-12-08 22:37:31 +00:00
impl RawToSql for Range<$t> {
2014-03-28 05:43:10 +00:00
fn raw_to_sql<W: Writer>(&self, buf: &mut W)
2014-04-26 22:07:40 +00:00
-> PostgresResult<()> {
2013-12-08 22:37:31 +00:00
let mut tag = 0;
if self.is_empty() {
tag |= RANGE_EMPTY;
} else {
match self.lower() {
2013-12-08 22:37:31 +00:00
None => tag |= RANGE_LOWER_UNBOUNDED,
Some(&RangeBound { type_: Inclusive, .. }) =>
2013-12-08 22:37:31 +00:00
tag |= RANGE_LOWER_INCLUSIVE,
_ => {}
}
match self.upper() {
2013-12-08 22:37:31 +00:00
None => tag |= RANGE_UPPER_UNBOUNDED,
Some(&RangeBound { type_: Inclusive, .. }) =>
2013-12-08 22:37:31 +00:00
tag |= RANGE_UPPER_INCLUSIVE,
_ => {}
}
}
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_i8(tag));
2013-12-08 22:37:31 +00:00
match self.lower() {
Some(bound) => {
2013-12-08 22:37:31 +00:00
let mut inner_buf = MemWriter::new();
2014-03-28 05:43:10 +00:00
try!(bound.value.raw_to_sql(&mut inner_buf));
2014-01-10 05:06:57 +00:00
let inner_buf = inner_buf.unwrap();
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(inner_buf.len() as i32));
2014-04-08 03:02:05 +00:00
try_pg!(buf.write(inner_buf.as_slice()));
2013-12-08 22:37:31 +00:00
}
None => {}
}
match self.upper() {
Some(bound) => {
2013-12-08 22:37:31 +00:00
let mut inner_buf = MemWriter::new();
2014-03-28 05:43:10 +00:00
try!(bound.value.raw_to_sql(&mut inner_buf));
2014-01-10 05:06:57 +00:00
let inner_buf = inner_buf.unwrap();
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(inner_buf.len() as i32));
2014-04-08 03:02:05 +00:00
try_pg!(buf.write(inner_buf.as_slice()));
2013-12-08 22:37:31 +00:00
}
None => {}
}
2014-03-28 05:43:10 +00:00
Ok(())
2013-12-08 22:37:31 +00:00
}
}
)
)
2014-04-23 06:02:56 +00:00
to_range_impl!(i32)
to_range_impl!(i64)
to_range_impl!(Timespec)
2013-12-08 22:37:31 +00:00
2013-12-09 00:00:33 +00:00
impl RawToSql for Json {
2014-04-26 22:07:40 +00:00
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> PostgresResult<()> {
2014-03-28 05:43:10 +00:00
Ok(try_pg!(self.to_writer(raw as &mut Writer)))
2013-12-09 00:00:33 +00:00
}
}
macro_rules! to_option_impl(
2013-12-05 05:20:48 +00:00
($($oid:pat)|+, $t:ty) => (
impl ToSql for Option<$t> {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
2013-09-05 04:30:20 +00:00
check_types!($($oid)|+, ty)
2013-09-02 17:27:09 +00:00
match *self {
2014-03-28 05:43:10 +00:00
None => Ok((Text, None)),
2013-09-02 17:27:09 +00:00
Some(ref val) => val.to_sql(ty)
}
}
}
2013-12-05 05:20:48 +00:00
)
)
2013-12-12 03:22:18 +00:00
macro_rules! to_option_impl_lifetime(
2013-12-05 05:20:48 +00:00
($($oid:pat)|+, $t:ty) => (
2013-12-12 03:22:18 +00:00
impl<'a> ToSql for Option<$t> {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
2013-09-05 04:30:20 +00:00
check_types!($($oid)|+, ty)
2013-09-02 20:54:02 +00:00
match *self {
2014-03-28 05:43:10 +00:00
None => Ok((Text, None)),
2013-09-02 20:54:02 +00:00
Some(ref val) => val.to_sql(ty)
}
}
}
)
)
2013-10-31 02:55:25 +00:00
macro_rules! to_raw_to_impl(
($($oid:ident)|+, $t:ty) => (
impl ToSql for $t {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
2013-10-31 02:55:25 +00:00
check_types!($($oid)|+, ty)
let mut writer = MemWriter::new();
2014-03-28 05:43:10 +00:00
try!(self.raw_to_sql(&mut writer));
Ok((Binary, Some(writer.unwrap())))
2013-10-31 02:55:25 +00:00
}
}
to_option_impl!($($oid)|+, $t)
2013-10-31 02:55:25 +00:00
)
)
2013-12-07 23:39:44 +00:00
to_raw_to_impl!(PgBool, bool)
2014-03-15 06:01:46 +00:00
to_raw_to_impl!(PgByteA, Vec<u8>)
2014-05-16 02:59:01 +00:00
to_raw_to_impl!(PgVarchar | PgText | PgCharN | PgName, StrBuf)
2013-12-09 00:00:33 +00:00
to_raw_to_impl!(PgJson, Json)
2013-12-08 02:49:55 +00:00
to_raw_to_impl!(PgChar, i8)
2013-12-08 02:58:40 +00:00
to_raw_to_impl!(PgInt2, i16)
2013-10-31 02:55:25 +00:00
to_raw_to_impl!(PgInt4, i32)
to_raw_to_impl!(PgInt8, i64)
2013-12-06 05:51:09 +00:00
to_raw_to_impl!(PgFloat4, f32)
2013-12-06 05:58:22 +00:00
to_raw_to_impl!(PgFloat8, f64)
2013-12-08 22:37:31 +00:00
to_raw_to_impl!(PgInt4Range, Range<i32>)
to_raw_to_impl!(PgInt8Range, Range<i64>)
to_raw_to_impl!(PgTsRange | PgTstzRange, Range<Timespec>)
2013-10-31 02:55:25 +00:00
2013-12-12 03:22:18 +00:00
impl<'a> ToSql for &'a str {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
check_types!(PgVarchar | PgText | PgCharN | PgName, ty)
2014-04-08 03:02:05 +00:00
Ok((Text, Some(Vec::from_slice(self.as_bytes()))))
}
}
to_option_impl_lifetime!(PgVarchar | PgText | PgCharN | PgName, &'a str)
2013-12-12 03:22:18 +00:00
impl<'a> ToSql for &'a [u8] {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
2013-09-05 04:30:20 +00:00
check_types!(PgByteA, ty)
2014-04-08 03:02:05 +00:00
Ok((Binary, Some(Vec::from_slice(*self))))
}
}
2013-12-12 03:22:18 +00:00
to_option_impl_lifetime!(PgByteA, &'a [u8])
2013-12-08 22:08:35 +00:00
to_raw_to_impl!(PgTimestamp | PgTimestampTZ, Timespec)
2013-12-08 22:16:37 +00:00
to_raw_to_impl!(PgUuid, Uuid)
2013-12-02 05:09:31 +00:00
macro_rules! to_array_impl(
2013-12-08 19:44:37 +00:00
($($oid:ident)|+, $t:ty) => (
2013-12-02 05:09:31 +00:00
impl ToSql for ArrayBase<Option<$t>> {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
2013-12-02 05:09:31 +00:00
check_types!($($oid)|+, ty)
let mut buf = MemWriter::new();
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(self.dimension_info().len() as i32));
try_pg!(buf.write_be_i32(1));
try_pg!(buf.write_be_u32(ty.member_type().to_oid()));
2013-12-02 05:09:31 +00:00
for info in self.dimension_info().iter() {
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(info.len as i32));
try_pg!(buf.write_be_i32(info.lower_bound as i32));
2013-12-02 05:09:31 +00:00
}
for v in self.values() {
match *v {
Some(ref val) => {
2013-12-08 22:37:31 +00:00
let mut inner_buf = MemWriter::new();
2014-03-28 05:43:10 +00:00
try!(val.raw_to_sql(&mut inner_buf));
2014-01-10 05:06:57 +00:00
let inner_buf = inner_buf.unwrap();
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(inner_buf.len() as i32));
2014-04-08 03:02:05 +00:00
try_pg!(buf.write(inner_buf.as_slice()));
2013-12-02 05:09:31 +00:00
}
2014-03-28 05:43:10 +00:00
None => try_pg!(buf.write_be_i32(-1))
2013-12-02 05:09:31 +00:00
}
}
2014-03-28 05:43:10 +00:00
Ok((Binary, Some(buf.unwrap())))
2013-12-02 05:09:31 +00:00
}
}
to_option_impl!($($oid)|+, ArrayBase<Option<$t>>)
2013-12-02 05:09:31 +00:00
)
)
2013-12-08 19:44:37 +00:00
to_array_impl!(PgBoolArray, bool)
2014-03-15 06:01:46 +00:00
to_array_impl!(PgByteAArray, Vec<u8>)
2013-12-08 19:44:37 +00:00
to_array_impl!(PgCharArray, i8)
to_array_impl!(PgInt2Array, i16)
to_array_impl!(PgInt4Array, i32)
to_array_impl!(PgInt8Array, i64)
2014-05-16 02:59:01 +00:00
to_array_impl!(PgTextArray | PgCharNArray | PgVarcharArray | PgNameArray, StrBuf)
2013-12-08 22:08:35 +00:00
to_array_impl!(PgTimestampArray | PgTimestampTZArray, Timespec)
2013-12-08 19:44:37 +00:00
to_array_impl!(PgFloat4Array, f32)
to_array_impl!(PgFloat8Array, f64)
2013-12-08 22:16:37 +00:00
to_array_impl!(PgUuidArray, Uuid)
2013-12-08 22:37:31 +00:00
to_array_impl!(PgInt4RangeArray, Range<i32>)
2013-12-08 23:02:38 +00:00
to_array_impl!(PgTsRangeArray | PgTstzRangeArray, Range<Timespec>)
2013-12-08 23:07:11 +00:00
to_array_impl!(PgInt8RangeArray, Range<i64>)
2013-12-09 00:00:33 +00:00
to_array_impl!(PgJsonArray, Json)
2013-12-06 05:58:22 +00:00
2014-05-16 02:59:01 +00:00
impl ToSql for HashMap<StrBuf, Option<StrBuf>> {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
2014-03-13 06:50:10 +00:00
match *ty {
2014-05-16 02:27:19 +00:00
PgUnknownType { name: ref name, .. }
if "hstore" == name.as_slice() => {}
2014-03-28 05:43:10 +00:00
_ => return Err(PgWrongType(ty.clone()))
2014-03-13 06:50:10 +00:00
}
2013-12-05 05:20:48 +00:00
let mut buf = MemWriter::new();
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(self.len() as i32));
2013-12-05 05:20:48 +00:00
for (key, val) in self.iter() {
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(key.len() as i32));
try_pg!(buf.write(key.as_bytes()));
2013-12-05 05:20:48 +00:00
match *val {
Some(ref val) => {
2014-03-28 05:43:10 +00:00
try_pg!(buf.write_be_i32(val.len() as i32));
try_pg!(buf.write(val.as_bytes()));
2013-12-05 05:20:48 +00:00
}
2014-03-28 05:43:10 +00:00
None => try_pg!(buf.write_be_i32(-1))
2013-12-05 05:20:48 +00:00
}
}
2014-03-28 05:43:10 +00:00
Ok((Binary, Some(buf.unwrap())))
2013-12-05 05:20:48 +00:00
}
}
2014-03-13 06:50:10 +00:00
2014-05-16 02:59:01 +00:00
impl ToSql for Option<HashMap<StrBuf, Option<StrBuf>>> {
2014-03-28 05:43:10 +00:00
fn to_sql(&self, ty: &PostgresType)
2014-04-26 22:07:40 +00:00
-> PostgresResult<(Format, Option<Vec<u8>>)> {
2014-03-13 06:50:10 +00:00
match *ty {
2014-05-16 02:27:19 +00:00
PgUnknownType { name: ref name, .. }
if "hstore" == name.as_slice() => {}
2014-03-28 05:43:10 +00:00
_ => return Err(PgWrongType(ty.clone()))
2014-03-13 06:50:10 +00:00
}
match *self {
Some(ref inner) => inner.to_sql(ty),
2014-03-28 05:43:10 +00:00
None => Ok((Binary, None))
2014-03-13 06:50:10 +00:00
}
}
}