1 use super::{Type, Value}; 2 use crate::types::{FromSqlError, FromSqlResult}; 3 4 /// A non-owning [dynamic type value](http://sqlite.org/datatype3.html). Typically the 5 /// memory backing this value is owned by SQLite. 6 /// 7 /// See [`Value`](enum.Value.html) for an owning dynamic type value. 8 #[derive(Copy, Clone, Debug, PartialEq)] 9 pub enum ValueRef<'a> { 10 /// The value is a `NULL` value. 11 Null, 12 /// The value is a signed integer. 13 Integer(i64), 14 /// The value is a floating point number. 15 Real(f64), 16 /// The value is a text string. 17 Text(&'a [u8]), 18 /// The value is a blob of data 19 Blob(&'a [u8]), 20 } 21 22 impl ValueRef<'_> { 23 /// Returns SQLite fundamental datatype. data_type(&self) -> Type24 pub fn data_type(&self) -> Type { 25 match *self { 26 ValueRef::Null => Type::Null, 27 ValueRef::Integer(_) => Type::Integer, 28 ValueRef::Real(_) => Type::Real, 29 ValueRef::Text(_) => Type::Text, 30 ValueRef::Blob(_) => Type::Blob, 31 } 32 } 33 } 34 35 impl<'a> ValueRef<'a> { 36 /// If `self` is case `Integer`, returns the integral value. Otherwise, 37 /// returns `Err(Error::InvalidColumnType)`. as_i64(&self) -> FromSqlResult<i64>38 pub fn as_i64(&self) -> FromSqlResult<i64> { 39 match *self { 40 ValueRef::Integer(i) => Ok(i), 41 _ => Err(FromSqlError::InvalidType), 42 } 43 } 44 45 /// If `self` is case `Real`, returns the floating point value. Otherwise, 46 /// returns `Err(Error::InvalidColumnType)`. as_f64(&self) -> FromSqlResult<f64>47 pub fn as_f64(&self) -> FromSqlResult<f64> { 48 match *self { 49 ValueRef::Real(f) => Ok(f), 50 _ => Err(FromSqlError::InvalidType), 51 } 52 } 53 54 /// If `self` is case `Text`, returns the string value. Otherwise, returns 55 /// `Err(Error::InvalidColumnType)`. as_str(&self) -> FromSqlResult<&'a str>56 pub fn as_str(&self) -> FromSqlResult<&'a str> { 57 match *self { 58 ValueRef::Text(t) => { 59 std::str::from_utf8(t).map_err(|e| FromSqlError::Other(Box::new(e))) 60 } 61 _ => Err(FromSqlError::InvalidType), 62 } 63 } 64 65 /// If `self` is case `Blob`, returns the byte slice. Otherwise, returns 66 /// `Err(Error::InvalidColumnType)`. as_blob(&self) -> FromSqlResult<&'a [u8]>67 pub fn as_blob(&self) -> FromSqlResult<&'a [u8]> { 68 match *self { 69 ValueRef::Blob(b) => Ok(b), 70 _ => Err(FromSqlError::InvalidType), 71 } 72 } 73 } 74 75 impl From<ValueRef<'_>> for Value { from(borrowed: ValueRef<'_>) -> Value76 fn from(borrowed: ValueRef<'_>) -> Value { 77 match borrowed { 78 ValueRef::Null => Value::Null, 79 ValueRef::Integer(i) => Value::Integer(i), 80 ValueRef::Real(r) => Value::Real(r), 81 ValueRef::Text(s) => { 82 let s = std::str::from_utf8(s).expect("invalid UTF-8"); 83 Value::Text(s.to_string()) 84 } 85 ValueRef::Blob(b) => Value::Blob(b.to_vec()), 86 } 87 } 88 } 89 90 impl<'a> From<&'a str> for ValueRef<'a> { from(s: &str) -> ValueRef<'_>91 fn from(s: &str) -> ValueRef<'_> { 92 ValueRef::Text(s.as_bytes()) 93 } 94 } 95 96 impl<'a> From<&'a [u8]> for ValueRef<'a> { from(s: &[u8]) -> ValueRef<'_>97 fn from(s: &[u8]) -> ValueRef<'_> { 98 ValueRef::Blob(s) 99 } 100 } 101 102 impl<'a> From<&'a Value> for ValueRef<'a> { from(value: &'a Value) -> ValueRef<'a>103 fn from(value: &'a Value) -> ValueRef<'a> { 104 match *value { 105 Value::Null => ValueRef::Null, 106 Value::Integer(i) => ValueRef::Integer(i), 107 Value::Real(r) => ValueRef::Real(r), 108 Value::Text(ref s) => ValueRef::Text(s.as_bytes()), 109 Value::Blob(ref b) => ValueRef::Blob(b), 110 } 111 } 112 } 113 114 impl<'a, T> From<Option<T>> for ValueRef<'a> 115 where 116 T: Into<ValueRef<'a>>, 117 { from(s: Option<T>) -> ValueRef<'a>118 fn from(s: Option<T>) -> ValueRef<'a> { 119 match s { 120 Some(x) => x.into(), 121 None => ValueRef::Null, 122 } 123 } 124 } 125 126 #[cfg(any(feature = "functions", feature = "session", feature = "vtab"))] 127 impl<'a> ValueRef<'a> { from_value(value: *mut crate::ffi::sqlite3_value) -> ValueRef<'a>128 pub(crate) unsafe fn from_value(value: *mut crate::ffi::sqlite3_value) -> ValueRef<'a> { 129 use crate::ffi; 130 use std::slice::from_raw_parts; 131 132 match ffi::sqlite3_value_type(value) { 133 ffi::SQLITE_NULL => ValueRef::Null, 134 ffi::SQLITE_INTEGER => ValueRef::Integer(ffi::sqlite3_value_int64(value)), 135 ffi::SQLITE_FLOAT => ValueRef::Real(ffi::sqlite3_value_double(value)), 136 ffi::SQLITE_TEXT => { 137 let text = ffi::sqlite3_value_text(value); 138 let len = ffi::sqlite3_value_bytes(value); 139 assert!( 140 !text.is_null(), 141 "unexpected SQLITE_TEXT value type with NULL data" 142 ); 143 let s = from_raw_parts(text as *const u8, len as usize); 144 ValueRef::Text(s) 145 } 146 ffi::SQLITE_BLOB => { 147 let (blob, len) = ( 148 ffi::sqlite3_value_blob(value), 149 ffi::sqlite3_value_bytes(value), 150 ); 151 152 assert!( 153 len >= 0, 154 "unexpected negative return from sqlite3_value_bytes" 155 ); 156 if len > 0 { 157 assert!( 158 !blob.is_null(), 159 "unexpected SQLITE_BLOB value type with NULL data" 160 ); 161 ValueRef::Blob(from_raw_parts(blob as *const u8, len as usize)) 162 } else { 163 // The return value from sqlite3_value_blob() for a zero-length BLOB 164 // is a NULL pointer. 165 ValueRef::Blob(&[]) 166 } 167 } 168 _ => unreachable!("sqlite3_value_type returned invalid value"), 169 } 170 } 171 } 172