How to re-use an sqlx::Executor?

1.9k views Asked by At

I'm trying to develop an app server in Rust using SQLX for back-end storage. It's for a primitive CMS with some idiosyncratic default behavior, to wit: if the page is not found, generate it automatically with some blank content. I want to be able to re-use the functions that invoke the SQL, so I want them to take types implementing the sqlx::Executor trait, including &mut sqlx::Connection, &mut sqlx::pool::PoolConnection, and &mut sqlx::Transaction.

Every function with a single call to the database works great!

However, it seems like I can't re-use an executor. This function is called after I've determined the page does not exist; I create a transaction and call it with an &mut Transaction as the e argument:

async fn create_page_for_title(e: impl Executor<'_, Database = Sqlite>, title: &str) -> SqlResult<RawPage> {
    let newcontent_id = insert_new_root_content(e).await?;
    let newpage = insert_new_page(e, title, newcontent_id).await?;
    Ok(newpage)
}

And this is what Rust (1.46) says:

Error[E0382]: use of moved value: `e`
   --> src/store.rs:239:30
    |
230 | async fn create_page_for_title(e: impl Executor<'_, Database = Sqlite>, title: &str) -> SqlResult<RawPage>
    |                                - move occurs because `e` has type `impl Executor<'_, Database = Sqlite>`, which does not implement the `Copy` trait
...
238 |     let newcontent_id = insert_new_root_content(e).await?;
    |                                                 - value moved here
239 |     let newpage = insert_new_page(e, title, newcontent_id).await?;
    |                                   ^ value used here after move

I know e is a reference, and references are Copy. But I seem to be unable to convince Rust of this, and I'm not sure why. This is the only function where I use an impl Executor twice in the same scope, but I'm sure I'll discover more as time goes on. Please help?

0

There are 0 answers