From f56c5190978331f7e703d092f16cc59a8ffcaeb5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 30 Aug 2013 02:28:46 -0400 Subject: [PATCH] Boolean parameters transmitted as binary Work towards #7. --- src/test.rs | 24 ++++++++++++++++++++++++ src/types.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/test.rs b/src/test.rs index 6b472e27..1af01439 100644 --- a/src/test.rs +++ b/src/test.rs @@ -68,6 +68,30 @@ fn test_nulls() { }; } +#[test] +fn test_binary_bool_params() { + let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1:5432"); + + do conn.in_transaction |trans| { + trans.prepare("CREATE TABLE foo ( + id BIGINT PRIMARY KEY, + b BOOL + )").update([]); + trans.prepare("INSERT INTO foo (id, b) VALUES + ($1, $2), ($3, $4), ($5, $6)") + .update([&1 as &ToSql, &true as &ToSql, + &2 as &ToSql, &false as &ToSql, + &3 as &ToSql, &None:: as &ToSql]); + let stmt = trans.prepare("SELECT b FROM foo ORDER BY id"); + let result = stmt.query([]); + + assert_eq!(~[Some(true), Some(false), None], + result.iter().map(|row| { row[0] }).collect()); + + trans.set_rollback(); + } +} + #[test] fn test_wrong_num_params() { let conn = PostgresConnection::connect("postgres://postgres@127.0.0.1:5432"); diff --git a/src/types.rs b/src/types.rs index 9be4a1fd..6466debf 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,6 +2,9 @@ use std::str; pub type Oid = i32; +// Values from pg_type.h +static BOOLOID: Oid = 16; + pub enum Format { Text = 0, Binary = 1 @@ -39,6 +42,23 @@ macro_rules! from_option_impl( ) ) +impl FromSql for Option { + fn from_sql(raw: &Option<~[u8]>) -> Option { + match *raw { + None => None, + Some(ref buf) => { + assert_eq!(1, buf.len()); + match buf[0] as char { + 't' => Some(true), + 'f' => Some(false), + byte => fail!("Invalid byte: %?", byte) + } + } + } + } +} +from_option_impl!(bool) + from_str_impl!(int) from_option_impl!(int) from_str_impl!(i8) @@ -102,6 +122,17 @@ macro_rules! to_option_impl( ) ) +impl ToSql for bool { + fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) { + if ty == BOOLOID { + (Binary, Some(~[*self as u8])) + } else { + (Text, Some(self.to_str().into_bytes())) + } + } +} +to_option_impl!(bool) + to_str_impl!(int) to_option_impl!(int) to_str_impl!(i8)