-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sqlx lost transaction support starting version 0.7.0 #2699
Comments
Please read the 0.7 changelog and look at the current examples. This is not a bug, just a breaking change how transactions are used |
@goodjius . Here is the relevant part of the changelog mentioned by @dragonnn
What helped was using My example self.conn.transaction(|tx| Box::pin(async move {
sqlx::query(
r#"...
"#,
).bind(...)
.execute(tx.as_mut())
.await?;
Ok::<_, eyre::Error>(())
})).await?; In your example this would be: let mut tx = pool.begin().await?;
let res = sqlx::query("DELETE FROM \"testcases\" WHERE id = $1")
.bind(id)
.execute(tx.as_mut()) // <-- here
.await?
.rows_affected();
tx.commit().await?; |
Hi, sorry for bumping this old issue. I stumbled across the same problem, I wanted to use a transaction in a personal project and I wasn't able to get it to work at first. The examples in this repo were able to help me and I got it working, but I think it would be nice to add a short example on how to use Is that a good idea? If yes, I would submit a PR 😄. |
@Lachstec Yes please do it. |
@fosskers Okay, I will get to it if I find some time today. |
@fosskers I've submitted a PR where I added a Snippet inspired by the one in this issue, hope that it is fine like that :) |
Currently, there are only these scenarios available: /// Scenario 1: pool/tx interface + multiple queries
///
/// TLDR we should never want this ambiguity
///
/// for a single query this one will work just fine
pub async fn run(executor: impl Executor<'_, Database = Postgres>) {
sqlx::query("SELECT 1").execute(executor).await.unwrap();
sqlx::query("SELECT 1").execute(executor).await.unwrap();
// error: ^^^^^^^^ value used after move
}
/// Scenario 2: we want to use the same executor for multiple queries
///
/// we can demand Executor: Copy
pub async fn run_copy(executor: impl Executor<'_, Database = Postgres> + std::marker::Copy) {
sqlx::query("SELECT 1").execute(executor).await.unwrap();
run_copy(executor).await;
sqlx::query("SELECT 1").execute(executor).await.unwrap();
}
/// Scenario 3: we want to use the same executor for multiple queries
///
/// We can specify an executor type as a Transaction explicitly
/// This allows us to use transactions as normal with multiple queries
#[async_recursion::async_recursion]
pub async fn run_atomic(executor: &mut Transaction<'_, Postgres>) {
sqlx::query("SELECT 1").execute(&mut **executor).await.unwrap();
run_atomic(executor).await;
sqlx::query("SELECT 1").execute(&mut **executor).await.unwrap();
}
pub async fn outer_logic(pool: sqlx::Pool<Postgres>) {
{
// Scenario 2 use
// w/o transaction -- works
run_copy(&pool).await;
run_copy(&pool).await;
// with transaction won't work
}
{
// Scenario 3 use
// w/o transaction
// run_atomic(&pool).await; // error: cannot use pool
// with transaction -- works
let mut tx = pool.begin().await.unwrap();
sqlx::query("SELECT 1").execute(&mut *tx).await.unwrap();
run_atomic(&mut tx).await;
sqlx::query("SELECT 1").execute(&mut *tx).await.unwrap();
tx.commit().await.unwrap();
}
} I prefer Scenario 3 as universal. And the cost is small: you should make every query in transactions, which is not a big deal most of the time. |
Bug Description
Get error: .fetch_one(&mut tx)
| --------- ^^^^^^^ the trait
Executor<'_>
is not implemented for&mut Transaction<'_, Sqlite>
.This is no problem with sqlx 0.6.x.
Compiler start to complain starting 0.7.0
Minimal Reproduction
Info
rustc --version
: 1.71.0The text was updated successfully, but these errors were encountered: