Skip to content

Commit f5ec24d

Browse files
committed
Use type conversions from protocol crate
This also changes ToSql and FromSql to explicitly deal in byte buffers.
1 parent ff85381 commit f5ec24d

File tree

16 files changed

+234
-432
lines changed

16 files changed

+234
-432
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ uuid = { version = ">= 0.1, < 0.4", optional = true }
5252

5353
[dev-dependencies]
5454
url = "1.0"
55+
56+
[replace]
57+
"fallible-iterator:0.1.2" = { git = "https://github.com/sfackler/rust-fallible-iterator" }

codegen/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ use std::ascii::AsciiExt;
66
use std::path::Path;
77

88
mod sqlstate;
9-
mod types;
9+
mod type_gen;
1010

1111
fn main() {
1212
let path = Path::new("../src");
1313
sqlstate::build(path);
14-
types::build(path);
14+
type_gen::build(path);
1515
}
1616

1717
fn snake_to_camel(s: &str) -> String {

codegen/src/types.rs renamed to codegen/src/type_gen.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ struct Type {
2020
}
2121

2222
pub fn build(path: &Path) {
23-
let mut file = BufWriter::new(File::create(path.join("types/types.rs")).unwrap());
23+
let mut file = BufWriter::new(File::create(path.join("types/type_gen.rs")).unwrap());
2424

2525
let ranges = parse_ranges();
2626
let types = parse_types(&ranges);

src/lib.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ impl InnerConnection {
528528
let mut values = vec![];
529529
for (param, ty) in params.iter().zip(param_types) {
530530
let mut buf = vec![];
531-
match try!(param.to_sql_checked(ty, &mut buf, &SessionInfo::new(self))) {
531+
match try!(param.to_sql_checked(ty, &mut buf, &SessionInfo::new(self)).map_err(Error::Conversion)) {
532532
IsNull::Yes => values.push(None),
533533
IsNull::No => values.push(Some(buf)),
534534
}
@@ -671,18 +671,30 @@ impl InnerConnection {
671671

672672
let (name, type_, elem_oid, rngsubtype, basetype, schema, relid) = {
673673
let ctx = SessionInfo::new(self);
674-
let name = try!(String::from_sql(&Type::Name, &mut &**row[0].as_ref().unwrap(), &ctx));
675-
let type_ = try!(i8::from_sql(&Type::Char, &mut &**row[1].as_ref().unwrap(), &ctx));
676-
let elem_oid = try!(Oid::from_sql(&Type::Oid, &mut &**row[2].as_ref().unwrap(), &ctx));
674+
let name = try!(String::from_sql(&Type::Name, &mut &**row[0].as_ref().unwrap(), &ctx)
675+
.map_err(Error::Conversion));
676+
let type_ = try!(i8::from_sql(&Type::Char, &mut &**row[1].as_ref().unwrap(), &ctx)
677+
.map_err(Error::Conversion));
678+
let elem_oid = try!(Oid::from_sql(&Type::Oid, &mut &**row[2].as_ref().unwrap(), &ctx)
679+
.map_err(Error::Conversion));
677680
let rngsubtype = match row[3] {
678-
Some(ref data) => try!(Option::<Oid>::from_sql(&Type::Oid, &mut &**data, &ctx)),
679-
None => try!(Option::<Oid>::from_sql_null(&Type::Oid, &ctx)),
681+
Some(ref data) => {
682+
try!(Option::<Oid>::from_sql(&Type::Oid, &mut &**data, &ctx)
683+
.map_err(Error::Conversion))
684+
},
685+
None => {
686+
try!(Option::<Oid>::from_sql_null(&Type::Oid, &ctx)
687+
.map_err(Error::Conversion))
688+
},
680689
};
681-
let basetype = try!(Oid::from_sql(&Type::Oid, &mut &**row[4].as_ref().unwrap(), &ctx));
690+
let basetype = try!(Oid::from_sql(&Type::Oid, &mut &**row[4].as_ref().unwrap(), &ctx)
691+
.map_err(Error::Conversion));
682692
let schema = try!(String::from_sql(&Type::Name,
683693
&mut &**row[5].as_ref().unwrap(),
684-
&ctx));
685-
let relid = try!(Oid::from_sql(&Type::Oid, &mut &**row[6].as_ref().unwrap(), &ctx));
694+
&ctx)
695+
.map_err(Error::Conversion));
696+
let relid = try!(Oid::from_sql(&Type::Oid, &mut &**row[6].as_ref().unwrap(), &ctx)
697+
.map_err(Error::Conversion));
686698
(name, type_, elem_oid, rngsubtype, basetype, schema, relid)
687699
};
688700

@@ -743,7 +755,8 @@ impl InnerConnection {
743755
for row in rows {
744756
variants.push(try!(String::from_sql(&Type::Name,
745757
&mut &**row[0].as_ref().unwrap(),
746-
&ctx)));
758+
&ctx)
759+
.map_err(Error::Conversion)));
747760
}
748761

749762
Ok(variants)
@@ -778,8 +791,10 @@ impl InnerConnection {
778791
let ctx = SessionInfo::new(self);
779792
let name = try!(String::from_sql(&Type::Name,
780793
&mut &**row[0].as_ref().unwrap(),
781-
&ctx));
782-
let type_ = try!(Oid::from_sql(&Type::Oid, &mut &**row[1].as_ref().unwrap(), &ctx));
794+
&ctx)
795+
.map_err(Error::Conversion));
796+
let type_ = try!(Oid::from_sql(&Type::Oid, &mut &**row[1].as_ref().unwrap(), &ctx)
797+
.map_err(Error::Conversion));
783798
(name, type_)
784799
};
785800
let type_ = try!(self.get_type(type_));

src/rows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ impl<'a> Row<'a> {
240240
Some(ref data) => FromSql::from_sql(ty, &mut &**data, &SessionInfo::new(&*conn)),
241241
None => FromSql::from_sql_null(ty, &SessionInfo::new(&*conn)),
242242
};
243-
Some(value)
243+
Some(value.map_err(Error::Conversion))
244244
}
245245

246246
/// Retrieves the specified field as a raw buffer of Postgres data.

src/types/bit_vec.rs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
extern crate bit_vec;
22

3-
use std::io::prelude::*;
4-
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
3+
use postgres_protocol::types;
54
use self::bit_vec::BitVec;
5+
use std::error::Error;
66

7-
use Result;
8-
use types::{FromSql, ToSql, IsNull, Type, SessionInfo, downcast};
7+
use types::{FromSql, ToSql, IsNull, Type, SessionInfo};
98

109
impl FromSql for BitVec {
11-
fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<BitVec> {
12-
let len = try!(raw.read_i32::<BigEndian>()) as usize;
13-
let mut bytes = vec![];
14-
try!(raw.take(((len + 7) / 8) as u64).read_to_end(&mut bytes));
15-
16-
let mut bitvec = BitVec::from_bytes(&bytes);
17-
while bitvec.len() > len {
10+
fn from_sql(_: &Type, raw: &[u8], _: &SessionInfo) -> Result<BitVec, Box<Error + Sync + Send>> {
11+
let varbit = try!(types::varbit_from_sql(raw));
12+
let mut bitvec = BitVec::from_bytes(varbit.bytes());
13+
while bitvec.len() > varbit.len() {
1814
bitvec.pop();
1915
}
2016

@@ -25,14 +21,8 @@ impl FromSql for BitVec {
2521
}
2622

2723
impl ToSql for BitVec {
28-
fn to_sql<W: Write + ?Sized>(&self,
29-
_: &Type,
30-
mut out: &mut W,
31-
_: &SessionInfo)
32-
-> Result<IsNull> {
33-
try!(out.write_i32::<BigEndian>(try!(downcast(self.len()))));
34-
try!(out.write_all(&self.to_bytes()));
35-
24+
fn to_sql(&self, _: &Type, mut out: &mut Vec<u8>, _: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
25+
try!(types::varbit_to_sql(self.len(), self.to_bytes().into_iter(), out));
3626
Ok(IsNull::No)
3727
}
3828

src/types/chrono.rs

Lines changed: 23 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,32 @@
11
extern crate chrono;
22

3-
use std::io::prelude::*;
4-
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
3+
use postgres_protocol::types;
54
use self::chrono::{Duration, NaiveDate, NaiveTime, NaiveDateTime, DateTime, UTC, Local,
65
FixedOffset};
6+
use std::error::Error;
77

8-
use Result;
9-
use error::Error;
108
use types::{FromSql, ToSql, IsNull, Type, SessionInfo};
119

1210
fn base() -> NaiveDateTime {
1311
NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0)
1412
}
1513

1614
impl FromSql for NaiveDateTime {
17-
fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveDateTime> {
18-
let t = try!(raw.read_i64::<BigEndian>());
15+
fn from_sql(_: &Type, raw: &[u8], _: &SessionInfo) -> Result<NaiveDateTime, Box<Error + Sync + Send>> {
16+
let t = try!(types::timestamp_from_sql(raw));
1917
Ok(base() + Duration::microseconds(t))
2018
}
2119

2220
accepts!(Type::Timestamp);
2321
}
2422

2523
impl ToSql for NaiveDateTime {
26-
fn to_sql<W: Write + ?Sized>(&self,
27-
_: &Type,
28-
mut w: &mut W,
29-
_: &SessionInfo)
30-
-> Result<IsNull> {
24+
fn to_sql(&self, _: &Type, w: &mut Vec<u8>, _: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
3125
let time = match (*self - base()).num_microseconds() {
3226
Some(time) => time,
33-
None => return Err(Error::Conversion("value too large to transmit".into())),
27+
None => return Err("value too large to transmit".into()),
3428
};
35-
try!(w.write_i64::<BigEndian>(time));
29+
types::timestamp_to_sql(time, w);
3630
Ok(IsNull::No)
3731
}
3832

@@ -41,7 +35,7 @@ impl ToSql for NaiveDateTime {
4135
}
4236

4337
impl FromSql for DateTime<UTC> {
44-
fn from_sql<R: Read>(type_: &Type, raw: &mut R, info: &SessionInfo) -> Result<DateTime<UTC>> {
38+
fn from_sql(type_: &Type, raw: &[u8], info: &SessionInfo) -> Result<DateTime<UTC>, Box<Error + Sync + Send>> {
4539
let naive = try!(NaiveDateTime::from_sql(type_, raw, info));
4640
Ok(DateTime::from_utc(naive, UTC))
4741
}
@@ -50,11 +44,7 @@ impl FromSql for DateTime<UTC> {
5044
}
5145

5246
impl ToSql for DateTime<UTC> {
53-
fn to_sql<W: Write + ?Sized>(&self,
54-
type_: &Type,
55-
mut w: &mut W,
56-
info: &SessionInfo)
57-
-> Result<IsNull> {
47+
fn to_sql(&self, type_: &Type, w: &mut Vec<u8>, info: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
5848
self.naive_utc().to_sql(type_, w, info)
5949
}
6050

@@ -63,7 +53,7 @@ impl ToSql for DateTime<UTC> {
6353
}
6454

6555
impl FromSql for DateTime<Local> {
66-
fn from_sql<R: Read>(type_: &Type, raw: &mut R, info: &SessionInfo) -> Result<DateTime<Local>> {
56+
fn from_sql(type_: &Type, raw: &[u8], info: &SessionInfo) -> Result<DateTime<Local>, Box<Error + Sync + Send>> {
6757
let utc = try!(DateTime::<UTC>::from_sql(type_, raw, info));
6858
Ok(utc.with_timezone(&Local))
6959
}
@@ -72,11 +62,7 @@ impl FromSql for DateTime<Local> {
7262
}
7363

7464
impl ToSql for DateTime<Local> {
75-
fn to_sql<W: Write + ?Sized>(&self,
76-
type_: &Type,
77-
mut w: &mut W,
78-
info: &SessionInfo)
79-
-> Result<IsNull> {
65+
fn to_sql(&self, type_: &Type, mut w: &mut Vec<u8>, info: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
8066
self.with_timezone(&UTC).to_sql(type_, w, info)
8167
}
8268

@@ -85,10 +71,7 @@ impl ToSql for DateTime<Local> {
8571
}
8672

8773
impl FromSql for DateTime<FixedOffset> {
88-
fn from_sql<R: Read>(type_: &Type,
89-
raw: &mut R,
90-
info: &SessionInfo)
91-
-> Result<DateTime<FixedOffset>> {
74+
fn from_sql(type_: &Type, raw: &[u8], info: &SessionInfo) -> Result<DateTime<FixedOffset>, Box<Error + Sync + Send>> {
9275
let utc = try!(DateTime::<UTC>::from_sql(type_, raw, info));
9376
Ok(utc.with_timezone(&FixedOffset::east(0)))
9477
}
@@ -97,11 +80,7 @@ impl FromSql for DateTime<FixedOffset> {
9780
}
9881

9982
impl ToSql for DateTime<FixedOffset> {
100-
fn to_sql<W: Write + ?Sized>(&self,
101-
type_: &Type,
102-
mut w: &mut W,
103-
info: &SessionInfo)
104-
-> Result<IsNull> {
83+
fn to_sql(&self, type_: &Type, w: &mut Vec<u8>, info: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
10584
self.with_timezone(&UTC).to_sql(type_, w, info)
10685
}
10786

@@ -110,26 +89,22 @@ impl ToSql for DateTime<FixedOffset> {
11089
}
11190

11291
impl FromSql for NaiveDate {
113-
fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveDate> {
114-
let jd = try!(raw.read_i32::<BigEndian>());
92+
fn from_sql(_: &Type, raw: &[u8], _: &SessionInfo) -> Result<NaiveDate, Box<Error + Sync + Send>> {
93+
let jd = try!(types::date_from_sql(raw));
11594
Ok(base().date() + Duration::days(jd as i64))
11695
}
11796

11897
accepts!(Type::Date);
11998
}
12099

121100
impl ToSql for NaiveDate {
122-
fn to_sql<W: Write + ?Sized>(&self,
123-
_: &Type,
124-
mut w: &mut W,
125-
_: &SessionInfo)
126-
-> Result<IsNull> {
101+
fn to_sql(&self, _: &Type, w: &mut Vec<u8>, _: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
127102
let jd = (*self - base().date()).num_days();
128103
if jd > i32::max_value() as i64 || jd < i32::min_value() as i64 {
129-
return Err(Error::Conversion("value too large to transmit".into()));
104+
return Err("value too large to transmit".into());
130105
}
131106

132-
try!(w.write_i32::<BigEndian>(jd as i32));
107+
types::date_to_sql(jd as i32, w);
133108
Ok(IsNull::No)
134109
}
135110

@@ -138,26 +113,22 @@ impl ToSql for NaiveDate {
138113
}
139114

140115
impl FromSql for NaiveTime {
141-
fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveTime> {
142-
let usec = try!(raw.read_i64::<BigEndian>());
116+
fn from_sql(_: &Type, raw: &[u8], _: &SessionInfo) -> Result<NaiveTime, Box<Error + Sync + Send>> {
117+
let usec = try!(types::time_from_sql(raw));
143118
Ok(NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(usec))
144119
}
145120

146121
accepts!(Type::Time);
147122
}
148123

149124
impl ToSql for NaiveTime {
150-
fn to_sql<W: Write + ?Sized>(&self,
151-
_: &Type,
152-
mut w: &mut W,
153-
_: &SessionInfo)
154-
-> Result<IsNull> {
125+
fn to_sql(&self, _: &Type, w: &mut Vec<u8>, _: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
155126
let delta = *self - NaiveTime::from_hms(0, 0, 0);
156127
let time = match delta.num_microseconds() {
157128
Some(time) => time,
158-
None => return Err(Error::Conversion("value too large to transmit".into())),
129+
None => return Err("value too large to transmit".into()),
159130
};
160-
try!(w.write_i64::<BigEndian>(time));
131+
types::time_to_sql(time, w);
161132
Ok(IsNull::No)
162133
}
163134

src/types/eui48.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
extern crate eui48;
22

3-
use std::io::prelude::*;
4-
53
use self::eui48::MacAddress;
4+
use std::error::Error;
5+
use postgres_protocol::types;
66

77
use types::{FromSql, ToSql, Type, IsNull, SessionInfo};
8-
use Result;
98

109
impl FromSql for MacAddress {
11-
fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<MacAddress> {
12-
let mut bytes = [0; 6];
13-
try!(raw.read_exact(&mut bytes));
10+
fn from_sql(_: &Type, raw: &[u8], _: &SessionInfo) -> Result<MacAddress, Box<Error + Sync + Send>> {
11+
let bytes = try!(types::macaddr_from_sql(raw));
1412
Ok(MacAddress::new(bytes))
1513
}
1614

1715
accepts!(Type::Macaddr);
1816
}
1917

2018
impl ToSql for MacAddress {
21-
fn to_sql<W: Write + ?Sized>(&self, _: &Type, w: &mut W, _: &SessionInfo) -> Result<IsNull> {
22-
try!(w.write_all(self.as_bytes()));
19+
fn to_sql(&self, _: &Type, w: &mut Vec<u8>, _: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
20+
let mut bytes = [0; 6];
21+
bytes.copy_from_slice(self.as_bytes());
22+
types::macaddr_to_sql(bytes, w);
2323
Ok(IsNull::No)
2424
}
2525

0 commit comments

Comments
 (0)