From aa37fe31d4b4943010ee6684f471931e828ea17a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 Sep 2013 16:54:02 -0400 Subject: [PATCH] Json and Uuid support cc #6 --- src/test.rs | 48 +++++++++++++++++++++----------- src/types.rs | 78 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 91 insertions(+), 35 deletions(-) diff --git a/src/test.rs b/src/test.rs index 05616529..dfb49f33 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,5 +1,8 @@ +extern mod extra; extern mod postgres; +use extra::json; +use extra::uuid::Uuid; use std::f32; use std::f64; @@ -92,7 +95,7 @@ fn test_lazy_query() { } } -fn test_param_type(sql_type: &str, values: &[T]) { +fn test_type(sql_type: &str, values: &[T]) { do test_in_transaction |trans| { trans.update("CREATE TABLE foo ( id SERIAL PRIMARY KEY, @@ -113,54 +116,67 @@ fn test_param_type(sql_type: &str, values: &[T]) { #[test] fn test_bool_params() { - test_param_type("BOOL", [Some(true), Some(false), None]); + test_type("BOOL", [Some(true), Some(false), None]); } #[test] fn test_i16_params() { - test_param_type("SMALLINT", [Some(0x0011i16), Some(-0x0011i16), None]); + test_type("SMALLINT", [Some(0x0011i16), Some(-0x0011i16), None]); } #[test] fn test_i32_params() { - test_param_type("INT", [Some(0x00112233i32), Some(-0x00112233i32), None]); + test_type("INT", [Some(0x00112233i32), Some(-0x00112233i32), None]); } #[test] fn test_i64_params() { - test_param_type("BIGINT", [Some(0x0011223344556677i64), - Some(-0x0011223344556677i64), None]); + test_type("BIGINT", [Some(0x0011223344556677i64), + Some(-0x0011223344556677i64), None]); } #[test] fn test_f32_params() { - test_param_type("REAL", [Some(f32::infinity), Some(f32::neg_infinity), - Some(1000.55), None]); + test_type("REAL", [Some(f32::infinity), Some(f32::neg_infinity), + Some(1000.55), None]); } #[test] fn test_f64_params() { - test_param_type("DOUBLE PRECISION", [Some(f64::infinity), - Some(f64::neg_infinity), - Some(10000.55), None]); + test_type("DOUBLE PRECISION", [Some(f64::infinity), + Some(f64::neg_infinity), + Some(10000.55), None]); } #[test] fn test_varchar_params() { - test_param_type("VARCHAR", [Some(~"hello world"), - Some(~"イロハニホヘト チリヌルヲ"), None]); + test_type("VARCHAR", [Some(~"hello world"), + Some(~"イロハニホヘト チリヌルヲ"), None]); } #[test] fn test_text_params() { - test_param_type("TEXT", [Some(~"hello world"), - Some(~"イロハニホヘト チリヌルヲ"), None]); + test_type("TEXT", [Some(~"hello world"), + Some(~"イロハニホヘト チリヌルヲ"), None]); } #[test] fn test_bytea_params() { - test_param_type("BYTEA", [Some(~[0u8, 1, 2, 3, 254, 255]), None]); + test_type("BYTEA", [Some(~[0u8, 1, 2, 3, 254, 255]), None]); +} + +#[test] +fn test_json_params() { + test_type("JSON", [Some(json::from_str("[10, 11, 12]").unwrap()), + Some(json::from_str("{\"f\": \"asd\"}").unwrap()), + None]) +} + +#[test] +fn test_uuid_params() { + test_type("UUID", [Some(Uuid::parse_string("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11").unwrap()), + None]) } fn test_nan_param(sql_type: &str) { diff --git a/src/types.rs b/src/types.rs index ebbbec76..f68362bf 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,3 +1,8 @@ +extern mod extra; + +use extra::json; +use extra::json::Json; +use extra::uuid::Uuid; use std::rt::io::Decorator; use std::rt::io::extensions::{WriterByteConversions, ReaderByteConversions}; use std::rt::io::mem::{MemWriter, MemReader}; @@ -12,9 +17,11 @@ static INT8OID: Oid = 20; static INT2OID: Oid = 21; static INT4OID: Oid = 23; static TEXTOID: Oid = 25; +static JSONOID: Oid = 114; static FLOAT4OID: Oid = 700; static FLOAT8OID: Oid = 701; static VARCHAROID: Oid = 1043; +static UUIDOID: Oid = 2950; pub enum Format { Text = 0, @@ -29,7 +36,8 @@ pub fn result_format(ty: Oid) -> Format { INT2OID | INT4OID | FLOAT4OID | - FLOAT8OID => Binary, + FLOAT8OID | + UUIDOID => Binary, _ => Text } } @@ -98,8 +106,8 @@ from_option_impl!(f64) impl FromSql for Option<~str> { fn from_sql(ty:Oid, raw: &Option<~[u8]>) -> Option<~str> { check_oid!(VARCHAROID | TEXTOID, ty) - do raw.chain_ref |buf| { - Some(str::from_bytes(buf.as_slice())) + do raw.map |buf| { + str::from_bytes(buf.as_slice()) } } } @@ -113,6 +121,26 @@ impl FromSql for Option<~[u8]> { } from_option_impl!(~[u8]) +impl FromSql for Option { + fn from_sql(ty: Oid, raw: &Option<~[u8]>) -> Option { + check_oid!(JSONOID, ty) + do raw.map |buf| { + json::from_str(str::from_bytes_slice(buf.as_slice())).unwrap() + } + } +} +from_option_impl!(Json) + +impl FromSql for Option { + fn from_sql(ty: Oid, raw: &Option<~[u8]>) -> Option { + check_oid!(UUIDOID, ty) + do raw.map |buf| { + Uuid::from_bytes(buf.as_slice()).unwrap() + } + } +} +from_option_impl!(Uuid) + pub trait ToSql { fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>); } @@ -129,6 +157,18 @@ macro_rules! to_option_impl( } } } + ); + (self, $($oid:ident)|+, $t:ty) => ( + impl<'self> ToSql for Option<$t> { + fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) { + check_oid!($($oid)|+, ty) + + match *self { + None => (Text, None), + Some(ref val) => val.to_sql(ty) + } + } + } ) ) @@ -173,16 +213,7 @@ impl<'self> ToSql for &'self str { } to_option_impl!(VARCHAROID | TEXTOID, ~str) - -impl<'self> ToSql for Option<&'self str> { - fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) { - check_oid!(VARCHAROID | TEXTOID, ty) - match *self { - None => (Text, None), - Some(val) => val.to_sql(ty) - } - } -} +to_option_impl!(self, VARCHAROID | TEXTOID, &'self str) impl<'self> ToSql for &'self [u8] { fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) { @@ -192,13 +223,22 @@ impl<'self> ToSql for &'self [u8] { } to_option_impl!(BYTEAOID, ~[u8]) +to_option_impl!(self, BYTEAOID, &'self [u8]) -impl<'self> ToSql for Option<&'self [u8]> { +impl ToSql for Json { fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) { - check_oid!(BYTEAOID, ty) - match *self { - None => (Text, None), - Some(val) => val.to_sql(ty) - } + check_oid!(JSONOID, ty) + (Text, Some(self.to_str().into_bytes())) } } + +to_option_impl!(JSONOID, Json) + +impl ToSql for Uuid { + fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) { + check_oid!(UUIDOID, ty) + (Binary, Some(self.to_bytes().to_owned())) + } +} + +to_option_impl!(UUIDOID, Uuid)