From e4eda2041e804f38922952cac1ee2e1e974e191b Mon Sep 17 00:00:00 2001 From: Patrick Fernie Date: Thu, 27 Aug 2015 14:01:01 -0400 Subject: [PATCH] Implement SqliteConnection::query_row_and_then() --- src/lib.rs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 229cc8e..91f32db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -302,6 +302,37 @@ impl SqliteConnection { } } + /// Convenience method to execute a query that is expected to return a single row, + /// and execute a mapping via `f` on that returned row with the possibility of failure. + /// The `Result` type of `f` must implement `std::convert::From`. + /// + /// ## Example + /// + /// ```rust,no_run + /// # use rusqlite::{SqliteResult,SqliteConnection}; + /// fn preferred_locale(conn: &SqliteConnection) -> SqliteResult { + /// conn.query_row_and_then("SELECT value FROM preferences WHERE name='locale'", &[], |row| { + /// row.get_checked(0) + /// }) + /// } + /// ``` + /// + /// If the query returns more than one row, all rows except the first are ignored. + pub fn query_row_and_then(&self, sql: &str, params: &[&ToSql], f: F) -> Result + where F: FnOnce(SqliteRow) -> Result, + E: convert::From { + let mut stmt = try!(self.prepare(sql)); + let mut rows = try!(stmt.query(params)); + + match rows.next() { + Some(row) => row.map_err(E::from).and_then(f), + None => Err(E::from(SqliteError{ + code: ffi::SQLITE_NOTICE, + message: "Query did not return a row".to_string(), + })) + } + } + /// Convenience method to execute a query that is expected to return a single row. /// /// ## Example @@ -779,8 +810,6 @@ impl<'stmt, T, E, F> Iterator for AndThenRows<'stmt, F> F: FnMut(SqliteRow) -> Result { type Item = Result; - // Through the magic of FromIterator, if F returns a Result, - // you can collect that to a Result, E> fn next(&mut self) -> Option { self.rows.next().map(|row_result| row_result .map_err(E::from)