mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 13:58:55 +08:00 
			
		
		
		
	Remove functions::FromValue.
With the new definition of FromSql, we can reuse it since we can convert a sqlite3_value into a BorrowedValue.
This commit is contained in:
		
							
								
								
									
										134
									
								
								src/functions.rs
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								src/functions.rs
									
									
									
									
									
								
							| @@ -54,7 +54,6 @@ use std::ffi::CStr; | |||||||
| use std::mem; | use std::mem; | ||||||
| use std::ptr; | use std::ptr; | ||||||
| use std::slice; | use std::slice; | ||||||
| use std::str; |  | ||||||
| use libc::{c_int, c_double, c_char, c_void}; | use libc::{c_int, c_double, c_char, c_void}; | ||||||
|  |  | ||||||
| use ffi; | use ffi; | ||||||
| @@ -63,7 +62,7 @@ pub use ffi::sqlite3_value; | |||||||
| pub use ffi::sqlite3_value_type; | pub use ffi::sqlite3_value_type; | ||||||
| pub use ffi::sqlite3_value_numeric_type; | pub use ffi::sqlite3_value_numeric_type; | ||||||
|  |  | ||||||
| use types::Null; | use types::{Null, FromSql, BorrowedValue}; | ||||||
|  |  | ||||||
| use {Result, Error, Connection, str_to_cstring, InnerConnection}; | use {Result, Error, Connection, str_to_cstring, InnerConnection}; | ||||||
|  |  | ||||||
| @@ -157,108 +156,35 @@ impl ToResult for Null { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// A trait for types that can be created from a SQLite function parameter value. | impl<'a> BorrowedValue<'a> { | ||||||
| pub trait FromValue: Sized { |     unsafe fn from_value(value: *mut sqlite3_value) -> BorrowedValue<'a> { | ||||||
|     unsafe fn parameter_value(v: *mut sqlite3_value) -> Result<Self>; |  | ||||||
|  |  | ||||||
|     /// FromValue types can implement this method and use sqlite3_value_type to check that |  | ||||||
|     /// the type reported by SQLite matches a type suitable for Self. This method is used |  | ||||||
|     /// by `Context::get` to confirm that the parameter contains a valid type before |  | ||||||
|     /// attempting to retrieve the value. |  | ||||||
|     unsafe fn parameter_has_valid_sqlite_type(_: *mut sqlite3_value) -> bool { |  | ||||||
|         true |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| macro_rules! raw_from_impl( |  | ||||||
|     ($t:ty, $f:ident, $c:expr) => ( |  | ||||||
|         impl FromValue for $t { |  | ||||||
|             unsafe fn parameter_value(v: *mut sqlite3_value) -> Result<$t> { |  | ||||||
|                 Ok(ffi::$f(v)) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool { |  | ||||||
|                 sqlite3_value_numeric_type(v) == $c |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     ) |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| raw_from_impl!(c_int, sqlite3_value_int, ffi::SQLITE_INTEGER); |  | ||||||
| raw_from_impl!(i64, sqlite3_value_int64, ffi::SQLITE_INTEGER); |  | ||||||
|  |  | ||||||
| impl FromValue for bool { |  | ||||||
|     unsafe fn parameter_value(v: *mut sqlite3_value) -> Result<bool> { |  | ||||||
|         match ffi::sqlite3_value_int(v) { |  | ||||||
|             0 => Ok(false), |  | ||||||
|             _ => Ok(true), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool { |  | ||||||
|         sqlite3_value_numeric_type(v) == ffi::SQLITE_INTEGER |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl FromValue for c_double { |  | ||||||
|     unsafe fn parameter_value(v: *mut sqlite3_value) -> Result<c_double> { |  | ||||||
|         Ok(ffi::sqlite3_value_double(v)) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool { |  | ||||||
|         sqlite3_value_numeric_type(v) == ffi::SQLITE_FLOAT || |  | ||||||
|         sqlite3_value_numeric_type(v) == ffi::SQLITE_INTEGER |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl FromValue for String { |  | ||||||
|     unsafe fn parameter_value(v: *mut sqlite3_value) -> Result<String> { |  | ||||||
|         let c_text = ffi::sqlite3_value_text(v); |  | ||||||
|         if c_text.is_null() { |  | ||||||
|             Ok("".to_owned()) |  | ||||||
|         } else { |  | ||||||
|             let c_slice = CStr::from_ptr(c_text as *const c_char).to_bytes(); |  | ||||||
|             let utf8_str = try!(str::from_utf8(c_slice)); |  | ||||||
|             Ok(utf8_str.into()) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool { |  | ||||||
|         sqlite3_value_type(v) == ffi::SQLITE_TEXT |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl FromValue for Vec<u8> { |  | ||||||
|     unsafe fn parameter_value(v: *mut sqlite3_value) -> Result<Vec<u8>> { |  | ||||||
|         use std::slice::from_raw_parts; |         use std::slice::from_raw_parts; | ||||||
|         let c_blob = ffi::sqlite3_value_blob(v); |  | ||||||
|         let len = ffi::sqlite3_value_bytes(v); |  | ||||||
|  |  | ||||||
|         assert!(len >= 0, |         match ffi::sqlite3_value_type(value) { | ||||||
|                 "unexpected negative return from sqlite3_value_bytes"); |             ffi::SQLITE_NULL => BorrowedValue::Null, | ||||||
|         let len = len as usize; |             ffi::SQLITE_INTEGER => BorrowedValue::Integer(ffi::sqlite3_value_int64(value)), | ||||||
|  |             ffi::SQLITE_FLOAT => BorrowedValue::Real(ffi::sqlite3_value_double(value)), | ||||||
|  |             ffi::SQLITE_TEXT => { | ||||||
|  |                 let text = ffi::sqlite3_value_text(value); | ||||||
|  |                 assert!(!text.is_null(), "unexpected SQLITE_TEXT value type with NULL data"); | ||||||
|  |                 let s = CStr::from_ptr(text as *const c_char); | ||||||
|  |  | ||||||
|         Ok(from_raw_parts(mem::transmute(c_blob), len).to_vec()) |                 // sqlite3_value_text returns UTF8 data, so our unwrap here should be fine. | ||||||
|     } |                 let s = s.to_str().expect("sqlite3_value_text returned invalid UTF-8"); | ||||||
|  |                 BorrowedValue::Text(s) | ||||||
|  |             } | ||||||
|  |             ffi::SQLITE_BLOB => { | ||||||
|  |                 let blob = ffi::sqlite3_value_blob(value); | ||||||
|  |                 assert!(!blob.is_null(), "unexpected SQLITE_BLOB value type with NULL data"); | ||||||
|  |  | ||||||
|     unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool { |                 let len = ffi::sqlite3_value_bytes(value); | ||||||
|         sqlite3_value_type(v) == ffi::SQLITE_BLOB |                 assert!(len >= 0, "unexpected negative return from sqlite3_value_bytes"); | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T: FromValue> FromValue for Option<T> { |                 BorrowedValue::Blob(from_raw_parts(blob as *const u8, len as usize)) | ||||||
|     unsafe fn parameter_value(v: *mut sqlite3_value) -> Result<Option<T>> { |             } | ||||||
|         if sqlite3_value_type(v) == ffi::SQLITE_NULL { |             _ => unreachable!("sqlite3_value_type returned invalid value") | ||||||
|             Ok(None) |  | ||||||
|         } else { |  | ||||||
|             FromValue::parameter_value(v).map(Some) |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool { |  | ||||||
|         sqlite3_value_type(v) == ffi::SQLITE_NULL || T::parameter_has_valid_sqlite_type(v) |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) { | unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) { | ||||||
| @@ -288,15 +214,13 @@ impl<'a> Context<'a> { | |||||||
|     /// Will panic if `idx` is greater than or equal to `self.len()`. |     /// Will panic if `idx` is greater than or equal to `self.len()`. | ||||||
|     /// |     /// | ||||||
|     /// Will return Err if the underlying SQLite type cannot be converted to a `T`. |     /// Will return Err if the underlying SQLite type cannot be converted to a `T`. | ||||||
|     pub fn get<T: FromValue>(&self, idx: usize) -> Result<T> { |     pub fn get<T: FromSql>(&self, idx: usize) -> Result<T> { | ||||||
|         let arg = self.args[idx]; |         let arg = self.args[idx]; | ||||||
|         unsafe { |         let value = unsafe { BorrowedValue::from_value(arg) }; | ||||||
|             if T::parameter_has_valid_sqlite_type(arg) { |         FromSql::column_result(value).map_err(|err| match err { | ||||||
|                 T::parameter_value(arg) |             Error::InvalidColumnType => Error::InvalidFunctionParameterType, | ||||||
|             } else { |             _ => err | ||||||
|                 Err(Error::InvalidFunctionParameterType) |         }) | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Sets the auxilliary data associated with a particular parameter. See |     /// Sets the auxilliary data associated with a particular parameter. See | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user