rustrusqlite

Failing to specify return type for returning a rusqlite::MappedRows


I would like write a Rust function that, provided a rusqlite::Statement and a time interval (from, to), returns a rusqlite::MappedRows that I can then use as an interator to read rows from a database.

The get_mapped_rows function should return the MappedRows struct:

fn get_mapped_rows<'stmt>(
    stmt: &'stmt Statement,
    from: u64,
    to: u64
)-> MappedRows<'stmt, FnMut(&Row<'_>) -> Result<FromSql, Error>> {
    stmt
        .query(params![from, to])
            .unwrap()
            .mapped(Box::new(|row| {
                Ok(Box::new(row.get(0)?) as Box<dyn FromSql>)
            }))
}

And get_rows below calls it:

fn get_rows(conn: &mut Connection) {
    let mut stmt =
        conn.prepare("SELECT dbl_time FROM log WHERE time >= ?1 AND time < ?2")
        .unwrap();

    let mapped_rows = get_mapped_rows(stmt, 2, 4);

    while let Some(row_result) = mapped_rows.next() {
        match row_result {
            Ok(dbl_time) => { println!("dbl_time: {}", dbl_time); },
            _ => panic!("What happened?!"),
        }
    }
}

When compiling I get the following error:

error[E0782]: trait objects must include the `dyn` keyword
  --> src/main.rs:48:23
   |
48 | )-> MappedRows<'stmt, FnMut(&Row<'_>) -> Result<FromSql, Error>> {
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
help: add `dyn` keyword before this trait
   |
48 | )-> MappedRows<'stmt, dyn FnMut(&Row<'_>) -> Result<FromSql, Error>> {
   |                       +++

error[E0782]: trait objects must include the `dyn` keyword
  --> src/main.rs:48:49
   |
48 | )-> MappedRows<'stmt, FnMut(&Row<'_>) -> Result<FromSql, Error>> {
   |                                                 ^^^^^^^
   |
help: add `dyn` keyword before this trait
   |
48 | )-> MappedRows<'stmt, FnMut(&Row<'_>) -> Result<dyn FromSql, Error>> {
   |                                                 +++

I tried adding dyn according to the hints and a lot of other things including Boxing the FnMut and the FromSql part of the result. But no luck. I am getting the feeling that this is not the right way to solve my problem.

Update: This is what made it work:

fn get_mapped_rows<'stmt>(
    stmt: &'stmt mut Statement,
    from: u64,
    to: u64
)-> MappedRows<'stmt, impl FnMut(&Row<'_>) -> Result<i64, Error>> {
    stmt
        .query(params![from, to])
        .unwrap()
        .mapped(|row| {
            Ok(row.get(0)?)
        })
}

Solution

  • I got it working by updating the get_mapped_rows function to the following:

    fn get_mapped_rows<'stmt>(
        stmt: &'stmt mut Statement,
        from: u64,
        to: u64
    )-> MappedRows<'stmt, impl FnMut(&Row<'_>) -> Result<i64, Error>> {
        stmt
            .query(params![from, to])
            .unwrap()
            .mapped(|row| {
                Ok(row.get(0)?)
            })
    }
    

    What I learnt here is that you use impl FnMut to indicate a type known by the compiler (or rather, a signature I guess?). I tried initially to use impl FromSql instead of i64 in the Result but the compiler did not like that.