Add Rows::map method

This commit is contained in:
gwenn 2019-03-10 12:58:20 +01:00
parent 59a44cfae5
commit 71a2004894
7 changed files with 49 additions and 25 deletions

View File

@ -58,6 +58,7 @@ serde_json = { version = "1.0", optional = true }
csv = { version = "1.0", optional = true } csv = { version = "1.0", optional = true }
lazy_static = { version = "1.0", optional = true } lazy_static = { version = "1.0", optional = true }
byteorder = { version = "1.2", features = ["i128"], optional = true } byteorder = { version = "1.2", features = ["i128"], optional = true }
fallible-iterator = "0.1"
fallible-streaming-iterator = "0.1" fallible-streaming-iterator = "0.1"
memchr = "2.2.0" memchr = "2.2.0"

View File

@ -151,6 +151,7 @@ impl StatementCache {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use fallible_iterator::FallibleIterator;
use super::StatementCache; use super::StatementCache;
use crate::{Connection, NO_PARAMS}; use crate::{Connection, NO_PARAMS};
@ -277,12 +278,9 @@ mod test {
{ {
let mut stmt = db.prepare_cached(sql).unwrap(); let mut stmt = db.prepare_cached(sql).unwrap();
assert_eq!( assert_eq!(
1i32, Ok(Some(1i32)),
stmt.query_map::<i32, _, _>(NO_PARAMS, |r| r.get(0)) stmt.query(NO_PARAMS).unwrap().map(|r| r.get(0))
.unwrap()
.next() .next()
.unwrap()
.unwrap()
); );
} }
@ -297,12 +295,9 @@ mod test {
{ {
let mut stmt = db.prepare_cached(sql).unwrap(); let mut stmt = db.prepare_cached(sql).unwrap();
assert_eq!( assert_eq!(
(1i32, 2i32), Ok(Some((1i32, 2i32))),
stmt.query_map(NO_PARAMS, |r| Ok((r.get(0)?, r.get(1)?))) stmt.query(NO_PARAMS).unwrap().map(|r| Ok((r.get(0)?, r.get(1)?)))
.unwrap()
.next() .next()
.unwrap()
.unwrap()
); );
} }
} }

View File

@ -77,8 +77,6 @@ use std::str;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
pub use fallible_streaming_iterator::FallibleStreamingIterator;
use crate::cache::StatementCache; use crate::cache::StatementCache;
use crate::inner_connection::{InnerConnection, BYPASS_SQLITE_INIT}; use crate::inner_connection::{InnerConnection, BYPASS_SQLITE_INIT};
use crate::raw_statement::RawStatement; use crate::raw_statement::RawStatement;
@ -846,6 +844,7 @@ unsafe fn db_filename(_: *mut ffi::sqlite3) -> Option<PathBuf> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use fallible_iterator::FallibleIterator;
use self::tempdir::TempDir; use self::tempdir::TempDir;
pub use super::*; pub use super::*;
use crate::ffi; use crate::ffi;
@ -1132,8 +1131,7 @@ mod test {
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap(); let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
let results: Result<Vec<String>> = query let results: Result<Vec<String>> = query
.query_map(NO_PARAMS, |row| row.get(1)) .query(NO_PARAMS).unwrap().map(|row| row.get(1))
.unwrap()
.collect(); .collect();
assert_eq!(results.unwrap().concat(), "hello, world!"); assert_eq!(results.unwrap().concat(), "hello, world!");
@ -1322,7 +1320,7 @@ mod test {
.prepare("SELECT interrupt() FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)") .prepare("SELECT interrupt() FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)")
.unwrap(); .unwrap();
let result: Result<Vec<i32>> = stmt.query_map(NO_PARAMS, |r| r.get(0)).unwrap().collect(); let result: Result<Vec<i32>> = stmt.query(NO_PARAMS).unwrap().map(|r| r.get(0)).collect();
match result.unwrap_err() { match result.unwrap_err() {
Error::SqliteFailure(err, _) => { Error::SqliteFailure(err, _) => {

View File

@ -1,6 +1,8 @@
use fallible_iterator::FallibleIterator;
use fallible_streaming_iterator::FallibleStreamingIterator;
use std::{convert, result}; use std::{convert, result};
use super::{Error, FallibleStreamingIterator, Result, Statement}; use super::{Error, Result, Statement};
use crate::types::{FromSql, FromSqlError, ValueRef}; use crate::types::{FromSql, FromSqlError, ValueRef};
/// An handle for the resulting rows of a query. /// An handle for the resulting rows of a query.
@ -32,6 +34,13 @@ impl<'stmt> Rows<'stmt> {
self.advance()?; self.advance()?;
Ok((*self).get()) Ok((*self).get())
} }
pub fn map<F, B>(self, f: F) -> Map<'stmt, F>
where
F: FnMut(&Row<'_>) -> Result<B>,
{
Map { rows: self, f: f }
}
} }
impl<'stmt> Rows<'stmt> { impl<'stmt> Rows<'stmt> {
@ -56,6 +65,26 @@ impl Drop for Rows<'_> {
} }
} }
pub struct Map<'stmt, F> {
rows: Rows<'stmt>,
f: F,
}
impl<F, B> FallibleIterator for Map<'_, F>
where
F: FnMut(&Row<'_>) -> Result<B>,
{
type Error = Error;
type Item = B;
fn next(&mut self) -> Result<Option<B>> {
match self.rows.next()? {
Some(v) => Ok(Some((self.f)(v)?)),
None => Ok(None),
}
}
}
/// An iterator over the mapped resulting rows of a query. /// An iterator over the mapped resulting rows of a query.
pub struct MappedRows<'stmt, F> { pub struct MappedRows<'stmt, F> {
rows: Rows<'stmt>, rows: Rows<'stmt>,

View File

@ -10,13 +10,13 @@ use std::panic::{catch_unwind, RefUnwindSafe};
use std::ptr; use std::ptr;
use std::slice::{from_raw_parts, from_raw_parts_mut}; use std::slice::{from_raw_parts, from_raw_parts_mut};
use fallible_streaming_iterator::FallibleStreamingIterator;
use crate::error::error_from_sqlite_code; use crate::error::error_from_sqlite_code;
use crate::ffi; use crate::ffi;
use crate::hooks::Action; use crate::hooks::Action;
use crate::types::ValueRef; use crate::types::ValueRef;
use crate::{ use crate::{errmsg_to_string, str_to_cstring, Connection, DatabaseName, Result};
errmsg_to_string, str_to_cstring, Connection, DatabaseName, FallibleStreamingIterator, Result,
};
// https://sqlite.org/session.html // https://sqlite.org/session.html
@ -720,10 +720,11 @@ unsafe extern "C" fn x_output(p_out: *mut c_void, data: *const c_void, len: c_in
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use fallible_streaming_iterator::FallibleStreamingIterator;
use super::{Changeset, ChangesetIter, ConflictAction, ConflictType, Session}; use super::{Changeset, ChangesetIter, ConflictAction, ConflictType, Session};
use crate::hooks::Action; use crate::hooks::Action;
use crate::{Connection, FallibleStreamingIterator}; use crate::Connection;
fn one_changeset() -> Changeset { fn one_changeset() -> Changeset {
let db = Connection::open_in_memory().unwrap(); let db = Connection::open_in_memory().unwrap();

View File

@ -168,7 +168,7 @@ impl Statement<'_> {
/// ## Example /// ## Example
/// ///
/// ```rust,no_run /// ```rust,no_run
/// # use rusqlite::{Connection, FallibleStreamingIterator, Result, NO_PARAMS}; /// # use rusqlite::{Connection, Result, NO_PARAMS};
/// fn get_names(conn: &Connection) -> Result<Vec<String>> { /// fn get_names(conn: &Connection) -> Result<Vec<String>> {
/// let mut stmt = conn.prepare("SELECT name FROM people")?; /// let mut stmt = conn.prepare("SELECT name FROM people")?;
/// let mut rows = stmt.query(NO_PARAMS)?; /// let mut rows = stmt.query(NO_PARAMS)?;
@ -204,7 +204,7 @@ impl Statement<'_> {
/// ## Example /// ## Example
/// ///
/// ```rust,no_run /// ```rust,no_run
/// # use rusqlite::{Connection, FallibleStreamingIterator, Result}; /// # use rusqlite::{Connection, Result};
/// fn query(conn: &Connection) -> Result<()> { /// fn query(conn: &Connection) -> Result<()> {
/// let mut stmt = conn.prepare("SELECT * FROM test where name = :name")?; /// let mut stmt = conn.prepare("SELECT * FROM test where name = :name")?;
/// let mut rows = stmt.query_named(&[(":name", &"one")])?; /// let mut rows = stmt.query_named(&[(":name", &"one")])?;
@ -219,7 +219,7 @@ impl Statement<'_> {
/// and so the above example could also be written as: /// and so the above example could also be written as:
/// ///
/// ```rust,no_run /// ```rust,no_run
/// # use rusqlite::{Connection, FallibleStreamingIterator, Result, named_params}; /// # use rusqlite::{Connection, Result, named_params};
/// fn query(conn: &Connection) -> Result<()> { /// fn query(conn: &Connection) -> Result<()> {
/// let mut stmt = conn.prepare("SELECT * FROM test where name = :name")?; /// let mut stmt = conn.prepare("SELECT * FROM test where name = :name")?;
/// let mut rows = stmt.query_named(named_params!{ ":name": "one" })?; /// let mut rows = stmt.query_named(named_params!{ ":name": "one" })?;

View File

@ -345,6 +345,7 @@ impl From<csv::Error> for Error {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use fallible_iterator::FallibleIterator;
use crate::vtab::csvtab; use crate::vtab::csvtab;
use crate::{Connection, Result, NO_PARAMS}; use crate::{Connection, Result, NO_PARAMS};
@ -363,8 +364,7 @@ mod test {
} }
let ids: Result<Vec<i32>> = s let ids: Result<Vec<i32>> = s
.query_map(NO_PARAMS, |row| row.get::<_, i32>(0)) .query(NO_PARAMS).unwrap().map(|row| row.get::<_, i32>(0))
.unwrap()
.collect(); .collect();
let sum = ids.unwrap().iter().sum::<i32>(); let sum = ids.unwrap().iter().sum::<i32>();
assert_eq!(sum, 15); assert_eq!(sum, 15);