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?