Skip to content
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

fix and extend postgres transaction example #1636

Merged
merged 1 commit into from
Feb 17, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
95 changes: 81 additions & 14 deletions examples/postgres/transaction/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,104 @@
use sqlx::query;

#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let conn_str =
std::env::var("DATABASE_URL").expect("Env var DATABASE_URL is required for this example.");
let pool = sqlx::PgPool::connect(&conn_str).await?;

let mut transaction = pool.begin().await?;

let test_id = 1;
async fn insert_and_verify(
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
test_id: i64,
) -> Result<(), Box<dyn std::error::Error>> {
query!(
r#"INSERT INTO todos (id, description)
VALUES ( $1, $2 )
"#,
test_id,
"test todo"
)
.execute(&mut transaction)
.execute(&mut *transaction)
.await?;

// check that inserted todo can be fetched
// check that inserted todo can be fetched inside the uncommitted transaction
let _ = query!(r#"SELECT FROM todos WHERE id = $1"#, test_id)
.fetch_one(&mut transaction)
.fetch_one(transaction)
.await?;

transaction.rollback();
Ok(())
}

async fn explicit_rollback_example(
pool: &sqlx::PgPool,
test_id: i64,
) -> Result<(), Box<dyn std::error::Error>> {
let mut transaction = pool.begin().await?;

insert_and_verify(&mut transaction, test_id).await?;

transaction.rollback().await?;

Ok(())
}

async fn implicit_rollback_example(
pool: &sqlx::PgPool,
test_id: i64,
) -> Result<(), Box<dyn std::error::Error>> {
let mut transaction = pool.begin().await?;

insert_and_verify(&mut transaction, test_id).await?;

// no explicit rollback here but the transaction object is dropped at the end of the scope
Ok(())
}

async fn commit_example(
pool: &sqlx::PgPool,
test_id: i64,
) -> Result<(), Box<dyn std::error::Error>> {
let mut transaction = pool.begin().await?;

insert_and_verify(&mut transaction, test_id).await?;

transaction.commit().await?;

// check that inserted todo is now gone
Ok(())
}

#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let conn_str =
std::env::var("DATABASE_URL").expect("Env var DATABASE_URL is required for this example.");
let pool = sqlx::PgPool::connect(&conn_str).await?;

let test_id = 1;

// remove any old values that might be in the table already with this id from a previous run
let _ = query!(r#"DELETE FROM todos WHERE id = $1"#, test_id)
.execute(&pool)
.await?;

explicit_rollback_example(&pool, test_id).await?;

// check that inserted todo is not visible outside the transaction after explicit rollback
let inserted_todo = query!(r#"SELECT FROM todos WHERE id = $1"#, test_id)
.fetch_one(&pool)
.await;

assert!(inserted_todo.is_err());

implicit_rollback_example(&pool, test_id).await?;

// check that inserted todo is not visible outside the transaction after implicit rollback
let inserted_todo = query!(r#"SELECT FROM todos WHERE id = $1"#, test_id)
.fetch_one(&pool)
.await;

assert!(inserted_todo.is_err());

commit_example(&pool, test_id).await?;

// check that inserted todo is visible outside the transaction after commit
let inserted_todo = query!(r#"SELECT FROM todos WHERE id = $1"#, test_id)
.fetch_one(&pool)
.await;

assert!(inserted_todo.is_ok());

Ok(())
}