withSavepoint<T> method
Runs action within a savepoint named name. On success the savepoint
is released; on any thrown exception we rollback to the savepoint, then
rethrow so the caller can decide what to do with the surrounding
transaction.
This is the recommended way to do partial-rollback inside a longer transaction.
Implementation
Future<T> withSavepoint<T>(
String name,
Future<T> Function() action,
) async {
if (!createSavepoint(name)) {
throw StateError('Failed to create savepoint "$name" on txn $_txnId');
}
try {
final result = await action();
releaseSavepoint(name);
return result;
} on Object {
rollbackToSavepoint(name);
// We do not auto-release after rollback: SQL-92 keeps the savepoint
// alive after ROLLBACK TO, and SQL Server has no RELEASE at all.
rethrow;
}
}