From 9a87c6e18a25cc7cd07f15b35a1b7bb0bf20c1a7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 17 Nov 2014 19:11:32 -0800 Subject: [PATCH] Make time support optional --- Cargo.toml | 3 +- README.md | 10 +++- src/lib.rs | 5 +- src/types/mod.rs | 119 ++++++++++++++++++++------------------------ src/types/range.rs | 7 --- src/types/time.rs | 53 ++++++++++++++++++++ src/types/uuid.rs | 9 +--- tests/test.rs | 1 - tests/types/mod.rs | 115 ++++++++++-------------------------------- tests/types/time.rs | 70 ++++++++++++++++++++++++++ tests/types/uuid.rs | 2 - 11 files changed, 219 insertions(+), 175 deletions(-) create mode 100644 src/types/time.rs create mode 100644 tests/types/time.rs diff --git a/Cargo.toml b/Cargo.toml index 25a8c967..6160e0a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/README.md b/README.md index 14fe7198..10f15dd8 100644 --- a/README.md +++ b/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] diff --git a/src/lib.rs b/src/lib.rs index a07bc6e4..a34db109 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/types/mod.rs b/src/types/mod.rs index e51b5e81..0ecf45e0 100644 --- a/src/types/mod.rs +++ b/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(rdr: &mut R) -> Result> { + 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>) - -> Result> { + impl ::types::FromSql for Option<$t> { + fn from_sql(ty: &Type, raw: &Option>) -> Result> { 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>) - -> Result<$t> { + impl ::types::FromSql for $t { + fn from_sql(ty: &Type, raw: &Option>) -> Result<$t> { + use Error; + use types::FromSql; + // FIXME when you can specify Self types properly let ret: Result> = 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| { + 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>, |buf: &Vec| { + from_map_impl!($($oid)|+, ::types::array::ArrayBase>, |buf: &Vec| { + 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(&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>> { 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>> { + 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> { + impl ::types::ToSql for ::types::array::ArrayBase> { fn to_sql(&self, ty: &Type) -> Result>> { + 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> $(, $a)*) + to_option_impl!($($oid)|+, ::types::array::ArrayBase> $(, $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(raw: &mut R) -> Result { - 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(raw: &mut R) -> Result { @@ -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) from_raw_from_impl!(Int8Range, Range) -from_raw_from_impl!(TsRange | TstzRange, Range) from_array_impl!(BoolArray, bool) from_array_impl!(ByteAArray, Vec) @@ -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) -from_array_impl!(TsRangeArray | TstzRangeArray, Range) from_array_impl!(Int8RangeArray, Range) impl FromSql for Option>> { @@ -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(&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(&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) to_raw_to_impl!(Int8Range, Range) -to_raw_to_impl!(TsRange | TstzRange, Range) impl<'a> ToSql for &'a str { fn to_sql(&self, ty: &Type) -> Result>> { @@ -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) 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) -to_array_impl!(TsRangeArray | TstzRangeArray, Range) to_array_impl!(Int8RangeArray, Range) to_array_impl!(JsonArray, json::Json) diff --git a/src/types/range.rs b/src/types/range.rs index 9d39547c..4a0cc738 100644 --- a/src/types/range.rs +++ b/src/types/range.rs @@ -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(bound: RangeBound) -> RangeBound { - bound - } -} - /// The possible sides of a bound #[deriving(PartialEq, Eq)] pub enum BoundSide { diff --git a/src/types/time.rs b/src/types/time.rs new file mode 100644 index 00000000..19a96e6d --- /dev/null +++ b/src/types/time.rs @@ -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(raw: &mut R) -> Result { + 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) +from_array_impl!(Type::TimestampArray | Type::TimestampTZArray, Timespec) +from_array_impl!(Type::TsRangeArray | Type::TstzRangeArray, Range) + +impl RawToSql for Timespec { + fn raw_to_sql(&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) +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) + +impl Normalizable for Timespec { + fn normalize(bound: RangeBound) -> RangeBound { + bound + } +} + diff --git a/src/types/uuid.rs b/src/types/uuid.rs index 131fecc4..16e3486e 100644 --- a/src/types/uuid.rs +++ b/src/types/uuid.rs @@ -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 { diff --git a/tests/test.rs b/tests/test.rs index 26b904cf..cab739ec 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -3,7 +3,6 @@ #[phase(plugin, link)] extern crate postgres; extern crate serialize; -extern crate time; extern crate url; extern crate openssl; diff --git a/tests/types/mod.rs b/tests/types/mod.rs index fa49a4d1..621adfb4 100644 --- a/tests/types/mod.rs +++ b/tests/types/mod.rs @@ -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(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, &'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", diff --git a/tests/types/time.rs b/tests/types/time.rs new file mode 100644 index 00000000..46a14c49 --- /dev/null +++ b/tests/types/time.rs @@ -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, &'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); +} + diff --git a/tests/types/uuid.rs b/tests/types/uuid.rs index 635f7095..863dcd41 100644 --- a/tests/types/uuid.rs +++ b/tests/types/uuid.rs @@ -1,7 +1,5 @@ extern crate uuid; -use postgres::types::array::ArrayBase; - use types::test_type; #[test]