sqlx icon indicating copy to clipboard operation
sqlx copied to clipboard

`Executor` not implemented for `&mut Transaction` - Missleading/Incomplete example in docs

Open DragonDev1906 opened this issue 3 months ago • 3 comments

I have found these related issues/pull requests

https://github.com/launchbadge/sqlx/pull/3311 https://docs.rs/sqlx/latest/sqlx/struct.Transaction.html

Description

The second select in the code sample below returns the following error, even though that's how you're supposed to work with transactions (it does work if done like in the example linked above where everything is in the same function.

The workaround I've found is to call .as_mut(), as the PR initially suggested. This can be seen as me overlooking that * only gives me the Transaction and doesn't call deref on the transaction (see second working example), but in that case it might still be a good idea to put that into the documentation so others don't have to dig through issues+PRs here.

the trait `Executor<'_>` is not implemented for `&mut sqlx::Transaction<'_, Sqlite>`

Reproduction steps

async fn test(txn: &mut Transaction<'_, Sqlite>) {
    // Works
    sqlx::query("SELECT 1").execute(txn.as_mut()).await.unwrap();
    // Doesn't work but is suggested by the docs
    // Granted, in the docs `txn` is not behind a reference.
    sqlx::query("SELECT 1").execute(&mut *txn).await.unwrap();
    // Also works
    sqlx::query("SELECT 1").execute(&mut **txn).await.unwrap();
}

SQLx version

0.8.6

Enabled SQLx features

"runtime-tokio", "sqlite"

Database server and version

Sqlite 3.50.4

Operating system

Linux

Rust version

rustc 1.90.0 (1159e78c4 2025-09-14)

DragonDev1906 avatar Oct 07 '25 11:10 DragonDev1906

Not sure how the example is misleading. Right the big difference is that in the example the tx is and owned sqlx::Transaction. The Executor trait is not implemented for a Transaction but the underlying sqlx::Connection, which you can get by dereferencing to it. The Executor trait is also not implemented for a &mut Transaction so you need to deref twice, once to get to the transaction and once to get to the Connection in the transaction. That is the reason for the extra deref.

There are examples how you can reuse a transaction, e.g. in the transaction example.

joeydewaal avatar Oct 18 '25 10:10 joeydewaal

I get why a double deref is needed (after searching for half an hour or so). My main point is that this feels common enough to warrant being mentioned in the above linked documentation, and not just in an example (outside of docs.rs), which is "hidden" in a backend/db subfolder. So when looking for a seemingly sqlite specific problem (it isn't, sqlite specific, I know that now) you don't tend to look there.

When I started writing this issue I didn't even know about the double deref and thought txn.as_mut() was the only/intended way (which I only found out by looking through issues + PRs on github that contained a similar error message.

Hence my suggestion to add such an example to the doctest/example on Transaction, which is where I was looking first (maybe should've made that clearer in the issue description).

DragonDev1906 avatar Oct 20 '25 06:10 DragonDev1906

True, it might be useful to have an example for this in the docs. I can image that more people run into this situation and the solution isn't that obvious.

joeydewaal avatar Oct 22 '25 21:10 joeydewaal