Make time support optional
This commit is contained in:
parent
22f4be2b8c
commit
9a87c6e18a
@ -13,7 +13,7 @@ name = "test"
|
|||||||
path = "tests/test.rs"
|
path = "tests/test.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["uuid"]
|
default = ["uuid", "time"]
|
||||||
|
|
||||||
[dependencies.openssl]
|
[dependencies.openssl]
|
||||||
git = "https://github.com/sfackler/rust-openssl"
|
git = "https://github.com/sfackler/rust-openssl"
|
||||||
@ -30,6 +30,7 @@ optional = true
|
|||||||
|
|
||||||
[dependencies.time]
|
[dependencies.time]
|
||||||
git = "https://github.com/rust-lang/time"
|
git = "https://github.com/rust-lang/time"
|
||||||
|
optional = true
|
||||||
|
|
||||||
[dev-dependencies.url]
|
[dev-dependencies.url]
|
||||||
git = "https://github.com/servo/rust-url"
|
git = "https://github.com/servo/rust-url"
|
||||||
|
10
README.md
10
README.md
@ -297,8 +297,14 @@ traits.
|
|||||||
### UUID type
|
### UUID type
|
||||||
|
|
||||||
[UUID](http://www.postgresql.org/docs/9.4/static/datatype-uuid.html) support is
|
[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
|
provided optionally by the `uuid` feature. It is enabled by default.
|
||||||
`UUID` support, add `default-features = false` to your Cargo manifest:
|
|
||||||
|
### 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
|
```toml
|
||||||
[dependencies.postgres]
|
[dependencies.postgres]
|
||||||
|
@ -4,8 +4,11 @@
|
|||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! extern crate postgres;
|
//! extern crate postgres;
|
||||||
|
//! # #[cfg(feature = "time")]
|
||||||
//! extern crate time;
|
//! extern crate time;
|
||||||
//!
|
//!
|
||||||
|
//! # #[cfg(not(feature = "time"))] fn main() {}
|
||||||
|
//! # #[cfg(feature = "time")] fn main() {
|
||||||
//! use time::Timespec;
|
//! use time::Timespec;
|
||||||
//!
|
//!
|
||||||
//! use postgres::{Connection, SslMode};
|
//! use postgres::{Connection, SslMode};
|
||||||
@ -49,6 +52,7 @@
|
|||||||
//! println!("Found person {}", person.name);
|
//! println!("Found person {}", person.name);
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
#![doc(html_root_url="https://sfackler.github.io/doc")]
|
#![doc(html_root_url="https://sfackler.github.io/doc")]
|
||||||
#![feature(globs, macro_rules, phase, unsafe_destructor, slicing_syntax, default_type_params, if_let)]
|
#![feature(globs, macro_rules, phase, unsafe_destructor, slicing_syntax, default_type_params, if_let)]
|
||||||
@ -56,7 +60,6 @@
|
|||||||
|
|
||||||
extern crate openssl;
|
extern crate openssl;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
extern crate time;
|
|
||||||
extern crate phf;
|
extern crate phf;
|
||||||
#[phase(plugin)]
|
#[phase(plugin)]
|
||||||
extern crate phf_mac;
|
extern crate phf_mac;
|
||||||
|
119
src/types/mod.rs
119
src/types/mod.rs
@ -3,20 +3,17 @@
|
|||||||
|
|
||||||
use serialize::json;
|
use serialize::json;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::{AsRefReader, MemWriter, BufReader};
|
use std::io::{ByRefReader, MemWriter, BufReader};
|
||||||
use std::io::util::LimitReader;
|
|
||||||
use time::Timespec;
|
|
||||||
|
|
||||||
use Result;
|
use Result;
|
||||||
use error::{PgWrongType, PgWasNull, PgBadData};
|
use error::{PgWrongType, PgWasNull, PgBadData};
|
||||||
use types::array::{Array, ArrayBase, DimensionInfo};
|
use types::range::{Inclusive, Exclusive, Range};
|
||||||
use types::range::{RangeBound, Inclusive, Exclusive, Range};
|
|
||||||
|
|
||||||
macro_rules! check_types(
|
macro_rules! check_types(
|
||||||
($($expected:pat)|+, $actual:ident) => (
|
($($expected:pat)|+, $actual:ident) => (
|
||||||
match $actual {
|
match $actual {
|
||||||
$(&$expected)|+ => {}
|
$(&$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(
|
macro_rules! from_range_impl(
|
||||||
($t:ty) => (
|
($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>> {
|
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());
|
let t = try!(rdr.read_i8());
|
||||||
|
|
||||||
if t & RANGE_EMPTY != 0 {
|
if t & RANGE_EMPTY != 0 {
|
||||||
@ -43,8 +46,8 @@ macro_rules! from_range_impl(
|
|||||||
let lower = match t & RANGE_LOWER_UNBOUNDED {
|
let lower = match t & RANGE_LOWER_UNBOUNDED {
|
||||||
0 => {
|
0 => {
|
||||||
let type_ = match t & RANGE_LOWER_INCLUSIVE {
|
let type_ = match t & RANGE_LOWER_INCLUSIVE {
|
||||||
0 => Exclusive,
|
0 => BoundType::Exclusive,
|
||||||
_ => Inclusive
|
_ => BoundType::Inclusive
|
||||||
};
|
};
|
||||||
let len = try!(rdr.read_be_i32()) as uint;
|
let len = try!(rdr.read_be_i32()) as uint;
|
||||||
let mut limit = LimitReader::new(rdr.by_ref(), len);
|
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 {
|
let upper = match t & RANGE_UPPER_UNBOUNDED {
|
||||||
0 => {
|
0 => {
|
||||||
let type_ = match t & RANGE_UPPER_INCLUSIVE {
|
let type_ = match t & RANGE_UPPER_INCLUSIVE {
|
||||||
0 => Exclusive,
|
0 => BoundType::Exclusive,
|
||||||
_ => Inclusive
|
_ => BoundType::Inclusive
|
||||||
};
|
};
|
||||||
let len = try!(rdr.read_be_i32()) as uint;
|
let len = try!(rdr.read_be_i32()) as uint;
|
||||||
let mut limit = LimitReader::new(rdr.by_ref(), len);
|
let mut limit = LimitReader::new(rdr.by_ref(), len);
|
||||||
@ -81,9 +84,8 @@ macro_rules! from_range_impl(
|
|||||||
macro_rules! from_map_impl(
|
macro_rules! from_map_impl(
|
||||||
($($expected:pat)|+, $t:ty, $blk:expr $(, $a:meta)*) => (
|
($($expected:pat)|+, $t:ty, $blk:expr $(, $a:meta)*) => (
|
||||||
$(#[$a])*
|
$(#[$a])*
|
||||||
impl FromSql for Option<$t> {
|
impl ::types::FromSql for Option<$t> {
|
||||||
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>)
|
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>) -> Result<Option<$t>> {
|
||||||
-> Result<Option<$t>> {
|
|
||||||
check_types!($($expected)|+, ty)
|
check_types!($($expected)|+, ty)
|
||||||
match *raw {
|
match *raw {
|
||||||
Some(ref buf) => ($blk)(buf).map(|ok| Some(ok)),
|
Some(ref buf) => ($blk)(buf).map(|ok| Some(ok)),
|
||||||
@ -93,14 +95,16 @@ macro_rules! from_map_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(#[$a])*
|
$(#[$a])*
|
||||||
impl FromSql for $t {
|
impl ::types::FromSql for $t {
|
||||||
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>)
|
fn from_sql(ty: &Type, raw: &Option<Vec<u8>>) -> Result<$t> {
|
||||||
-> Result<$t> {
|
use Error;
|
||||||
|
use types::FromSql;
|
||||||
|
|
||||||
// FIXME when you can specify Self types properly
|
// FIXME when you can specify Self types properly
|
||||||
let ret: Result<Option<$t>> = FromSql::from_sql(ty, raw);
|
let ret: Result<Option<$t>> = FromSql::from_sql(ty, raw);
|
||||||
match ret {
|
match ret {
|
||||||
Ok(Some(val)) => Ok(val),
|
Ok(Some(val)) => Ok(val),
|
||||||
Ok(None) => Err(PgWasNull),
|
Ok(None) => Err(Error::PgWasNull),
|
||||||
Err(err) => Err(err)
|
Err(err) => Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +115,9 @@ macro_rules! from_map_impl(
|
|||||||
macro_rules! from_raw_from_impl(
|
macro_rules! from_raw_from_impl(
|
||||||
($($expected:pat)|+, $t:ty $(, $a:meta)*) => (
|
($($expected:pat)|+, $t:ty $(, $a:meta)*) => (
|
||||||
from_map_impl!($($expected)|+, $t, |buf: &Vec<u8>| {
|
from_map_impl!($($expected)|+, $t, |buf: &Vec<u8>| {
|
||||||
|
use std::io::BufReader;
|
||||||
|
use types::RawFromSql;
|
||||||
|
|
||||||
let mut reader = BufReader::new(buf[]);
|
let mut reader = BufReader::new(buf[]);
|
||||||
RawFromSql::raw_from_sql(&mut reader)
|
RawFromSql::raw_from_sql(&mut reader)
|
||||||
} $(, $a)*)
|
} $(, $a)*)
|
||||||
@ -119,7 +126,12 @@ macro_rules! from_raw_from_impl(
|
|||||||
|
|
||||||
macro_rules! from_array_impl(
|
macro_rules! from_array_impl(
|
||||||
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
($($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 mut rdr = BufReader::new(buf[]);
|
||||||
|
|
||||||
let ndim = try!(rdr.read_be_i32()) as uint;
|
let ndim = try!(rdr.read_be_i32()) as uint;
|
||||||
@ -164,20 +176,29 @@ macro_rules! raw_to_impl(
|
|||||||
|
|
||||||
macro_rules! to_range_impl(
|
macro_rules! to_range_impl(
|
||||||
($t:ty) => (
|
($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<()> {
|
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;
|
let mut tag = 0;
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
tag |= RANGE_EMPTY;
|
tag |= RANGE_EMPTY;
|
||||||
} else {
|
} else {
|
||||||
match self.lower() {
|
match self.lower() {
|
||||||
None => tag |= RANGE_LOWER_UNBOUNDED,
|
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() {
|
match self.upper() {
|
||||||
None => tag |= RANGE_UPPER_UNBOUNDED,
|
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(
|
macro_rules! to_option_impl(
|
||||||
($($oid:pat)|+, $t:ty $(,$a:meta)*) => (
|
($($oid:pat)|+, $t:ty $(,$a:meta)*) => (
|
||||||
$(#[$a])*
|
$(#[$a])*
|
||||||
impl ToSql for Option<$t> {
|
impl ::types::ToSql for Option<$t> {
|
||||||
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
||||||
check_types!($($oid)|+, ty)
|
check_types!($($oid)|+, ty)
|
||||||
|
|
||||||
@ -245,8 +266,10 @@ macro_rules! to_option_impl_lifetime(
|
|||||||
macro_rules! to_raw_to_impl(
|
macro_rules! to_raw_to_impl(
|
||||||
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
||||||
$(#[$a])*
|
$(#[$a])*
|
||||||
impl ToSql for $t {
|
impl ::types::ToSql for $t {
|
||||||
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
||||||
|
use std::io::MemWriter;
|
||||||
|
|
||||||
check_types!($($oid)|+, ty)
|
check_types!($($oid)|+, ty)
|
||||||
|
|
||||||
let mut writer = MemWriter::new();
|
let mut writer = MemWriter::new();
|
||||||
@ -262,8 +285,11 @@ macro_rules! to_raw_to_impl(
|
|||||||
macro_rules! to_array_impl(
|
macro_rules! to_array_impl(
|
||||||
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
($($oid:pat)|+, $t:ty $(, $a:meta)*) => (
|
||||||
$(#[$a])*
|
$(#[$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>>> {
|
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
||||||
|
use std::io::MemWriter;
|
||||||
|
use types::array::Array;
|
||||||
|
|
||||||
check_types!($($oid)|+, ty)
|
check_types!($($oid)|+, ty)
|
||||||
let mut buf = MemWriter::new();
|
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;
|
pub mod range;
|
||||||
#[cfg(feature = "uuid")]
|
#[cfg(feature = "uuid")]
|
||||||
mod uuid;
|
mod uuid;
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
mod time;
|
||||||
|
|
||||||
/// A Postgres OID
|
/// A Postgres OID
|
||||||
pub type Oid = u32;
|
pub type Oid = u32;
|
||||||
@ -347,12 +375,6 @@ const TSTZRANGEARRAYOID: Oid = 3911;
|
|||||||
const INT8RANGEOID: Oid = 3926;
|
const INT8RANGEOID: Oid = 3926;
|
||||||
const INT8RANGEARRAYOID: Oid = 3927;
|
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_UPPER_UNBOUNDED: i8 = 0b0001_0000;
|
||||||
const RANGE_LOWER_UNBOUNDED: i8 = 0b0000_1000;
|
const RANGE_LOWER_UNBOUNDED: i8 = 0b0000_1000;
|
||||||
const RANGE_UPPER_INCLUSIVE: i8 = 0b0000_0100;
|
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!(f32, read_be_f32)
|
||||||
raw_from_impl!(f64, read_be_f64)
|
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!(i32)
|
||||||
from_range_impl!(i64)
|
from_range_impl!(i64)
|
||||||
from_range_impl!(Timespec)
|
|
||||||
|
|
||||||
impl RawFromSql for json::Json {
|
impl RawFromSql for json::Json {
|
||||||
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<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!(Float8, f64)
|
||||||
from_raw_from_impl!(Json, json::Json)
|
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!(Int4Range, Range<i32>)
|
||||||
from_raw_from_impl!(Int8Range, Range<i64>)
|
from_raw_from_impl!(Int8Range, Range<i64>)
|
||||||
from_raw_from_impl!(TsRange | TstzRange, Range<Timespec>)
|
|
||||||
|
|
||||||
from_array_impl!(BoolArray, bool)
|
from_array_impl!(BoolArray, bool)
|
||||||
from_array_impl!(ByteAArray, Vec<u8>)
|
from_array_impl!(ByteAArray, Vec<u8>)
|
||||||
@ -576,12 +580,10 @@ from_array_impl!(Int2Array, i16)
|
|||||||
from_array_impl!(Int4Array, i32)
|
from_array_impl!(Int4Array, i32)
|
||||||
from_array_impl!(TextArray | CharNArray | VarcharArray | NameArray, String)
|
from_array_impl!(TextArray | CharNArray | VarcharArray | NameArray, String)
|
||||||
from_array_impl!(Int8Array, i64)
|
from_array_impl!(Int8Array, i64)
|
||||||
from_array_impl!(TimestampArray | TimestampTZArray, Timespec)
|
|
||||||
from_array_impl!(JsonArray, json::Json)
|
from_array_impl!(JsonArray, json::Json)
|
||||||
from_array_impl!(Float4Array, f32)
|
from_array_impl!(Float4Array, f32)
|
||||||
from_array_impl!(Float8Array, f64)
|
from_array_impl!(Float8Array, f64)
|
||||||
from_array_impl!(Int4RangeArray, Range<i32>)
|
from_array_impl!(Int4RangeArray, Range<i32>)
|
||||||
from_array_impl!(TsRangeArray | TstzRangeArray, Range<Timespec>)
|
|
||||||
from_array_impl!(Int8RangeArray, Range<i64>)
|
from_array_impl!(Int8RangeArray, Range<i64>)
|
||||||
|
|
||||||
impl FromSql for Option<HashMap<String, Option<String>>> {
|
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!(f32, write_be_f32)
|
||||||
raw_to_impl!(f64, write_be_f64)
|
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!(i32)
|
||||||
to_range_impl!(i64)
|
to_range_impl!(i64)
|
||||||
to_range_impl!(Timespec)
|
|
||||||
|
|
||||||
impl RawToSql for json::Json {
|
impl RawToSql for json::Json {
|
||||||
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> Result<()> {
|
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!(Float8, f64)
|
||||||
to_raw_to_impl!(Int4Range, Range<i32>)
|
to_raw_to_impl!(Int4Range, Range<i32>)
|
||||||
to_raw_to_impl!(Int8Range, Range<i64>)
|
to_raw_to_impl!(Int8Range, Range<i64>)
|
||||||
to_raw_to_impl!(TsRange | TstzRange, Range<Timespec>)
|
|
||||||
|
|
||||||
impl<'a> ToSql for &'a str {
|
impl<'a> ToSql for &'a str {
|
||||||
fn to_sql(&self, ty: &Type) -> Result<Option<Vec<u8>>> {
|
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_option_impl_lifetime!(ByteA, &'a [u8])
|
||||||
|
|
||||||
to_raw_to_impl!(Timestamp | TimestampTZ, Timespec)
|
|
||||||
|
|
||||||
to_array_impl!(BoolArray, bool)
|
to_array_impl!(BoolArray, bool)
|
||||||
to_array_impl!(ByteAArray, Vec<u8>)
|
to_array_impl!(ByteAArray, Vec<u8>)
|
||||||
to_array_impl!(CharArray, i8)
|
to_array_impl!(CharArray, i8)
|
||||||
@ -736,11 +727,9 @@ to_array_impl!(Int2Array, i16)
|
|||||||
to_array_impl!(Int4Array, i32)
|
to_array_impl!(Int4Array, i32)
|
||||||
to_array_impl!(Int8Array, i64)
|
to_array_impl!(Int8Array, i64)
|
||||||
to_array_impl!(TextArray | CharNArray | VarcharArray | NameArray, String)
|
to_array_impl!(TextArray | CharNArray | VarcharArray | NameArray, String)
|
||||||
to_array_impl!(TimestampArray | TimestampTZArray, Timespec)
|
|
||||||
to_array_impl!(Float4Array, f32)
|
to_array_impl!(Float4Array, f32)
|
||||||
to_array_impl!(Float8Array, f64)
|
to_array_impl!(Float8Array, f64)
|
||||||
to_array_impl!(Int4RangeArray, Range<i32>)
|
to_array_impl!(Int4RangeArray, Range<i32>)
|
||||||
to_array_impl!(TsRangeArray | TstzRangeArray, Range<Timespec>)
|
|
||||||
to_array_impl!(Int8RangeArray, Range<i64>)
|
to_array_impl!(Int8RangeArray, Range<i64>)
|
||||||
to_array_impl!(JsonArray, json::Json)
|
to_array_impl!(JsonArray, json::Json)
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::i32;
|
use std::i32;
|
||||||
use std::i64;
|
use std::i64;
|
||||||
use time::Timespec;
|
|
||||||
|
|
||||||
/// The `range!` macro can make it easier to create ranges. It roughly mirrors
|
/// The `range!` macro can make it easier to create ranges. It roughly mirrors
|
||||||
/// traditional mathematic range syntax.
|
/// traditional mathematic range syntax.
|
||||||
@ -131,12 +130,6 @@ macro_rules! bounded_normalizable(
|
|||||||
bounded_normalizable!(i32)
|
bounded_normalizable!(i32)
|
||||||
bounded_normalizable!(i64)
|
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
|
/// The possible sides of a bound
|
||||||
#[deriving(PartialEq, Eq)]
|
#[deriving(PartialEq, Eq)]
|
||||||
pub enum BoundSide {
|
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;
|
extern crate uuid;
|
||||||
|
|
||||||
use std::io::{MemWriter, BufReader};
|
|
||||||
use std::io::util::LimitReader;
|
|
||||||
use std::io::ByRefReader;
|
|
||||||
|
|
||||||
use self::uuid::Uuid;
|
use self::uuid::Uuid;
|
||||||
use types::{RawFromSql, FromSql, ToSql, RawToSql, Type, Oid};
|
use types::{RawFromSql, ToSql, RawToSql, Type};
|
||||||
use Error::{PgWasNull, PgWrongType, PgBadData};
|
use Error::{PgWasNull, PgBadData};
|
||||||
use types::array::{ArrayBase, DimensionInfo, Array};
|
|
||||||
use Result;
|
use Result;
|
||||||
|
|
||||||
impl RawFromSql for Uuid {
|
impl RawFromSql for Uuid {
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#[phase(plugin, link)]
|
#[phase(plugin, link)]
|
||||||
extern crate postgres;
|
extern crate postgres;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
extern crate time;
|
|
||||||
extern crate url;
|
extern crate url;
|
||||||
extern crate openssl;
|
extern crate openssl;
|
||||||
|
|
||||||
|
@ -2,16 +2,16 @@ use serialize::json;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::f64;
|
use std::f64;
|
||||||
use time;
|
|
||||||
use time::Timespec;
|
|
||||||
use std::num::Float;
|
use std::num::Float;
|
||||||
|
|
||||||
use postgres::{Connection, SslMode};
|
use postgres::{Connection, SslMode};
|
||||||
use postgres::types::array::ArrayBase;
|
|
||||||
use postgres::types::{ToSql, FromSql};
|
use postgres::types::{ToSql, FromSql};
|
||||||
|
|
||||||
macro_rules! test_array_params(
|
macro_rules! test_array_params(
|
||||||
($name:expr, $v1:expr, $s1:expr, $v2:expr, $s2:expr, $v3:expr, $s3:expr) => ({
|
($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)),
|
let tests = [(Some(ArrayBase::from_vec(vec!(Some($v1), Some($v2), None), 1)),
|
||||||
format!("'{{{},{},NULL}}'", $s1, $s2).into_string()),
|
format!("'{{{},{},NULL}}'", $s1, $s2).into_string()),
|
||||||
(None, "NULL".to_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 array;
|
||||||
mod range;
|
mod range;
|
||||||
#[cfg(feature = "uuid")]
|
#[cfg(feature = "uuid")]
|
||||||
mod uuid;
|
mod uuid;
|
||||||
|
#[cfg(feature = "time")]
|
||||||
|
mod time;
|
||||||
|
|
||||||
fn test_type<T: PartialEq+FromSql+ToSql, S: Str>(sql_type: &str, checks: &[(T, S)]) {
|
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));
|
let conn = or_panic!(Connection::connect("postgres://postgres@localhost", &SslMode::None));
|
||||||
@ -140,44 +163,6 @@ fn test_json_params() {
|
|||||||
(None, "NULL")])
|
(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]
|
#[test]
|
||||||
fn test_int4range_params() {
|
fn test_int4range_params() {
|
||||||
test_range!("INT4RANGE", i32, 100i32, "100", 200i32, "200")
|
test_range!("INT4RANGE", i32, 100i32, "100", 200i32, "200")
|
||||||
@ -188,25 +173,6 @@ fn test_int8range_params() {
|
|||||||
test_range!("INT8RANGE", i64, 100i64, "100", 200i64, "200")
|
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]
|
#[test]
|
||||||
fn test_boolarray_params() {
|
fn test_boolarray_params() {
|
||||||
test_array_params!("BOOL", false, "f", true, "t", true, "t");
|
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_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]
|
#[test]
|
||||||
fn test_float4array_params() {
|
fn test_float4array_params() {
|
||||||
test_array_params!("FLOAT4", 0f32, "0", 1.5f32, "1.5", 0.009f32, ".009");
|
test_array_params!("FLOAT4", 0f32, "0", 1.5f32, "1.5", 0.009f32, ".009");
|
||||||
@ -293,23 +247,6 @@ fn test_int4rangearray_params() {
|
|||||||
range!('(', 10i32 ')'), "\"(,10)\"");
|
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]
|
#[test]
|
||||||
fn test_int8rangearray_params() {
|
fn test_int8rangearray_params() {
|
||||||
test_array_params!("INT8RANGE",
|
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;
|
extern crate uuid;
|
||||||
|
|
||||||
use postgres::types::array::ArrayBase;
|
|
||||||
|
|
||||||
use types::test_type;
|
use types::test_type;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user