Make time support optional
This commit is contained in:
parent
22f4be2b8c
commit
9a87c6e18a
@ -13,7 +13,7 @@ name = "test"
|
||||
path = "tests/test.rs"
|
||||
|
||||
[features]
|
||||
default = ["uuid"]
|
||||
default = ["uuid", "time"]
|
||||
|
||||
[dependencies.openssl]
|
||||
git = "https://github.com/sfackler/rust-openssl"
|
||||
@ -30,6 +30,7 @@ optional = true
|
||||
|
||||
[dependencies.time]
|
||||
git = "https://github.com/rust-lang/time"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.url]
|
||||
git = "https://github.com/servo/rust-url"
|
||||
|
10
README.md
10
README.md
@ -297,8 +297,14 @@ traits.
|
||||
### UUID type
|
||||
|
||||
[UUID](http://www.postgresql.org/docs/9.4/static/datatype-uuid.html) support is
|
||||
provided optionally by the `uuid` feature. It is enabled by default. To disable
|
||||
`UUID` support, add `default-features = false` to your Cargo manifest:
|
||||
provided optionally by the `uuid` feature. It is enabled by default.
|
||||
|
||||
### Time types
|
||||
[Time](http://www.postgresql.org/docs/9.3/static/datatype-datetime.html)
|
||||
support is provided optionally by the `time` feature. It is enabled by default.
|
||||
|
||||
To disable support for optional features, add `default-features = false` to
|
||||
your Cargo manifest:
|
||||
|
||||
```toml
|
||||
[dependencies.postgres]
|
||||
|
@ -4,8 +4,11 @@
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! extern crate postgres;
|
||||
//! # #[cfg(feature = "time")]
|
||||
//! extern crate time;
|
||||
//!
|
||||
//! # #[cfg(not(feature = "time"))] fn main() {}
|
||||
//! # #[cfg(feature = "time")] fn main() {
|
||||
//! use time::Timespec;
|
||||
//!
|
||||
//! use postgres::{Connection, SslMode};
|
||||
@ -49,6 +52,7 @@
|
||||
//! println!("Found person {}", person.name);
|
||||
//! }
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
#![doc(html_root_url="https://sfackler.github.io/doc")]
|
||||
#![feature(globs, macro_rules, phase, unsafe_destructor, slicing_syntax, default_type_params, if_let)]
|
||||
@ -56,7 +60,6 @@
|
||||
|
||||
extern crate openssl;
|
||||
extern crate serialize;
|
||||
extern crate time;
|
||||
extern crate phf;
|
||||
#[phase(plugin)]
|
||||
extern crate phf_mac;
|
||||
|
119
src/types/mod.rs
119
src/types/mod.rs
@ -3,20 +3,17 @@
|
||||
|
||||
use serialize::json;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{AsRefReader, MemWriter, BufReader};
|
||||
use std::io::util::LimitReader;
|
||||
use time::Timespec;
|
||||
use std::io::{ByRefReader, MemWriter, BufReader};
|
||||
|
||||
use Result;
|
||||
use error::{PgWrongType, PgWasNull, PgBadData};
|
||||
use types::array::{Array, ArrayBase, DimensionInfo};
|
||||
use types::range::{RangeBound, Inclusive, Exclusive, Range};
|
||||
use types::range::{Inclusive, Exclusive, Range};
|
||||
|
||||
macro_rules! check_types(
|
||||
($($expected:pat)|+, $actual:ident) => (
|
||||
match $actual {
|
||||
$(&$expected)|+ => {}
|
||||
actual => return Err(PgWrongType(actual.clone()))
|
||||
actual => return Err(::Error::PgWrongType(actual.clone()))
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -33,8 +30,14 @@ macro_rules! raw_from_impl(
|
||||
|
||||
macro_rules! from_range_impl(
|
||||
($t:ty) => (
|
||||
impl RawFromSql for Range<$t> {
|
||||
impl ::types::RawFromSql for ::types::range::Range<$t> {
|
||||
fn raw_from_sql<R: Reader>(rdr: &mut R) -> Result<Range<$t>> {
|
||||
use std::io::ByRefReader;
|
||||
use std::io::util::LimitReader;
|
||||
use types::{RANGE_EMPTY, RANGE_LOWER_UNBOUNDED, RANGE_LOWER_INCLUSIVE,
|
||||
RANGE_UPPER_UNBOUNDED, RANGE_UPPER_INCLUSIVE};
|
||||
use types::range::{BoundType, Range, RangeBound};
|
||||
|
||||
let t = try!(rdr.read_i8());
|
||||
|
||||
if t & RANGE_EMPTY != 0 {
|
||||
@ -43,8 +46,8 @@ macro_rules! from_range_impl(
|
||||
let lower = match t & RANGE_LOWER_UNBOUNDED {
|
||||
0 => {
|
||||
let type_ = match t & RANGE_LOWER_INCLUSIVE {
|
||||
0 => Exclusive,
|
||||
_ => Inclusive
|
||||
0 => BoundType::Exclusive,
|
||||
_ => BoundType::Inclusive
|
||||
};
|
||||
let len = try!(rdr.read_be_i32()) as uint;
|
||||
let mut limit = LimitReader::new(rdr.by_ref(), len);
|
||||
@ -58,8 +61,8 @@ macro_rules! from_range_impl(
|
||||
let upper = match t & RANGE_UPPER_UNBOUNDED {
|
||||
0 => {
|
||||
let type_ = match t & RANGE_UPPER_INCLUSIVE {
|
||||
0 => Exclusive,
|
||||
_ => Inclusive
|
||||
0 => BoundType::Exclusive,
|
||||
_ => BoundType::Inclusive
|
||||
};
|
||||
let len = try!(rdr.read_be_i32()) as uint;
|
||||
let mut limit = LimitReader::new(rdr.by_ref(), len);
|
||||
@ -81,9 +84,8 @@ macro_rules! from_range_impl(
|
||||
macro_rules! from_map_impl(
|
||||
($($expected:pat)|+, $t:ty, $blk:expr $(, $a:meta)*) => (
|
||||
$(#[$a])*
|
||||
impl FromSql for Option<$t> {
|
||||
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>)
|
||||
-> Result<Option<$t>> {
|
||||
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)),
|
||||
@ -93,14 +95,16 @@ macro_rules! from_map_impl(
|
||||
}
|
||||
|
||||
$(#[$a])*
|
||||
impl FromSql for $t {
|
||||
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>)
|
||||
-> Result<$t> {
|
||||
impl ::types::FromSql for $t {
|
||||
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>) -> Result<$t> {
|
||||
use Error;
|
||||
use types::FromSql;
|
||||
|
||||
// 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(PgWasNull),
|
||||
Ok(None) => Err(Error::PgWasNull),
|
||||
Err(err) => Err(err)
|
||||
}
|
||||
}
|
||||
@ -111,6 +115,9 @@ macro_rules! from_map_impl(
|
||||
macro_rules! from_raw_from_impl(
|
||||
($($expected:pat)|+, $t:ty $(, $a:meta)*) => (
|
||||
from_map_impl!($($expected)|+, $t, |buf: &Vec<u8>| {
|
||||
use std::io::BufReader;
|
||||
use types::RawFromSql;
|
||||
|
||||
let mut reader = BufReader::new(buf[]);
|
||||
RawFromSql::raw_from_sql(&mut reader)
|
||||
} $(, $a)*)
|
||||
@ -119,7 +126,12 @@ macro_rules! from_raw_from_impl(
|
||||
|
||||
macro_rules! from_array_impl(
|
||||
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
||||
from_map_impl!($($oid)|+, ArrayBase<Option<$t>>, |buf: &Vec<u8>| {
|
||||
from_map_impl!($($oid)|+, ::types::array::ArrayBase<Option<$t>>, |buf: &Vec<u8>| {
|
||||
use std::io::{BufReader, ByRefReader};
|
||||
use std::io::util::LimitReader;
|
||||
use types::{Oid, RawFromSql};
|
||||
use types::array::{ArrayBase, DimensionInfo};
|
||||
|
||||
let mut rdr = BufReader::new(buf[]);
|
||||
|
||||
let ndim = try!(rdr.read_be_i32()) as uint;
|
||||
@ -164,20 +176,29 @@ macro_rules! raw_to_impl(
|
||||
|
||||
macro_rules! to_range_impl(
|
||||
($t:ty) => (
|
||||
impl RawToSql for Range<$t> {
|
||||
impl ::types::RawToSql for ::types::range::Range<$t> {
|
||||
fn raw_to_sql<W: Writer>(&self, buf: &mut W) -> Result<()> {
|
||||
use std::io::MemWriter;
|
||||
use types::{RANGE_EMPTY, RANGE_LOWER_UNBOUNDED, RANGE_LOWER_INCLUSIVE,
|
||||
RANGE_UPPER_UNBOUNDED, RANGE_UPPER_INCLUSIVE};
|
||||
use types::range::{BoundType, RangeBound};
|
||||
|
||||
let mut tag = 0;
|
||||
if self.is_empty() {
|
||||
tag |= RANGE_EMPTY;
|
||||
} else {
|
||||
match self.lower() {
|
||||
None => tag |= RANGE_LOWER_UNBOUNDED,
|
||||
Some(&RangeBound { type_: Inclusive, .. }) => tag |= RANGE_LOWER_INCLUSIVE,
|
||||
Some(&RangeBound { type_: BoundType::Inclusive, .. }) => {
|
||||
tag |= RANGE_LOWER_INCLUSIVE
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match self.upper() {
|
||||
None => tag |= RANGE_UPPER_UNBOUNDED,
|
||||
Some(&RangeBound { type_: Inclusive, .. }) => tag |= RANGE_UPPER_INCLUSIVE,
|
||||
Some(&RangeBound { type_: BoundType::Inclusive, .. }) => {
|
||||
tag |= RANGE_UPPER_INCLUSIVE
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -214,7 +235,7 @@ macro_rules! to_range_impl(
|
||||
macro_rules! to_option_impl(
|
||||
($($oid:pat)|+, $t:ty $(,$a:meta)*) => (
|
||||
$(#[$a])*
|
||||
impl ToSql for Option<$t> {
|
||||
impl ::types::ToSql for Option<$t> {
|
||||
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
||||
check_types!($($oid)|+, ty)
|
||||
|
||||
@ -245,8 +266,10 @@ macro_rules! to_option_impl_lifetime(
|
||||
macro_rules! to_raw_to_impl(
|
||||
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
||||
$(#[$a])*
|
||||
impl ToSql for $t {
|
||||
impl ::types::ToSql for $t {
|
||||
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
||||
use std::io::MemWriter;
|
||||
|
||||
check_types!($($oid)|+, ty)
|
||||
|
||||
let mut writer = MemWriter::new();
|
||||
@ -262,8 +285,11 @@ macro_rules! to_raw_to_impl(
|
||||
macro_rules! to_array_impl(
|
||||
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
||||
$(#[$a])*
|
||||
impl ToSql for ArrayBase<Option<$t>> {
|
||||
impl ::types::ToSql for ::types::array::ArrayBase<Option<$t>> {
|
||||
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
||||
use std::io::MemWriter;
|
||||
use types::array::Array;
|
||||
|
||||
check_types!($($oid)|+, ty)
|
||||
let mut buf = MemWriter::new();
|
||||
|
||||
@ -293,7 +319,7 @@ macro_rules! to_array_impl(
|
||||
}
|
||||
}
|
||||
|
||||
to_option_impl!($($oid)|+, ArrayBase<Option<$t>> $(, $a)*)
|
||||
to_option_impl!($($oid)|+, ::types::array::ArrayBase<Option<$t>> $(, $a)*)
|
||||
)
|
||||
)
|
||||
|
||||
@ -301,6 +327,8 @@ pub mod array;
|
||||
pub mod range;
|
||||
#[cfg(feature = "uuid")]
|
||||
mod uuid;
|
||||
#[cfg(feature = "time")]
|
||||
mod time;
|
||||
|
||||
/// A Postgres OID
|
||||
pub type Oid = u32;
|
||||
@ -347,12 +375,6 @@ const TSTZRANGEARRAYOID: Oid = 3911;
|
||||
const INT8RANGEOID: Oid = 3926;
|
||||
const INT8RANGEARRAYOID: Oid = 3927;
|
||||
|
||||
const USEC_PER_SEC: i64 = 1_000_000;
|
||||
const NSEC_PER_USEC: i64 = 1_000;
|
||||
|
||||
// Number of seconds from 1970-01-01 to 2000-01-01
|
||||
const TIME_SEC_CONVERSION: i64 = 946684800;
|
||||
|
||||
const RANGE_UPPER_UNBOUNDED: i8 = 0b0001_0000;
|
||||
const RANGE_LOWER_UNBOUNDED: i8 = 0b0000_1000;
|
||||
const RANGE_UPPER_INCLUSIVE: i8 = 0b0000_0100;
|
||||
@ -528,24 +550,8 @@ raw_from_impl!(i64, read_be_i64)
|
||||
raw_from_impl!(f32, read_be_f32)
|
||||
raw_from_impl!(f64, read_be_f64)
|
||||
|
||||
impl RawFromSql for Timespec {
|
||||
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<Timespec> {
|
||||
let t = try!(raw.read_be_i64());
|
||||
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;
|
||||
}
|
||||
|
||||
Ok(Timespec::new(sec, (usec * NSEC_PER_USEC) as i32))
|
||||
}
|
||||
}
|
||||
|
||||
from_range_impl!(i32)
|
||||
from_range_impl!(i64)
|
||||
from_range_impl!(Timespec)
|
||||
|
||||
impl RawFromSql for json::Json {
|
||||
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<json::Json> {
|
||||
@ -564,10 +570,8 @@ from_raw_from_impl!(Float4, f32)
|
||||
from_raw_from_impl!(Float8, f64)
|
||||
from_raw_from_impl!(Json, json::Json)
|
||||
|
||||
from_raw_from_impl!(Timestamp | TimestampTZ, Timespec)
|
||||
from_raw_from_impl!(Int4Range, Range<i32>)
|
||||
from_raw_from_impl!(Int8Range, Range<i64>)
|
||||
from_raw_from_impl!(TsRange | TstzRange, Range<Timespec>)
|
||||
|
||||
from_array_impl!(BoolArray, bool)
|
||||
from_array_impl!(ByteAArray, Vec<u8>)
|
||||
@ -576,12 +580,10 @@ from_array_impl!(Int2Array, i16)
|
||||
from_array_impl!(Int4Array, i32)
|
||||
from_array_impl!(TextArray | CharNArray | VarcharArray | NameArray, String)
|
||||
from_array_impl!(Int8Array, i64)
|
||||
from_array_impl!(TimestampArray | TimestampTZArray, Timespec)
|
||||
from_array_impl!(JsonArray, json::Json)
|
||||
from_array_impl!(Float4Array, f32)
|
||||
from_array_impl!(Float8Array, f64)
|
||||
from_array_impl!(Int4RangeArray, Range<i32>)
|
||||
from_array_impl!(TsRangeArray | TstzRangeArray, Range<Timespec>)
|
||||
from_array_impl!(Int8RangeArray, Range<i64>)
|
||||
|
||||
impl FromSql for Option<HashMap<String, Option<String>>> {
|
||||
@ -678,16 +680,8 @@ raw_to_impl!(i64, write_be_i64)
|
||||
raw_to_impl!(f32, write_be_f32)
|
||||
raw_to_impl!(f64, write_be_f64)
|
||||
|
||||
impl RawToSql for Timespec {
|
||||
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
|
||||
let t = (self.sec - TIME_SEC_CONVERSION) * USEC_PER_SEC + self.nsec as i64 / NSEC_PER_USEC;
|
||||
Ok(try!(w.write_be_i64(t)))
|
||||
}
|
||||
}
|
||||
|
||||
to_range_impl!(i32)
|
||||
to_range_impl!(i64)
|
||||
to_range_impl!(Timespec)
|
||||
|
||||
impl RawToSql for json::Json {
|
||||
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> Result<()> {
|
||||
@ -707,7 +701,6 @@ to_raw_to_impl!(Float4, f32)
|
||||
to_raw_to_impl!(Float8, f64)
|
||||
to_raw_to_impl!(Int4Range, Range<i32>)
|
||||
to_raw_to_impl!(Int8Range, Range<i64>)
|
||||
to_raw_to_impl!(TsRange | TstzRange, Range<Timespec>)
|
||||
|
||||
impl<'a> ToSql for &'a str {
|
||||
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
||||
@ -727,8 +720,6 @@ impl<'a> ToSql for &'a [u8] {
|
||||
|
||||
to_option_impl_lifetime!(ByteA, &'a [u8])
|
||||
|
||||
to_raw_to_impl!(Timestamp | TimestampTZ, Timespec)
|
||||
|
||||
to_array_impl!(BoolArray, bool)
|
||||
to_array_impl!(ByteAArray, Vec<u8>)
|
||||
to_array_impl!(CharArray, i8)
|
||||
@ -736,11 +727,9 @@ to_array_impl!(Int2Array, i16)
|
||||
to_array_impl!(Int4Array, i32)
|
||||
to_array_impl!(Int8Array, i64)
|
||||
to_array_impl!(TextArray | CharNArray | VarcharArray | NameArray, String)
|
||||
to_array_impl!(TimestampArray | TimestampTZArray, Timespec)
|
||||
to_array_impl!(Float4Array, f32)
|
||||
to_array_impl!(Float8Array, f64)
|
||||
to_array_impl!(Int4RangeArray, Range<i32>)
|
||||
to_array_impl!(TsRangeArray | TstzRangeArray, Range<Timespec>)
|
||||
to_array_impl!(Int8RangeArray, Range<i64>)
|
||||
to_array_impl!(JsonArray, json::Json)
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
use std::fmt;
|
||||
use std::i32;
|
||||
use std::i64;
|
||||
use time::Timespec;
|
||||
|
||||
/// The `range!` macro can make it easier to create ranges. It roughly mirrors
|
||||
/// traditional mathematic range syntax.
|
||||
@ -131,12 +130,6 @@ macro_rules! bounded_normalizable(
|
||||
bounded_normalizable!(i32)
|
||||
bounded_normalizable!(i64)
|
||||
|
||||
impl Normalizable for Timespec {
|
||||
fn normalize<S: BoundSided>(bound: RangeBound<S, Timespec>) -> RangeBound<S, Timespec> {
|
||||
bound
|
||||
}
|
||||
}
|
||||
|
||||
/// The possible sides of a bound
|
||||
#[deriving(PartialEq, Eq)]
|
||||
pub enum BoundSide {
|
||||
|
53
src/types/time.rs
Normal file
53
src/types/time.rs
Normal file
@ -0,0 +1,53 @@
|
||||
extern crate time;
|
||||
|
||||
use self::time::Timespec;
|
||||
use Result;
|
||||
use types::{RawFromSql, Type, RawToSql};
|
||||
use types::range::{Range, RangeBound, BoundSided, Normalizable};
|
||||
|
||||
const USEC_PER_SEC: i64 = 1_000_000;
|
||||
const NSEC_PER_USEC: i64 = 1_000;
|
||||
|
||||
// Number of seconds from 1970-01-01 to 2000-01-01
|
||||
const TIME_SEC_CONVERSION: i64 = 946684800;
|
||||
|
||||
impl RawFromSql for Timespec {
|
||||
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<Timespec> {
|
||||
let t = try!(raw.read_be_i64());
|
||||
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;
|
||||
}
|
||||
|
||||
Ok(Timespec::new(sec, (usec * NSEC_PER_USEC) as i32))
|
||||
}
|
||||
}
|
||||
|
||||
from_range_impl!(Timespec)
|
||||
from_raw_from_impl!(Type::Timestamp | Type::TimestampTZ, Timespec)
|
||||
from_raw_from_impl!(Type::TsRange | Type::TstzRange, Range<Timespec>)
|
||||
from_array_impl!(Type::TimestampArray | Type::TimestampTZArray, Timespec)
|
||||
from_array_impl!(Type::TsRangeArray | Type::TstzRangeArray, Range<Timespec>)
|
||||
|
||||
impl RawToSql for Timespec {
|
||||
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
|
||||
let t = (self.sec - TIME_SEC_CONVERSION) * USEC_PER_SEC + self.nsec as i64 / NSEC_PER_USEC;
|
||||
Ok(try!(w.write_be_i64(t)))
|
||||
}
|
||||
}
|
||||
|
||||
to_range_impl!(Timespec)
|
||||
to_raw_to_impl!(Type::TsRange | Type::TstzRange, Range<Timespec>)
|
||||
to_raw_to_impl!(Type::Timestamp | Type::TimestampTZ, Timespec)
|
||||
to_array_impl!(Type::TimestampArray | Type::TimestampTZArray, Timespec)
|
||||
to_array_impl!(Type::TsRangeArray | Type::TstzRangeArray, Range<Timespec>)
|
||||
|
||||
impl Normalizable for Timespec {
|
||||
fn normalize<S: BoundSided>(bound: RangeBound<S, Timespec>) -> RangeBound<S, Timespec> {
|
||||
bound
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,8 @@
|
||||
extern crate uuid;
|
||||
|
||||
use std::io::{MemWriter, BufReader};
|
||||
use std::io::util::LimitReader;
|
||||
use std::io::ByRefReader;
|
||||
|
||||
use self::uuid::Uuid;
|
||||
use types::{RawFromSql, FromSql, ToSql, RawToSql, Type, Oid};
|
||||
use Error::{PgWasNull, PgWrongType, PgBadData};
|
||||
use types::array::{ArrayBase, DimensionInfo, Array};
|
||||
use types::{RawFromSql, ToSql, RawToSql, Type};
|
||||
use Error::{PgWasNull, PgBadData};
|
||||
use Result;
|
||||
|
||||
impl RawFromSql for Uuid {
|
||||
|
@ -3,7 +3,6 @@
|
||||
#[phase(plugin, link)]
|
||||
extern crate postgres;
|
||||
extern crate serialize;
|
||||
extern crate time;
|
||||
extern crate url;
|
||||
extern crate openssl;
|
||||
|
||||
|
@ -2,16 +2,16 @@ use serialize::json;
|
||||
use std::collections::HashMap;
|
||||
use std::f32;
|
||||
use std::f64;
|
||||
use time;
|
||||
use time::Timespec;
|
||||
use std::num::Float;
|
||||
|
||||
use postgres::{Connection, SslMode};
|
||||
use postgres::types::array::ArrayBase;
|
||||
use postgres::types::{ToSql, FromSql};
|
||||
|
||||
macro_rules! test_array_params(
|
||||
($name:expr, $v1:expr, $s1:expr, $v2:expr, $s2:expr, $v3:expr, $s3:expr) => ({
|
||||
use postgres::types::array::ArrayBase;
|
||||
use types::test_type;
|
||||
|
||||
let tests = [(Some(ArrayBase::from_vec(vec!(Some($v1), Some($v2), None), 1)),
|
||||
format!("'{{{},{},NULL}}'", $s1, $s2).into_string()),
|
||||
(None, "NULL".to_string())];
|
||||
@ -25,10 +25,33 @@ macro_rules! test_array_params(
|
||||
})
|
||||
)
|
||||
|
||||
macro_rules! test_range(
|
||||
($name:expr, $t:ty, $low:expr, $low_str:expr, $high:expr, $high_str:expr) => ({
|
||||
let tests = [(Some(range!('(', ')')), "'(,)'".to_string()),
|
||||
(Some(range!('[' $low, ')')), format!("'[{},)'", $low_str)),
|
||||
(Some(range!('(' $low, ')')), format!("'({},)'", $low_str)),
|
||||
(Some(range!('(', $high ']')), format!("'(,{}]'", $high_str)),
|
||||
(Some(range!('(', $high ')')), format!("'(,{})'", $high_str)),
|
||||
(Some(range!('[' $low, $high ']')),
|
||||
format!("'[{},{}]'", $low_str, $high_str)),
|
||||
(Some(range!('[' $low, $high ')')),
|
||||
format!("'[{},{})'", $low_str, $high_str)),
|
||||
(Some(range!('(' $low, $high ']')),
|
||||
format!("'({},{}]'", $low_str, $high_str)),
|
||||
(Some(range!('(' $low, $high ')')),
|
||||
format!("'({},{})'", $low_str, $high_str)),
|
||||
(Some(range!(empty)), "'empty'".to_string()),
|
||||
(None, "NULL".to_string())];
|
||||
test_type($name, tests);
|
||||
})
|
||||
)
|
||||
|
||||
mod array;
|
||||
mod range;
|
||||
#[cfg(feature = "uuid")]
|
||||
mod uuid;
|
||||
#[cfg(feature = "time")]
|
||||
mod time;
|
||||
|
||||
fn test_type<T: PartialEq+FromSql+ToSql, S: Str>(sql_type: &str, checks: &[(T, S)]) {
|
||||
let conn = or_panic!(Connection::connect("postgres://postgres@localhost", &SslMode::None));
|
||||
@ -140,44 +163,6 @@ fn test_json_params() {
|
||||
(None, "NULL")])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tm_params() {
|
||||
fn make_check<'a>(time: &'a str) -> (Option<Timespec>, &'a str) {
|
||||
(Some(time::strptime(time, "'%Y-%m-%d %H:%M:%S.%f'").unwrap().to_timespec()), time)
|
||||
}
|
||||
test_type("TIMESTAMP",
|
||||
[make_check("'1970-01-01 00:00:00.01'"),
|
||||
make_check("'1965-09-25 11:19:33.100314'"),
|
||||
make_check("'2010-02-09 23:11:45.1202'"),
|
||||
(None, "NULL")]);
|
||||
test_type("TIMESTAMP WITH TIME ZONE",
|
||||
[make_check("'1970-01-01 00:00:00.01'"),
|
||||
make_check("'1965-09-25 11:19:33.100314'"),
|
||||
make_check("'2010-02-09 23:11:45.1202'"),
|
||||
(None, "NULL")]);
|
||||
}
|
||||
|
||||
macro_rules! test_range(
|
||||
($name:expr, $t:ty, $low:expr, $low_str:expr, $high:expr, $high_str:expr) => ({
|
||||
let tests = [(Some(range!('(', ')')), "'(,)'".to_string()),
|
||||
(Some(range!('[' $low, ')')), format!("'[{},)'", $low_str)),
|
||||
(Some(range!('(' $low, ')')), format!("'({},)'", $low_str)),
|
||||
(Some(range!('(', $high ']')), format!("'(,{}]'", $high_str)),
|
||||
(Some(range!('(', $high ')')), format!("'(,{})'", $high_str)),
|
||||
(Some(range!('[' $low, $high ']')),
|
||||
format!("'[{},{}]'", $low_str, $high_str)),
|
||||
(Some(range!('[' $low, $high ')')),
|
||||
format!("'[{},{})'", $low_str, $high_str)),
|
||||
(Some(range!('(' $low, $high ']')),
|
||||
format!("'({},{}]'", $low_str, $high_str)),
|
||||
(Some(range!('(' $low, $high ')')),
|
||||
format!("'({},{})'", $low_str, $high_str)),
|
||||
(Some(range!(empty)), "'empty'".to_string()),
|
||||
(None, "NULL".to_string())];
|
||||
test_type($name, tests);
|
||||
})
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn test_int4range_params() {
|
||||
test_range!("INT4RANGE", i32, 100i32, "100", 200i32, "200")
|
||||
@ -188,25 +173,6 @@ fn test_int8range_params() {
|
||||
test_range!("INT8RANGE", i64, 100i64, "100", 200i64, "200")
|
||||
}
|
||||
|
||||
fn test_timespec_range_params(sql_type: &str) {
|
||||
fn t(time: &str) -> Timespec {
|
||||
time::strptime(time, "%Y-%m-%d").unwrap().to_timespec()
|
||||
}
|
||||
let low = "1970-01-01";
|
||||
let high = "1980-01-01";
|
||||
test_range!(sql_type, Timespec, t(low), low, t(high), high);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tsrange_params() {
|
||||
test_timespec_range_params("TSRANGE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tstzrange_params() {
|
||||
test_timespec_range_params("TSTZRANGE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolarray_params() {
|
||||
test_array_params!("BOOL", false, "f", true, "t", true, "t");
|
||||
@ -263,18 +229,6 @@ fn test_int8array_params() {
|
||||
test_array_params!("INT8", 0i64, "0", 1i64, "1", 2i64, "2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_timestamparray_params() {
|
||||
fn make_check<'a>(time: &'a str) -> (Timespec, &'a str) {
|
||||
(time::strptime(time, "%Y-%m-%d %H:%M:%S.%f").unwrap().to_timespec(), time)
|
||||
}
|
||||
let (v1, s1) = make_check("1970-01-01 00:00:00.01");
|
||||
let (v2, s2) = make_check("1965-09-25 11:19:33.100314");
|
||||
let (v3, s3) = make_check("2010-02-09 23:11:45.1202");
|
||||
test_array_params!("TIMESTAMP", v1, s1, v2, s2, v3, s3);
|
||||
test_array_params!("TIMESTAMPTZ", v1, s1, v2, s2, v3, s3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float4array_params() {
|
||||
test_array_params!("FLOAT4", 0f32, "0", 1.5f32, "1.5", 0.009f32, ".009");
|
||||
@ -293,23 +247,6 @@ fn test_int4rangearray_params() {
|
||||
range!('(', 10i32 ')'), "\"(,10)\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tsrangearray_params() {
|
||||
fn make_check<'a>(time: &'a str) -> (Timespec, &'a str) {
|
||||
(time::strptime(time, "%Y-%m-%d").unwrap().to_timespec(), time)
|
||||
}
|
||||
let (v1, s1) = make_check("1970-10-11");
|
||||
let (v2, s2) = make_check("1990-01-01");
|
||||
let r1 = range!('(', ')');
|
||||
let rs1 = "\"(,)\"";
|
||||
let r2 = range!('[' v1, ')');
|
||||
let rs2 = format!("\"[{},)\"", s1);
|
||||
let r3 = range!('(', v2 ')');
|
||||
let rs3 = format!("\"(,{})\"", s2);
|
||||
test_array_params!("TSRANGE", r1, rs1, r2, rs2, r3, rs3);
|
||||
test_array_params!("TSTZRANGE", r1, rs1, r2, rs2, r3, rs3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_int8rangearray_params() {
|
||||
test_array_params!("INT8RANGE",
|
||||
|
70
tests/types/time.rs
Normal file
70
tests/types/time.rs
Normal file
@ -0,0 +1,70 @@
|
||||
extern crate time;
|
||||
|
||||
use self::time::Timespec;
|
||||
use types::test_type;
|
||||
|
||||
#[test]
|
||||
fn test_tm_params() {
|
||||
fn make_check<'a>(time: &'a str) -> (Option<Timespec>, &'a str) {
|
||||
(Some(time::strptime(time, "'%Y-%m-%d %H:%M:%S.%f'").unwrap().to_timespec()), time)
|
||||
}
|
||||
test_type("TIMESTAMP",
|
||||
[make_check("'1970-01-01 00:00:00.01'"),
|
||||
make_check("'1965-09-25 11:19:33.100314'"),
|
||||
make_check("'2010-02-09 23:11:45.1202'"),
|
||||
(None, "NULL")]);
|
||||
test_type("TIMESTAMP WITH TIME ZONE",
|
||||
[make_check("'1970-01-01 00:00:00.01'"),
|
||||
make_check("'1965-09-25 11:19:33.100314'"),
|
||||
make_check("'2010-02-09 23:11:45.1202'"),
|
||||
(None, "NULL")]);
|
||||
}
|
||||
|
||||
fn test_timespec_range_params(sql_type: &str) {
|
||||
fn t(time: &str) -> Timespec {
|
||||
time::strptime(time, "%Y-%m-%d").unwrap().to_timespec()
|
||||
}
|
||||
let low = "1970-01-01";
|
||||
let high = "1980-01-01";
|
||||
test_range!(sql_type, Timespec, t(low), low, t(high), high);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tsrange_params() {
|
||||
test_timespec_range_params("TSRANGE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tstzrange_params() {
|
||||
test_timespec_range_params("TSTZRANGE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_timestamparray_params() {
|
||||
fn make_check<'a>(time: &'a str) -> (Timespec, &'a str) {
|
||||
(time::strptime(time, "%Y-%m-%d %H:%M:%S.%f").unwrap().to_timespec(), time)
|
||||
}
|
||||
let (v1, s1) = make_check("1970-01-01 00:00:00.01");
|
||||
let (v2, s2) = make_check("1965-09-25 11:19:33.100314");
|
||||
let (v3, s3) = make_check("2010-02-09 23:11:45.1202");
|
||||
test_array_params!("TIMESTAMP", v1, s1, v2, s2, v3, s3);
|
||||
test_array_params!("TIMESTAMPTZ", v1, s1, v2, s2, v3, s3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tsrangearray_params() {
|
||||
fn make_check<'a>(time: &'a str) -> (Timespec, &'a str) {
|
||||
(time::strptime(time, "%Y-%m-%d").unwrap().to_timespec(), time)
|
||||
}
|
||||
let (v1, s1) = make_check("1970-10-11");
|
||||
let (v2, s2) = make_check("1990-01-01");
|
||||
let r1 = range!('(', ')');
|
||||
let rs1 = "\"(,)\"";
|
||||
let r2 = range!('[' v1, ')');
|
||||
let rs2 = format!("\"[{},)\"", s1);
|
||||
let r3 = range!('(', v2 ')');
|
||||
let rs3 = format!("\"(,{})\"", s2);
|
||||
test_array_params!("TSRANGE", r1, rs1, r2, rs2, r3, rs3);
|
||||
test_array_params!("TSTZRANGE", r1, rs1, r2, rs2, r3, rs3);
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
extern crate uuid;
|
||||
|
||||
use postgres::types::array::ArrayBase;
|
||||
|
||||
use types::test_type;
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user