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: Add savepoint documentation. #223

Merged
merged 6 commits into from
Dec 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions docs/06-concepts/06-database/08-transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,62 @@ The available isolation levels are:
| Serializable | `IsolationLevel.serializable` | Gives the same guarantees as `IsolationLevel.repeatableRead` but also throws if read rows are updated by other transactions. |

For a detailed explanation of the different isolation levels, see the [PostgreSQL documentation](https://www.postgresql.org/docs/current/transaction-iso.html).

## Savepoints

A savepoint is a special mark inside a transaction that allows all commands that are executed after it was established to be rolled back, restoring the transaction state to what it was at the time of the savepoint.

Read more about savepoints in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-savepoint.html).

### Creating savepoints
To create a savepoint, call the `createSavepoint` method on the transaction object:

```dart
await session.db.transaction((transaction) async {
await Company.db.insertRow(session, company, transaction: transaction);
// Create savepoint
var savepoint = await transaction.createSavepoint();
await Employee.db.insertRow(session, employee, transaction: transaction);
});
```

In the example, we create a savepoint after inserting a company but before inserting the employee. This gives us the option to roll back to the savepoint and preserve the company insertion.

#### Rolling back to savepoints

Once a savepoint is created, you can roll back to it by calling the `rollback` method on the savepoint object:

```dart
await session.db.transaction((transaction) async {
// Changes preserved in the database
await Company.db.insertRow(session, company, transaction: transaction);

// Create savepoint
var savepoint = await transaction.createSavepoint();

await Employee.db.insertRow(session, employee, transaction: transaction);
// Changes rolled back
await savepoint.rollback();
});
```

In the example, we create a savepoint after inserting a company. We then insert an employee but invoke a rollback to our savepoint. This results in the database preserving the company but not the employee insertion.

#### Releasing savepoints

Savepoints can also be released, which means that the changes made after the savepoint are preserved in the transaction. Releasing a savepoint will also render any subsequent savepoints invalid.

To release a savepoint, call the `release` method on the savepoint object:

```dart
await session.db.transaction((transaction) async {
// Create two savepoints
var savepoint = await transaction.createSavepoint();
var secondSavepoint = await transaction.createSavepoint();

await Company.db.insertRow(session, company, transaction: transaction);
await savepoint.release();
});
```

In the example, two savepoints are created. After the company is inserted the first savepoint is released, which renders the second savepoint invalid. If the second savepoint is used to rollback, an exception will be thrown.
Loading