diff --git a/docs/docs/database.md b/docs/docs/database.md index 12462d2..b179df5 100644 --- a/docs/docs/database.md +++ b/docs/docs/database.md @@ -51,7 +51,19 @@ defer session.deinit(); Using sessions, you can start transactions and use savepoints. +::: warning +You probably want to rollback all active transactions in `defer`, so that none remain active after leaving the active branch. +::: + ```zig +// Start a new session. +var session = try zrm.Session.init(database); +defer { + // Rollback all active transactions that remain active. + session.rollbackAll(); + session.deinit(); +}; + try session.beginTransaction(); // Do something. diff --git a/src/session.zig b/src/session.zig index 043cd97..3bd7862 100644 --- a/src/session.zig +++ b/src/session.zig @@ -12,6 +12,9 @@ pub const Session = struct { /// The active connection for the session. connection: *pg.Conn, + /// The count of active transactions for the session. + activeTransactions: usize = 0, + /// Execute a comptime-known SQL command for the current session. fn exec(self: Self, comptime sql: []const u8) !void { _ = self.connection.exec(sql, .{}) catch |err| { @@ -29,11 +32,25 @@ pub const Session = struct { try self.exec("ROLLBACK;"); } + /// Rollback all active transactions. + pub fn rollbackAll(self: Self) !void { + for (0..self.activeTransactions) |_| { + self.rollbackTransaction(); + } + } + /// Commit the current transaction. pub fn commitTransaction(self: Self) !void { try self.exec("COMMIT;"); } + /// Commit all active transactions. + pub fn commitAll(self: Self) !void { + for (0..self.activeTransactions) |_| { + self.commitTransaction(); + } + } + /// Create a new savepoint with the given name. pub fn savepoint(self: Self, comptime _savepoint: []const u8) !void { try self.exec("SAVEPOINT " ++ _savepoint ++ ";");