mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 05:48:56 +08:00 
			
		
		
		
	Allow getting a ValueRef out of Row and Context, fixes #259
This commit is contained in:
		| @@ -139,6 +139,16 @@ impl<'a> Context<'a> { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /// Returns the `idx`th argument as a `ValueRef`. | ||||
|     /// | ||||
|     /// # Failure | ||||
|     /// | ||||
|     /// Will panic if `idx` is greater than or equal to `self.len()`. | ||||
|     pub fn get_raw(&self, idx: usize) -> ValueRef<'a> { | ||||
|         let arg = self.args[idx]; | ||||
|         unsafe { ValueRef::from_value(arg) } | ||||
|     } | ||||
|  | ||||
|     /// Sets the auxilliary data associated with a particular parameter. See | ||||
|     /// https://www.sqlite.org/c3ref/get_auxdata.html for a discussion of | ||||
|     /// this feature, or the unit tests of this module for an example. | ||||
| @@ -530,8 +540,10 @@ mod test { | ||||
|         let is_match = { | ||||
|             let re = saved_re.unwrap_or_else(|| new_re.as_ref().unwrap()); | ||||
|  | ||||
|             let text = try!(ctx.get::<String>(1)); | ||||
|             re.is_match(&text) | ||||
|             let text = ctx.get_raw(1).as_str().map_err(|e| | ||||
|                 Error::UserFunctionError(e.into()))?; | ||||
|  | ||||
|             re.is_match(text) | ||||
|         }; | ||||
|  | ||||
|         if let Some(re) = new_re { | ||||
|   | ||||
							
								
								
									
										23
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -1592,6 +1592,29 @@ mod test { | ||||
|         // degree of reliability. | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_raw() { | ||||
|         let db = checked_memory_handle(); | ||||
|         db.execute_batch("CREATE TABLE foo(i, x);").unwrap(); | ||||
|         let vals = ["foobar", "1234", "qwerty"]; | ||||
|         let mut insert_stmt = db.prepare("INSERT INTO foo(i, x) VALUES(?, ?)").unwrap(); | ||||
|         for (i, v) in vals.iter().enumerate() { | ||||
|             let i_to_insert = i as i64; | ||||
|             assert_eq!(insert_stmt.execute(&[&i_to_insert as &dyn ToSql, &v]).unwrap(), 1); | ||||
|         } | ||||
|  | ||||
|         let mut query = db.prepare("SELECT i, x FROM foo").unwrap(); | ||||
|         let mut rows = query.query(NO_PARAMS).unwrap(); | ||||
|  | ||||
|         while let Some(res) = rows.next() { | ||||
|             let row = res.unwrap(); | ||||
|             let i = row.get_raw(0).as_i64().unwrap(); | ||||
|             let expect = vals[i as usize]; | ||||
|             let x = row.get_raw("x").as_str().unwrap(); | ||||
|             assert_eq!(x, expect); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     mod query_and_then_tests { | ||||
|         extern crate libsqlite3_sys as ffi; | ||||
|         use super::*; | ||||
|   | ||||
							
								
								
									
										47
									
								
								src/row.rs
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/row.rs
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ use std::marker::PhantomData; | ||||
| use std::{convert, result}; | ||||
|  | ||||
| use super::{Error, Result, Statement}; | ||||
| use types::{FromSql, FromSqlError}; | ||||
| use types::{FromSql, FromSqlError, ValueRef}; | ||||
|  | ||||
| /// An handle for the resulting rows of a query. | ||||
| pub struct Rows<'stmt> { | ||||
| @@ -126,7 +126,7 @@ where | ||||
| } | ||||
|  | ||||
| /// A single result row of a query. | ||||
| pub struct Row<'a, 'stmt> { | ||||
| pub struct Row<'a, 'stmt: 'a> { | ||||
|     stmt: &'stmt Statement<'stmt>, | ||||
|     phantom: PhantomData<&'a ()>, | ||||
| } | ||||
| @@ -173,6 +173,49 @@ impl<'a, 'stmt> Row<'a, 'stmt> { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /// Get the value of a particular column of the result row as a `ValueRef`, | ||||
|     /// allowing data to be read out of a row without copying. | ||||
|     /// | ||||
|     /// This `ValueRef` is valid only as long as this Row, which is enforced by | ||||
|     /// it's lifetime. This means that while this method is completely safe, | ||||
|     /// it can be somewhat difficult to use, and most callers will be better | ||||
|     /// served by `get` or `get_checked`. | ||||
|     /// | ||||
|     /// ## Failure | ||||
|     /// | ||||
|     /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid | ||||
|     /// column range for this row. | ||||
|     /// | ||||
|     /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column | ||||
|     /// name for this row. | ||||
|     pub fn get_raw_checked<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'a>> { | ||||
|         let idx = idx.idx(self.stmt)?; | ||||
|         // Narrowing from `ValueRef<'stmt>` (which `self.stmt.value_ref(idx)` | ||||
|         // returns) to `ValueRef<'a>` is needed because it's only valid until | ||||
|         // the next call to sqlite3_step. | ||||
|         let val_ref = self.stmt.value_ref(idx); | ||||
|         Ok(val_ref) | ||||
|     } | ||||
|  | ||||
|     /// Get the value of a particular column of the result row as a `ValueRef`, | ||||
|     /// allowing data to be read out of a row without copying. | ||||
|     /// | ||||
|     /// This `ValueRef` is valid only as long as this Row, which is enforced by | ||||
|     /// it's lifetime. This means that while this method is completely safe, | ||||
|     /// it can be difficult to use, and most callers will be better served by | ||||
|     /// `get` or `get_checked`. | ||||
|     /// | ||||
|     /// ## Failure | ||||
|     /// | ||||
|     /// Panics if calling `row.get_raw_checked(idx)` would return an error, | ||||
|     /// including: | ||||
|     /// | ||||
|     ///    * If `idx` is outside the range of columns in the returned query. | ||||
|     ///    * If `idx` is not a valid column name for this row. | ||||
|     pub fn get_raw<I: RowIndex>(&self, idx: I) -> ValueRef<'a> { | ||||
|         self.get_raw_checked(idx).unwrap() | ||||
|     } | ||||
|  | ||||
|     /// Return the number of columns in the current row. | ||||
|     pub fn column_count(&self) -> usize { | ||||
|         self.stmt.column_count() | ||||
|   | ||||
| @@ -52,7 +52,7 @@ impl<'a> ValueRef<'a> { | ||||
|  | ||||
|     /// If `self` is case `Text`, returns the string value. Otherwise, returns | ||||
|     /// `Err(Error::InvalidColumnType)`. | ||||
|     pub fn as_str(&self) -> FromSqlResult<&str> { | ||||
|     pub fn as_str(&self) -> FromSqlResult<&'a str> { | ||||
|         match *self { | ||||
|             ValueRef::Text(t) => Ok(t), | ||||
|             _ => Err(FromSqlError::InvalidType), | ||||
| @@ -61,7 +61,7 @@ impl<'a> ValueRef<'a> { | ||||
|  | ||||
|     /// If `self` is case `Blob`, returns the byte slice. Otherwise, returns | ||||
|     /// `Err(Error::InvalidColumnType)`. | ||||
|     pub fn as_blob(&self) -> FromSqlResult<&[u8]> { | ||||
|     pub fn as_blob(&self) -> FromSqlResult<&'a [u8]> { | ||||
|         match *self { | ||||
|             ValueRef::Blob(b) => Ok(b), | ||||
|             _ => Err(FromSqlError::InvalidType), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user