remove depth from Savepoint

Savepoints with the same name nest properly without issue.  This doesn't
work with rusqlite unless savepoints are always released on drop.
This commit is contained in:
Taylor C. Richberger 2023-05-18 08:44:50 -06:00
parent 65e4be3a19
commit 88653ca62a

View File

@ -91,7 +91,6 @@ pub struct Transaction<'conn> {
pub struct Savepoint<'conn> { pub struct Savepoint<'conn> {
conn: &'conn Connection, conn: &'conn Connection,
name: String, name: String,
depth: u32,
drop_behavior: DropBehavior, drop_behavior: DropBehavior,
committed: bool, committed: bool,
} }
@ -158,13 +157,13 @@ impl Transaction<'_> {
/// ``` /// ```
#[inline] #[inline]
pub fn savepoint(&mut self) -> Result<Savepoint<'_>> { pub fn savepoint(&mut self) -> Result<Savepoint<'_>> {
Savepoint::with_depth(self.conn, 1) Savepoint::new_(self.conn)
} }
/// Create a new savepoint with a custom savepoint name. See `savepoint()`. /// Create a new savepoint with a custom savepoint name. See `savepoint()`.
#[inline] #[inline]
pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> { pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> {
Savepoint::with_depth_and_name(self.conn, 1, name) Savepoint::with_name_(self.conn, name)
} }
/// Get the current setting for what happens to the transaction when it is /// Get the current setting for what happens to the transaction when it is
@ -249,50 +248,44 @@ impl Drop for Transaction<'_> {
impl Savepoint<'_> { impl Savepoint<'_> {
#[inline] #[inline]
fn with_depth_and_name<T: Into<String>>( fn with_name_<T: Into<String>>(conn: &Connection, name: T) -> Result<Savepoint<'_>> {
conn: &Connection,
depth: u32,
name: T,
) -> Result<Savepoint<'_>> {
let name = name.into(); let name = name.into();
conn.execute_batch(&format!("SAVEPOINT {name}")) conn.execute_batch(&format!("SAVEPOINT {name}"))
.map(|_| Savepoint { .map(|_| Savepoint {
conn, conn,
name, name,
depth,
drop_behavior: DropBehavior::Rollback, drop_behavior: DropBehavior::Rollback,
committed: false, committed: false,
}) })
} }
#[inline] #[inline]
fn with_depth(conn: &Connection, depth: u32) -> Result<Savepoint<'_>> { fn new_(conn: &Connection) -> Result<Savepoint<'_>> {
let name = format!("_rusqlite_sp_{depth}"); Savepoint::with_name_(conn, "_rusqlite_sp")
Savepoint::with_depth_and_name(conn, depth, name)
} }
/// Begin a new savepoint. Can be nested. /// Begin a new savepoint. Can be nested.
#[inline] #[inline]
pub fn new(conn: &mut Connection) -> Result<Savepoint<'_>> { pub fn new(conn: &mut Connection) -> Result<Savepoint<'_>> {
Savepoint::with_depth(conn, 0) Savepoint::new_(conn)
} }
/// Begin a new savepoint with a user-provided savepoint name. /// Begin a new savepoint with a user-provided savepoint name.
#[inline] #[inline]
pub fn with_name<T: Into<String>>(conn: &mut Connection, name: T) -> Result<Savepoint<'_>> { pub fn with_name<T: Into<String>>(conn: &mut Connection, name: T) -> Result<Savepoint<'_>> {
Savepoint::with_depth_and_name(conn, 0, name) Savepoint::with_name_(conn, name)
} }
/// Begin a nested savepoint. /// Begin a nested savepoint.
#[inline] #[inline]
pub fn savepoint(&mut self) -> Result<Savepoint<'_>> { pub fn savepoint(&mut self) -> Result<Savepoint<'_>> {
Savepoint::with_depth(self.conn, self.depth + 1) Savepoint::new_(self.conn)
} }
/// Begin a nested savepoint with a user-provided savepoint name. /// Begin a nested savepoint with a user-provided savepoint name.
#[inline] #[inline]
pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> { pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> {
Savepoint::with_depth_and_name(self.conn, self.depth + 1, name) Savepoint::with_name_(self.conn, name)
} }
/// Get the current setting for what happens to the savepoint when it is /// Get the current setting for what happens to the savepoint when it is
@ -352,7 +345,7 @@ impl Savepoint<'_> {
} }
match self.drop_behavior() { match self.drop_behavior() {
DropBehavior::Commit => self.commit_().or_else(|_| self.rollback()), DropBehavior::Commit => self.commit_().or_else(|_| self.rollback()),
DropBehavior::Rollback => self.rollback(), DropBehavior::Rollback => self.rollback().and_then(|_| self.commit_()),
DropBehavior::Ignore => Ok(()), DropBehavior::Ignore => Ok(()),
DropBehavior::Panic => panic!("Savepoint dropped unexpectedly."), DropBehavior::Panic => panic!("Savepoint dropped unexpectedly."),
} }