1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
use Queriable; use expression::*; use expression::bound::Bound; use std::error::Error; use std::fmt; use std::io::Write; use types::{NativeSqlType, FromSql, FromSqlRow, Nullable, ToSql, IsNull}; impl<T: NativeSqlType> NativeSqlType for Nullable<T> { fn oid(&self) -> u32 { self.0.oid() } fn array_oid(&self) -> u32 { self.0.oid() } fn new() -> Self { Nullable(T::new()) } } impl<T, ST> FromSql<Nullable<ST>> for Option<T> where T: FromSql<ST>, ST: NativeSqlType, { fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> { match bytes { Some(_) => T::from_sql(bytes).map(Some), None => Ok(None) } } } impl<T, ST> Queriable<Nullable<ST>> for Option<T> where T: Queriable<ST>, Option<T::Row>: FromSqlRow<Nullable<ST>>, ST: NativeSqlType, { type Row = Option<T::Row>; fn build(row: Self::Row) -> Self { row.map(T::build) } } impl<T, ST> ToSql<Nullable<ST>> for Option<T> where T: ToSql<ST>, ST: NativeSqlType, { fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error>> { if let &Some(ref value) = self { value.to_sql(out) } else { Ok(IsNull::Yes) } } } impl<T, ST> AsExpression<Nullable<ST>> for Option<T> where Option<T>: ToSql<Nullable<ST>>, ST: NativeSqlType, { type Expression = Bound<Nullable<ST>, Self>; fn as_expression(self) -> Self::Expression { Bound::new(self) } } impl<'a, T, ST> AsExpression<Nullable<ST>> for &'a Option<T> where Option<T>: ToSql<Nullable<ST>>, ST: NativeSqlType, { type Expression = Bound<Nullable<ST>, Self>; fn as_expression(self) -> Self::Expression { Bound::new(self) } } #[derive(Debug)] pub struct UnexpectedNullError { pub msg: String, } impl fmt::Display for UnexpectedNullError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.msg) } } impl Error for UnexpectedNullError { fn description(&self) -> &str { &self.msg } } #[cfg(test)] use types; #[test] fn option_to_sql() { type Type = types::Nullable<types::VarChar>; let mut bytes = Vec::<u8>::new(); let is_null = ToSql::<Type>::to_sql(&None::<String>, &mut bytes).unwrap(); assert_eq!(IsNull::Yes, is_null); assert!(bytes.is_empty()); let is_null = ToSql::<Type>::to_sql(&Some(""), &mut bytes).unwrap(); assert_eq!(IsNull::No, is_null); assert!(bytes.is_empty()); let is_null = ToSql::<Type>::to_sql(&Some("Sean"), &mut bytes).unwrap(); let expectd_bytes: Vec<_> = "Sean".as_bytes().into(); assert_eq!(IsNull::No, is_null); assert_eq!(expectd_bytes, bytes); }