@@ -328,6 +328,7 @@ impl PostgresConnection {
328328
329329 let trans = PostgresTransaction {
330330 conn: self,
331+ next_savepoint_id: Cell::new(0),
331332 commit: Cell::new(true)
332333 };
333334 // If this fails, Postgres will rollback when the connection closes
@@ -378,6 +379,7 @@ impl PostgresConnection {
378379
379380pub struct PostgresTransaction<'self> {
380381 priv conn: &'self PostgresConnection,
382+ priv next_savepoint_id: Cell<uint>,
381383 priv commit: Cell<bool>
382384}
383385
@@ -403,6 +405,30 @@ impl<'self> PostgresTransaction<'self> {
403405 self.conn.try_update(query, params)
404406 }
405407
408+ pub fn in_transaction<T>(&self, blk: &fn(&PostgresTransaction) -> T) -> T {
409+ let id = self.next_savepoint_id.take();
410+ let savepoint = fmt!(" savepoint_%u", id);
411+ self.next_savepoint_id.put_back(id + 1);
412+
413+ self.conn.quick_query(fmt!(" SAVEPOINT %s", savepoint));
414+
415+ let nested_trans = PostgresTransaction {
416+ conn: self.conn,
417+ next_savepoint_id: Cell::new(id + 1),
418+ commit: Cell::new(true)
419+ };
420+
421+ let ret = blk(&nested_trans);
422+
423+ if nested_trans.commit.take() {
424+ self.conn.quick_query(fmt!(" RELEASE %s", savepoint));
425+ } else {
426+ self.conn.quick_query(fmt!(" ROLLBACK TO %s", savepoint));
427+ }
428+
429+ ret
430+ }
431+
406432 pub fn will_commit(&self) -> bool {
407433 let commit = self.commit.take();
408434 self.commit.put_back(commit);
0 commit comments