Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boxing a rusqlite Rows iterator

Tags:

rust

rusqlite

I am having trouble figuring out how to return an Iterator (impl or Box) when using prepare and query.

Here is what I have tried:

fn foo<'a>(
    conn: &'a mut rusqlite::Connection
) -> Box<impl 'a + fallible_streaming_iterator::FallibleStreamingIterator<Item=rusqlite::Row<'a>>> {
    Box::new(
        conn
            .prepare("SELECT a, b FROM t")
            .unwrap()
            .query(rusqlite::NO_PARAMS)
            .unwrap()
    )
}

The problem is the prepared statement is a temporary variable owned by the function scope. (error[E0515]: cannot return value referencing temporary value).

like image 909
tcn Avatar asked Mar 16 '26 23:03

tcn


1 Answers

Not possible to return FallibleStreamingIterator<Item=rusqlite::Row<'a>> instance from foo function.

Rust borrow checker will not allow to do that.

To understand why, we need to understand how rusqlite::Rows<'a> is structured.

/// An handle for the resulting rows of a query.
#[must_use = "Rows is lazy and will do nothing unless consumed"]
pub struct Rows<'stmt> {
    pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
    row: Option<Row<'stmt>>,
}

Github source: Rows

and it's FallibleStreamingIterator implementation looks like

impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
    type Error = Error;
    type Item = Row<'stmt>;

    #[inline]
    fn advance(&mut self) -> Result<()> {
    ...

Github source: FallibleStreamingIterator

Rows holds a reference to Statement. Let's try to infer lifetime 'stmt here.

      Statement (scope limited to `foo` func)
          |
         Rows (refers Statement so valid scope `foo`)
          |
FallibleStreamingIterator (refers Rows so valid scope `foo`)

Possible solution could be

  1. either Return owned rusqlite::Statement<'a> and query on desired location
  2. or Return the computed resultset (owned)
like image 63
Arjun Avatar answered Mar 19 '26 12:03

Arjun