Commit Statement

The commit statement in Surreal ORM is used to commit a transaction and save the changes made within the transaction. It ensures that the changes are durable and permanent in the database.

Table of Contents

Using block! Macro with Commit Statement also Within Block for Chaining Multiple Statements

To perform a transaction and commit the changes, you can use the block! macro to chain multiple statements together. The commit_transaction statement is used within the block! macro to explicitly indicate the commitment of the transaction. Let's take a look at an example:

#![allow(unused)]
fn main() {
let db = Surreal::new::<Mem>(()).await.unwrap();
db.use_ns("test").use_db("test").await.unwrap();

let ref id1 = Account::create_id("one".into());
let ref id2 = Account::create_id("two".into());
let acc = Account::schema();

let amount_to_transfer = 300.00;

block! {
    BEGIN TRANSACTION;

    LET acc1 = create().content(Account {
        id: id1.clone(),
        balance: 135_605.16,
    });
    LET acc2 = create().content(Account {
        id: id2.clone(),
        balance: 91_031.31,
    });

    LET updated1 = update::<Account>(id1).set(acc.balance.increment_by(amount_to_transfer));
    LET update2 = update::<Account>(id2).set(acc.balance.decrement_by(amount_to_transfer));

    COMMIT TRANSACTION;
};

Ok(())
}

In the code snippet above, the block! macro is used to define a transaction with multiple statements. The LET statement is used to bind variables acc1, acc2, updated1, and update2 to the respective statements. The BEGIN TRANSACTION statement marks the start of the transaction, and the COMMIT TRANSACTION statement explicitly commits the transaction.

The generated SQL query for this code block would look like:

BEGIN TRANSACTION;

LET acc1 = CREATE account CONTENT { balance: 135605.16, id: account:one };
LET acc2 = CREATE account CONTENT { balance: 91031.31, id: account:two };
LET updated1 = UPDATE account:one SET balance += 300.0;
LET update2 = UPDATE account:two SET balance -= 300.0;

COMMIT TRANSACTION;

Using the block! macro with the commit_transaction statement within the block provides a clear and concise way to define a transaction and commit the changes.

Using block! Macro for Chaining Multiple Statements

Another recommended approach is to use the block! macro to chain multiple statements together within a transaction. The commit_transaction statement is called separately after the block! macro to explicitly commit the transaction. Let's see an example:

#![allow(unused)]
fn main() {
let db = Surreal::new::<Mem>(()).await.unwrap();
db.use_ns("test").use_db("test").await.unwrap();

let ref id1 = Account

::create_id("one".into());
let ref id2 = Account::create_id("two".into());
let acc = Account::schema();

let amount_to_transfer = 300.00;

let transaction_query = begin_transaction()
    .query(block! {
        LET acc1 = create().content(Account {
            id: id1.clone(),
            balance: 135_605.16,
        });
        LET acc2 = create().content(Account {
            id: id2.clone(),
            balance: 91_031.31,
        });

        LET updated1 = update::<Account>(id1).set(acc.balance.increment_by(amount_to_transfer));
        LET update2 = update::<Account>(id2).set(acc.balance.decrement_by(amount_to_transfer));
    })
    .commit_transaction();

transaction_query.run(db.clone()).await?;

Ok(())
}

In this approach, the block! macro is used to define a transaction block that includes multiple statements. The BEGIN TRANSACTION and COMMIT TRANSACTION statements mark the start and end of the transaction, respectively. The LET statement is used to bind variables to the statements within the block.

The generated SQL query for this code block would be the same as the previous approach.

Using the block! macro for chaining multiple statements and explicitly committing the transaction provides a more structured and organized way to handle complex transactions.

The less recommended approach involves chaining multiple statements directly without using the block! macro. Although functional, this approach may feel less ergonomic, especially when there is a need to bind and share variables within the statements.

Chaining Multiple Statements Directly

Here's an example of chaining multiple statements directly without using the block! macro:

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_transaction_commit_increment_and_decrement_update() -> SurrealOrmResult<()> {
    let db = Surreal::new::<Mem>(()).await.unwrap();
    db.use_ns("test").use_db("test").await.unwrap();

    let ref id1 = Account::create_id("one".into());
    let ref id2 = Account::create_id("two".into());
    let amount_to_transfer = 300.00;

    let acc = Account::schema();

    begin_transaction()
        .query(create().content(Account {
            id: id1.clone(),
            balance: 135_605.16,
        }))
        .query(create().content(Account {
            id: id2.clone(),
            balance: 91_031.31,
        }))
        .query(update::<Account>(id1).set(acc.balance.increment_by(amount_to_transfer)))
        .query(update::<Account>(id2).set(acc.balance.decrement_by(amount_to_transfer)))
        .commit_transaction()
        .run(db.clone())
        .await?;

    // Assertions and other code...

    Ok(())
}
}

In this approach, multiple statements are chained directly within the transaction. The create and update statements are used to perform operations on the Account table.

The generated SQL query for this code block would be the same as the previous approaches.

The less recommended approach of chaining multiple statements directly can be less ergonomic, especially when dealing with complex transactions that require variable bindings and subqueries.

It is generally recommended to use the recommended approaches with the block! macro for better readability, automation of variable bindings, and subquery handling.

That concludes the documentation for the commit statement in Surreal ORM. Use the recommended approaches to perform transactions and commit changes effectively.