Merge pull request #374 from rustonaut/fix_371_savepoint_nameing_in_nested_transactions

Fix #371 savepoint nameing in nested transactions
This commit is contained in:
Steven Fackler 2018-09-26 15:23:19 -07:00 committed by GitHub
commit 86b65aae22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 3 deletions

View File

@ -244,7 +244,7 @@ impl<'conn> Transaction<'conn> {
/// ///
/// Panics if there is an active nested transaction. /// Panics if there is an active nested transaction.
pub fn transaction<'a>(&'a self) -> Result<Transaction<'a>> { pub fn transaction<'a>(&'a self) -> Result<Transaction<'a>> {
self.savepoint("sp") self.savepoint(format!("sp_{}", self.depth()))
} }
/// Like `Connection::transaction`, but creates a nested transaction via /// Like `Connection::transaction`, but creates a nested transaction via
@ -253,7 +253,14 @@ impl<'conn> Transaction<'conn> {
/// # Panics /// # Panics
/// ///
/// Panics if there is an active nested transaction. /// Panics if there is an active nested transaction.
pub fn savepoint<'a>(&'a self, name: &str) -> Result<Transaction<'a>> { #[inline]
pub fn savepoint<'a, I>(&'a self, name: I) -> Result<Transaction<'a>>
where I: Into<String>
{
self._savepoint(name.into())
}
fn _savepoint<'a>(&'a self, name: String) -> Result<Transaction<'a>> {
let mut conn = self.conn.0.borrow_mut(); let mut conn = self.conn.0.borrow_mut();
check_desync!(conn); check_desync!(conn);
assert!( assert!(
@ -265,7 +272,7 @@ impl<'conn> Transaction<'conn> {
Ok(Transaction { Ok(Transaction {
conn: self.conn, conn: self.conn,
depth: self.depth + 1, depth: self.depth + 1,
savepoint_name: Some(name.to_owned()), savepoint_name: Some(name),
commit: Cell::new(false), commit: Cell::new(false),
finished: false, finished: false,
}) })

View File

@ -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::<Vec<i32>>()
);
}
#[test] #[test]
#[should_panic(expected = "active transaction")] #[should_panic(expected = "active transaction")]
fn test_conn_trans_when_nested() { fn test_conn_trans_when_nested() {