Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ language: rust
rust:
- nightly
- beta
- 1.10.0
- 1.20.0
addons:
postgresql: 9.4
script:
Expand Down
14 changes: 5 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
[package]
name = "postgres_range"
version = "0.8.2"
version = "0.9.0"
authors = ["Steven Fackler <sfackler@gmail.com>"]
license = "MIT"
description = "Range support for rust-postgres"
repository = "https://github.com/sfackler/rust-postgres-range"
documentation = "https://sfackler.github.io/rust-postgres-range/doc/v0.8.2/postgres_range"
documentation = "https://sfackler.github.io/rust-postgres-range/doc/v0.9.0/postgres_range"

[dependencies]
time = "0.1"
postgres = "0.11"
postgres-protocol = { git = "https://github.com/sfackler/rust-postgres-protocol" }
postgres = "0.15"
postgres-protocol = "0.3"

[dev-dependencies]
postgres = { version = "0.11", features = ["with-time"] }

[replace]
"postgres:0.11.11" = { git = "https://github.com/sfackler/rust-postgres" }
"fallible-iterator:0.1.2" = { git = "https://github.com/sfackler/rust-fallible-iterator" }
postgres = { version = "0.15", features = ["with-time"] }
76 changes: 43 additions & 33 deletions src/impls.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
use std::error::Error;
use postgres::types::{Type, Kind, ToSql, FromSql, IsNull, SessionInfo};
use postgres_protocol::types;
use postgres::types::{FromSql, IsNull, Kind, ToSql, Type};
use postgres_protocol::{self as protocol, types};

use {Range, RangeBound, BoundType, BoundSided, Normalizable};
use {BoundSided, BoundType, Normalizable, Range, RangeBound};

impl<T> FromSql for Range<T> where T: PartialOrd+Normalizable+FromSql {
fn from_sql(ty: &Type, raw: &[u8], info: &SessionInfo) -> Result<Range<T>, Box<Error + Sync + Send>> {
impl<T> FromSql for Range<T>
where
T: PartialOrd + Normalizable + FromSql,
{
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Range<T>, Box<Error + Sync + Send>> {
let element_type = match ty.kind() {
&Kind::Range(ref ty) => ty,
_ => panic!("unexpected type {:?}", ty)
_ => panic!("unexpected type {:?}", ty),
};

match try!(types::range_from_sql(raw)) {
match types::range_from_sql(raw)? {
types::Range::Empty => Ok(Range::empty()),
types::Range::Nonempty(lower, upper) => {
let lower = try!(bound_from_sql(lower, element_type, info));
let upper = try!(bound_from_sql(upper, element_type, info));
let lower = bound_from_sql(lower, element_type)?;
let upper = bound_from_sql(upper, element_type)?;
Ok(Range::new(lower, upper))
}
}
Expand All @@ -29,42 +32,48 @@ impl<T> FromSql for Range<T> where T: PartialOrd+Normalizable+FromSql {
}
}

fn bound_from_sql<T, S>(bound: types::RangeBound<Option<&[u8]>>, ty: &Type, info: &SessionInfo) -> Result<Option<RangeBound<S, T>>, Box<Error + Sync + Send>>
where T: PartialOrd + Normalizable + FromSql,
S: BoundSided
fn bound_from_sql<T, S>(bound: types::RangeBound<Option<&[u8]>>, ty: &Type) -> Result<Option<RangeBound<S, T>>, Box<Error + Sync + Send>>
where
T: PartialOrd + Normalizable + FromSql,
S: BoundSided,
{
match bound {
types::RangeBound::Exclusive(value) => {
let value = match value {
Some(value) => try!(T::from_sql(ty, value, info)),
None => try!(T::from_sql_null(ty, info)),
Some(value) => T::from_sql(ty, value)?,
None => T::from_sql_null(ty)?,
};
Ok(Some(RangeBound::new(value, BoundType::Exclusive)))
},
}
types::RangeBound::Inclusive(value) => {
let value = match value {
Some(value) => try!(T::from_sql(ty, value, info)),
None => try!(T::from_sql_null(ty, info)),
Some(value) => T::from_sql(ty, value)?,
None => T::from_sql_null(ty)?,
};
Ok(Some(RangeBound::new(value, BoundType::Inclusive)))
},
}
types::RangeBound::Unbounded => Ok(None),
}
}

impl<T> ToSql for Range<T> where T: PartialOrd+Normalizable+ToSql {
fn to_sql(&self, ty: &Type, mut buf: &mut Vec<u8>, info: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
impl<T> ToSql for Range<T>
where
T: PartialOrd + Normalizable + ToSql,
{
fn to_sql(&self, ty: &Type, buf: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
let element_type = match ty.kind() {
&Kind::Range(ref ty) => ty,
_ => panic!("unexpected type {:?}", ty)
_ => panic!("unexpected type {:?}", ty),
};

if self.is_empty() {
types::empty_range_to_sql(buf);
} else {
try!(types::range_to_sql(|buf| bound_to_sql(self.lower(), element_type, info, buf),
|buf| bound_to_sql(self.upper(), element_type, info, buf),
buf));
types::range_to_sql(
|buf| bound_to_sql(self.lower(), element_type, buf),
|buf| bound_to_sql(self.upper(), element_type, buf),
buf,
)?;
}

Ok(IsNull::No)
Expand All @@ -80,15 +89,16 @@ impl<T> ToSql for Range<T> where T: PartialOrd+Normalizable+ToSql {
to_sql_checked!();
}

fn bound_to_sql<S, T>(bound: Option<&RangeBound<S, T>>, ty: &Type, info: &SessionInfo, buf: &mut Vec<u8>) -> Result<types::RangeBound<types::IsNull>, Box<Error + Sync + Send>>
where S: BoundSided,
T: ToSql
fn bound_to_sql<S, T>(bound: Option<&RangeBound<S, T>>, ty: &Type, buf: &mut Vec<u8>) -> Result<types::RangeBound<protocol::IsNull>, Box<Error + Sync + Send>>
where
S: BoundSided,
T: ToSql,
{
match bound {
Some(bound) => {
let null = match try!(bound.value.to_sql(ty, buf, info)) {
IsNull::Yes => types::IsNull::Yes,
IsNull::No => types::IsNull::No,
let null = match bound.value.to_sql(ty, buf)? {
IsNull::Yes => protocol::IsNull::Yes,
IsNull::No => protocol::IsNull::No,
};

match bound.type_ {
Expand All @@ -98,7 +108,6 @@ fn bound_to_sql<S, T>(bound: Option<&RangeBound<S, T>>, ty: &Type, info: &Sessio
}
None => Ok(types::RangeBound::Unbounded),
}

}

#[cfg(test)]
Expand Down Expand Up @@ -130,10 +139,11 @@ mod test {
})
}

fn test_type<T: PartialEq+FromSql+ToSql, S: fmt::Display>(sql_type: &str, checks: &[(T, S)]) {
fn test_type<T: PartialEq + FromSql + ToSql, S: fmt::Display>(sql_type: &str, checks: &[(T, S)]) {
let conn = Connection::connect("postgres://postgres@localhost", TlsMode::None).unwrap();
for &(ref val, ref repr) in checks {
let stmt = conn.prepare(&*format!("SELECT {}::{}", *repr, sql_type)).unwrap();
let stmt = conn.prepare(&*format!("SELECT {}::{}", *repr, sql_type))
.unwrap();
let result = stmt.query(&[]).unwrap().iter().next().unwrap().get(0);
assert!(val == &result);

Expand Down
Loading