Rusqlite query params match borrowing issue

I'm trying to some how unify simple SQL queries by generating appropriate strings. However I'm stuck with rusqlite params matching:

pub fn find_taglines(search_params: Option<(SearchType, String)>) -> Result<Vec<Tagline>>{
    let conn = open_connection().unwrap();

    let options: (String, &[&dyn ToSql]) = match search_params {
        Some((search_type, value)) => {
            (get_search_by_query(search_type), params![value])
        },
        None => (String::from(SELECT_QUERY), &[]),
    };

and I get those errors:

error[E0716]: temporary value dropped while borrowed
  --> src/models.rs:71:52
   |
69 |         let options: (String, &[&dyn ToSql]) = match search_params {
   |             ------- borrow later stored here
70 |             Some((search_type, value)) => {
71 |                 (get_search_by_query(search_type), params![value])
   |                                                    ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
72 |             },
   |             - temporary value is freed at the end of this statement
   |
   = note: consider using a `let` binding to create a longer lived value
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0597]: `value` does not live long enough
  --> src/models.rs:71:52
   |
69 |         let options: (String, &[&dyn ToSql]) = match search_params {
   |             ------- borrow later stored here
70 |             Some((search_type, value)) => {
71 |                 (get_search_by_query(search_type), params![value])
   |                                                    ^^^^^^^^^^^^^^ borrowed value does not live long enough
72 |             },
   |              - `value` dropped here while still borrowed
   |
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to 2 previous errors

So I'm not really sure how to solve it in context of rusqlite internal types.

With a bit of guessing based on the code:

I believe the issue is that your match is taking apart your search_params. So the search_type and value values will now live in the scope of the match arm they are bound in. And at the end of that, they'll be dropped.

This causes the problem because you want to go from a value holding a String to a &dyn ToSql as rusqlite expects. But that match arm can't return a borrowed trait object pointing to a value that will be dropped after the match.

If your search_type implements Copy, the solution might be as simple as changing Some((search_type, value)) to Some((search_type, ref value)) (note the ref). The value will be a &String borrowed from the search_params instead of a plain owned String that is dropped.

1 Like

Looks like I messed up a bit. I isolated the problem up until this point:

    use rusqlite::{NO_PARAMS, params};

    let mut params = NO_PARAMS;
    if input_val != "" {
        params = params![input_val];
    }

And I get this error during compilation:

75 |             params = params![input_val];
   |                      ^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
   |                      |
   |                      creates a temporary which is freed while still in use

And the only solution I ended up is to move params macro outside of conditional scope. But there should be a better way!