Skip to content

Commit 86b65aa

Browse files
authored
Merge pull request sfackler#374 from rustonaut/fix_371_savepoint_nameing_in_nested_transactions
Fix sfackler#371 savepoint nameing in nested transactions
2 parents b190738 + 96f97a6 commit 86b65aa

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

postgres/src/transaction.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ impl<'conn> Transaction<'conn> {
244244
///
245245
/// Panics if there is an active nested transaction.
246246
pub fn transaction<'a>(&'a self) -> Result<Transaction<'a>> {
247-
self.savepoint("sp")
247+
self.savepoint(format!("sp_{}", self.depth()))
248248
}
249249

250250
/// Like `Connection::transaction`, but creates a nested transaction via
@@ -253,7 +253,14 @@ impl<'conn> Transaction<'conn> {
253253
/// # Panics
254254
///
255255
/// Panics if there is an active nested transaction.
256-
pub fn savepoint<'a>(&'a self, name: &str) -> Result<Transaction<'a>> {
256+
#[inline]
257+
pub fn savepoint<'a, I>(&'a self, name: I) -> Result<Transaction<'a>>
258+
where I: Into<String>
259+
{
260+
self._savepoint(name.into())
261+
}
262+
263+
fn _savepoint<'a>(&'a self, name: String) -> Result<Transaction<'a>> {
257264
let mut conn = self.conn.0.borrow_mut();
258265
check_desync!(conn);
259266
assert!(
@@ -265,7 +272,7 @@ impl<'conn> Transaction<'conn> {
265272
Ok(Transaction {
266273
conn: self.conn,
267274
depth: self.depth + 1,
268-
savepoint_name: Some(name.to_owned()),
275+
savepoint_name: Some(name),
269276
commit: Cell::new(false),
270277
finished: false,
271278
})

postgres/tests/test.rs

+35
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,41 @@ fn test_nested_transactions_finish() {
331331
);
332332
}
333333

334+
#[test]
335+
fn test_nested_transactions_partial_rollback() {
336+
let conn = or_panic!(Connection::connect(
337+
"postgres://postgres@localhost:5433",
338+
TlsMode::None,
339+
));
340+
or_panic!(conn.execute("CREATE TEMPORARY TABLE foo (id INT PRIMARY KEY)", &[]));
341+
342+
or_panic!(conn.execute("INSERT INTO foo (id) VALUES ($1)", &[&1i32]));
343+
344+
{
345+
let trans = or_panic!(conn.transaction());
346+
or_panic!(trans.execute("INSERT INTO foo (id) VALUES ($1)", &[&2i32]));
347+
{
348+
let trans = or_panic!(trans.transaction());
349+
or_panic!(trans.execute("INSERT INTO foo (id) VALUES ($1)", &[&3i32]));
350+
{
351+
let trans = or_panic!(trans.transaction());
352+
or_panic!(trans.execute("INSERT INTO foo (id) VALUES ($1)", &[&4i32]));
353+
drop(trans);
354+
}
355+
drop(trans);
356+
}
357+
or_panic!(trans.commit());
358+
}
359+
360+
let stmt = or_panic!(conn.prepare("SELECT * FROM foo ORDER BY id"));
361+
let result = or_panic!(stmt.query(&[]));
362+
363+
assert_eq!(
364+
vec![1i32, 2],
365+
result.iter().map(|row| row.get(0)).collect::<Vec<i32>>()
366+
);
367+
}
368+
334369
#[test]
335370
#[should_panic(expected = "active transaction")]
336371
fn test_conn_trans_when_nested() {

0 commit comments

Comments
 (0)