diff --git a/postgres/src/transaction.rs b/postgres/src/transaction.rs index 60b1dcb0..1dfdc7d3 100644 --- a/postgres/src/transaction.rs +++ b/postgres/src/transaction.rs @@ -244,7 +244,7 @@ impl<'conn> Transaction<'conn> { /// /// Panics if there is an active nested transaction. pub fn transaction<'a>(&'a self) -> Result> { - self.savepoint("sp") + self.savepoint(format!("sp_{}", self.depth())) } /// Like `Connection::transaction`, but creates a nested transaction via @@ -253,7 +253,14 @@ impl<'conn> Transaction<'conn> { /// # Panics /// /// Panics if there is an active nested transaction. - pub fn savepoint<'a>(&'a self, name: &str) -> Result> { + #[inline] + pub fn savepoint<'a, I>(&'a self, name: I) -> Result> + where I: Into + { + self._savepoint(name.into()) + } + + fn _savepoint<'a>(&'a self, name: String) -> Result> { let mut conn = self.conn.0.borrow_mut(); check_desync!(conn); assert!( @@ -265,7 +272,7 @@ impl<'conn> Transaction<'conn> { Ok(Transaction { conn: self.conn, depth: self.depth + 1, - savepoint_name: Some(name.to_owned()), + savepoint_name: Some(name), commit: Cell::new(false), finished: false, }) diff --git a/postgres/tests/test.rs b/postgres/tests/test.rs index 13ef53e7..753d9d9a 100644 --- a/postgres/tests/test.rs +++ b/postgres/tests/test.rs @@ -331,6 +331,41 @@ fn test_nested_transactions_finish() { ); } +#[test] +fn test_nested_transactions_partial_rollback() { + let conn = or_panic!(Connection::connect( + "postgres://postgres@localhost:5433", + TlsMode::None, + )); + or_panic!(conn.execute("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY)", &[])); + + or_panic!(conn.execute("INSERT INTO foo (id) VALUES ($1)", &[&1i32])); + + { + let trans = or_panic!(conn.transaction()); + or_panic!(trans.execute("INSERT INTO foo (id) VALUES ($1)", &[&2i32])); + { + let trans = or_panic!(trans.transaction()); + or_panic!(trans.execute("INSERT INTO foo (id) VALUES ($1)", &[&3i32])); + { + let trans = or_panic!(trans.transaction()); + or_panic!(trans.execute("INSERT INTO foo (id) VALUES ($1)", &[&4i32])); + drop(trans); + } + drop(trans); + } + or_panic!(trans.commit()); + } + + let stmt = or_panic!(conn.prepare("SELECT * FROM foo ORDER BY id")); + let result = or_panic!(stmt.query(&[])); + + assert_eq!( + vec![1i32, 2], + result.iter().map(|row| row.get(0)).collect::>() + ); +} + #[test] #[should_panic(expected = "active transaction")] fn test_conn_trans_when_nested() {