From 496ad3d1ff432cd04ee3a1a6c90d38e61450d606 Mon Sep 17 00:00:00 2001 From: "mkanat%bugzilla.org" <> Date: Thu, 15 Mar 2007 09:29:45 +0000 Subject: Bug 374004: Enable transaction code and use it in some installation places Patch By Max Kanat-Alexander (module owner) a=mkanat --- Bugzilla/DB.pm | 64 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'Bugzilla/DB.pm') diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 22c6bbafa..095ba27a6 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -859,39 +859,51 @@ sub bz_table_list_real { # Transaction Methods ##################################################################### +sub bz_in_transaction { + return $_[0]->{private_bz_transaction_count} ? 1 : 0; +} + sub bz_start_transaction { my ($self) = @_; - if ($self->{private_bz_in_transaction}) { - ThrowCodeError("nested_transaction"); + if ($self->bz_in_transaction) { + $self->{private_bz_transaction_count}++; } else { # Turn AutoCommit off and start a new transaction $self->begin_work(); - $self->{private_bz_in_transaction} = 1; + # REPEATABLE READ means "We work on a snapshot of the DB that + # is created when we execute our first SQL statement." It's + # what we need in Bugzilla to be safe, for what we do. + # Different DBs have different defaults for their isolation + # level, so we just set it here manually. + $self->do('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ'); + $self->{private_bz_transaction_count} = 1; } } sub bz_commit_transaction { my ($self) = @_; - - if (!$self->{private_bz_in_transaction}) { - ThrowCodeError("not_in_transaction"); - } else { + + if ($self->{private_bz_transaction_count} > 1) { + $self->{private_bz_transaction_count}--; + } elsif ($self->bz_in_transaction) { $self->commit(); - - $self->{private_bz_in_transaction} = 0; + $self->{private_bz_transaction_count} = 0; + } else { + ThrowCodeError('not_in_transaction'); } } sub bz_rollback_transaction { my ($self) = @_; - if (!$self->{private_bz_in_transaction}) { + # Unlike start and commit, if we rollback at any point it happens + # instantly, even if we're in a nested transaction. + if (!$self->bz_in_transaction) { ThrowCodeError("not_in_transaction"); } else { $self->rollback(); - - $self->{private_bz_in_transaction} = 0; + $self->{private_bz_transaction_count} = 0; } } @@ -928,9 +940,6 @@ sub db_new { # above "die" condition. $self->{RaiseError} = 1; - # class variables - $self->{private_bz_in_transaction} = 0; - bless ($self, $class); return $self; @@ -2212,20 +2221,33 @@ in the database. =over +=item C + +Returns C<1> if we are currently in the middle of an uncommitted transaction, +C<0> otherwise. + =item C -Starts a transaction if supported by the database being used. Returns nothing -and takes no parameters. +Starts a transaction. + +It is OK to call C when you are already inside of +a transaction. However, you must call L as many +times as you called C, in order for your transaction +to actually commit. + +Bugzilla uses C transactions. + +Returns nothing and takes no parameters. =item C -Ends a transaction, commiting all changes, if supported by the database -being used. Returns nothing and takes no parameters. +Ends a transaction, commiting all changes. Returns nothing and takes +no parameters. =item C -Ends a transaction, rolling back all changes, if supported by the database -being used. Returns nothing and takes no parameters. +Ends a transaction, rolling back all changes. Returns nothing and takes +no parameters. =back -- cgit v1.2.3-24-g4f1b