Skip to content

Commit bca16fd

Browse files
committed
Pass Type to raw traits and add jsonb support
1 parent cd8b5f7 commit bca16fd

5 files changed

Lines changed: 55 additions & 30 deletions

File tree

src/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ impl fmt::String for Error {
653653
write!(fmt, "A statement was executed with a connection it was not prepared with"),
654654
Error::WrongParamCount { expected, actual } =>
655655
write!(fmt, "Expected {} parameters but got {}", expected, actual),
656-
Error::WrongType(ref ty) => write!(fmt, "Unexpected type {}", ty),
656+
Error::WrongType(ref ty) => write!(fmt, "Unexpected type {:?}", ty),
657657
Error::InvalidColumn => write!(fmt, "Invalid column"),
658658
Error::WasNull => write!(fmt, "The value was NULL"),
659659
Error::WrongTransaction =>
@@ -696,7 +696,7 @@ impl error::Error for Error {
696696
Error::WrongParamCount { expected, actual } => {
697697
Some(format!("expected: {}, actual: {}", expected, actual))
698698
}
699-
Error::WrongType(ref ty) => Some(format!("saw type {}", ty)),
699+
Error::WrongType(ref ty) => Some(format!("saw type {:?}", ty)),
700700
_ => None
701701
}
702702
}

src/types/mod.rs

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ macro_rules! check_types {
1919
macro_rules! raw_from_impl {
2020
($t:ty, $f:ident) => (
2121
impl RawFromSql for $t {
22-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<$t> {
22+
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<$t> {
2323
Ok(try!(raw.$f()))
2424
}
2525
}
@@ -51,7 +51,7 @@ macro_rules! from_map_impl {
5151
fn from_sql(ty: &Type, raw: Option<&[u8]>) -> Result<Option<$t>> {
5252
check_types!($($expected),+; ty);
5353
match raw {
54-
Some(buf) => ($blk)(buf).map(|ok| Some(ok)),
54+
Some(buf) => ($blk)(ty, buf).map(|ok| Some(ok)),
5555
None => Ok(None)
5656
}
5757
}
@@ -63,18 +63,18 @@ macro_rules! from_map_impl {
6363

6464
macro_rules! from_raw_from_impl {
6565
($($expected:pat),+; $t:ty) => (
66-
from_map_impl!($($expected),+; $t, |&mut: mut buf: &[u8]| {
66+
from_map_impl!($($expected),+; $t, |&mut: ty, mut buf: &[u8]| {
6767
use types::RawFromSql;
6868

69-
RawFromSql::raw_from_sql(&mut buf)
69+
RawFromSql::raw_from_sql(ty, &mut buf)
7070
});
7171
)
7272
}
7373

7474
macro_rules! raw_to_impl {
7575
($t:ty, $f:ident) => (
7676
impl RawToSql for $t {
77-
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
77+
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
7878
Ok(try!(w.$f(*self)))
7979
}
8080
}
@@ -118,7 +118,7 @@ macro_rules! to_raw_to_impl {
118118
check_types!($($oid),+; ty);
119119

120120
let mut writer = vec![];
121-
try!(self.raw_to_sql(&mut writer));
121+
try!(self.raw_to_sql(ty, &mut writer));
122122
Ok(Some(writer))
123123
}
124124
}
@@ -351,24 +351,27 @@ pub trait FromSql {
351351

352352
/// A utility trait used by `FromSql` implementations
353353
pub trait RawFromSql {
354-
/// Creates a new value of this type from a reader of Postgre data.
355-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<Self>;
354+
/// Creates a new value of this type from a `Reader` of Postgres data.
355+
///
356+
/// It is the caller's responsibility to ensure that Postgres data of this
357+
/// type can be turned in to this type.
358+
fn raw_from_sql<R: Reader>(ty: &Type, raw: &mut R) -> Result<Self>;
356359
}
357360

358361
impl RawFromSql for bool {
359-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<bool> {
362+
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<bool> {
360363
Ok((try!(raw.read_u8())) != 0)
361364
}
362365
}
363366

364367
impl RawFromSql for Vec<u8> {
365-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<Vec<u8>> {
368+
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<Vec<u8>> {
366369
Ok(try!(raw.read_to_end()))
367370
}
368371
}
369372

370373
impl RawFromSql for String {
371-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<String> {
374+
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<String> {
372375
String::from_utf8(try!(raw.read_to_end())).map_err(|_| Error::BadData)
373376
}
374377
}
@@ -382,13 +385,19 @@ raw_from_impl!(f32, read_be_f32);
382385
raw_from_impl!(f64, read_be_f64);
383386

384387
impl RawFromSql for json::Json {
385-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<json::Json> {
388+
fn raw_from_sql<R: Reader>(ty: &Type, raw: &mut R) -> Result<json::Json> {
389+
if let Type::Jsonb = *ty {
390+
// We only support version 1 of the jsonb binary format
391+
if try!(raw.read_u8()) != 1 {
392+
return Err(Error::BadData);
393+
}
394+
}
386395
json::Json::from_reader(raw).map_err(|_| Error::BadData)
387396
}
388397
}
389398

390399
impl RawFromSql for IpAddr {
391-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<IpAddr> {
400+
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<IpAddr> {
392401
let family = try!(raw.read_u8());
393402
let _bits = try!(raw.read_u8());
394403
let _is_cidr = try!(raw.read_u8());
@@ -424,7 +433,7 @@ from_raw_from_impl!(Type::Oid; u32);
424433
from_raw_from_impl!(Type::Int8; i64);
425434
from_raw_from_impl!(Type::Float4; f32);
426435
from_raw_from_impl!(Type::Float8; f64);
427-
from_raw_from_impl!(Type::Json; json::Json);
436+
from_raw_from_impl!(Type::Json, Type::Jsonb; json::Json);
428437
from_raw_from_impl!(Type::Inet, Type::Cidr; IpAddr);
429438

430439
impl FromSql for Option<String> {
@@ -437,7 +446,7 @@ impl FromSql for Option<String> {
437446

438447
match raw {
439448
Some(mut buf) => {
440-
Ok(Some(try!(RawFromSql::raw_from_sql(&mut buf))))
449+
Ok(Some(try!(RawFromSql::raw_from_sql(ty, &mut buf))))
441450
}
442451
None => Ok(None)
443452
}
@@ -500,25 +509,28 @@ pub trait ToSql {
500509

501510
/// A utility trait used by `ToSql` implementations.
502511
pub trait RawToSql {
503-
/// Converts the value of `self` into the binary format appropriate for the
504-
/// Postgres backend, writing it to `w`.
505-
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()>;
512+
/// Converts the value of `self` into the binary format of the specified
513+
/// Postgres type, writing it to `w`.
514+
///
515+
/// It is the caller's responsibility to make sure that this type can be
516+
/// converted to the specified Postgres type.
517+
fn raw_to_sql<W: Writer>(&self, ty: &Type, w: &mut W) -> Result<()>;
506518
}
507519

508520
impl RawToSql for bool {
509-
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
521+
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
510522
Ok(try!(w.write_u8(*self as u8)))
511523
}
512524
}
513525

514526
impl RawToSql for Vec<u8> {
515-
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
527+
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
516528
Ok(try!(w.write(&**self)))
517529
}
518530
}
519531

520532
impl RawToSql for String {
521-
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
533+
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
522534
Ok(try!(w.write(self.as_bytes())))
523535
}
524536
}
@@ -532,13 +544,17 @@ raw_to_impl!(f32, write_be_f32);
532544
raw_to_impl!(f64, write_be_f64);
533545

534546
impl RawToSql for json::Json {
535-
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> Result<()> {
547+
fn raw_to_sql<W: Writer>(&self, ty: &Type, raw: &mut W) -> Result<()> {
548+
if let Type::Jsonb = *ty {
549+
try!(raw.write_u8(1));
550+
}
551+
536552
Ok(try!(write!(raw, "{}", self)))
537553
}
538554
}
539555

540556
impl RawToSql for IpAddr {
541-
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> Result<()> {
557+
fn raw_to_sql<W: Writer>(&self, _: &Type, raw: &mut W) -> Result<()> {
542558
match *self {
543559
IpAddr::Ipv4Addr(a, b, c, d) => {
544560
try!(raw.write(&[2, // family
@@ -570,7 +586,7 @@ impl RawToSql for IpAddr {
570586

571587
to_raw_to_impl!(Type::Bool; bool);
572588
to_raw_to_impl!(Type::ByteA; Vec<u8>);
573-
to_raw_to_impl!(Type::Json; json::Json);
589+
to_raw_to_impl!(Type::Json, Type::Jsonb; json::Json);
574590
to_raw_to_impl!(Type::Inet, Type::Cidr; IpAddr);
575591
to_raw_to_impl!(Type::Char; i8);
576592
to_raw_to_impl!(Type::Int2; i16);

src/types/time.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const NSEC_PER_USEC: i64 = 1_000;
99
const TIME_SEC_CONVERSION: i64 = 946684800;
1010

1111
impl RawFromSql for Timespec {
12-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<Timespec> {
12+
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<Timespec> {
1313
let t = try!(raw.read_be_i64());
1414
let mut sec = t / USEC_PER_SEC + TIME_SEC_CONVERSION;
1515
let mut usec = t % USEC_PER_SEC;
@@ -26,7 +26,7 @@ impl RawFromSql for Timespec {
2626
from_raw_from_impl!(Type::Timestamp, Type::TimestampTZ; Timespec);
2727

2828
impl RawToSql for Timespec {
29-
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
29+
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
3030
let t = (self.sec - TIME_SEC_CONVERSION) * USEC_PER_SEC + self.nsec as i64 / NSEC_PER_USEC;
3131
Ok(try!(w.write_be_i64(t)))
3232
}

src/types/uuid.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use Error;
66
use Result;
77

88
impl RawFromSql for Uuid {
9-
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<Uuid> {
9+
fn raw_from_sql<R: Reader>(_: &Type, raw: &mut R) -> Result<Uuid> {
1010
match Uuid::from_bytes(&*try!(raw.read_to_end())) {
1111
Some(u) => Ok(u),
1212
None => Err(Error::BadData),
@@ -17,7 +17,7 @@ impl RawFromSql for Uuid {
1717
from_raw_from_impl!(Type::Uuid; Uuid);
1818

1919
impl RawToSql for Uuid {
20-
fn raw_to_sql<W: Writer>(&self, w: &mut W) -> Result<()> {
20+
fn raw_to_sql<W: Writer>(&self, _: &Type, w: &mut W) -> Result<()> {
2121
Ok(try!(w.write(self.as_bytes())))
2222
}
2323
}

tests/types/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,15 @@ fn test_json_params() {
144144
(None, "NULL")])
145145
}
146146

147+
#[test]
148+
fn test_jsonb_params() {
149+
test_type("JSONB", &[(Some(Json::from_str("[10, 11, 12]").unwrap()),
150+
"'[10, 11, 12]'"),
151+
(Some(Json::from_str("{\"f\": \"asd\"}").unwrap()),
152+
"'{\"f\": \"asd\"}'"),
153+
(None, "NULL")])
154+
}
155+
147156
#[test]
148157
fn test_inet_params() {
149158
test_type("INET", &[(Some("127.0.0.1".parse::<IpAddr>().unwrap()),

0 commit comments

Comments
 (0)