diff options
-rw-r--r-- | Bugzilla/Constants.pm | 6 | ||||
-rw-r--r-- | Bugzilla/DB.pm | 4 | ||||
-rw-r--r-- | Bugzilla/Error.pm | 3 | ||||
-rw-r--r-- | Bugzilla/Series.pm | 4 | ||||
-rw-r--r-- | Bugzilla/Token.pm | 22 | ||||
-rw-r--r-- | Bugzilla/User.pm | 9 | ||||
-rwxr-xr-x | attachment.cgi | 21 | ||||
-rwxr-xr-x | buglist.cgi | 4 | ||||
-rwxr-xr-x | checksetup.pl | 8 | ||||
-rwxr-xr-x | editclassifications.cgi | 12 | ||||
-rwxr-xr-x | editcomponents.cgi | 32 | ||||
-rwxr-xr-x | editflagtypes.cgi | 48 | ||||
-rwxr-xr-x | editgroups.cgi | 16 | ||||
-rwxr-xr-x | editmilestones.cgi | 26 | ||||
-rwxr-xr-x | editproducts.cgi | 65 | ||||
-rwxr-xr-x | editversions.cgi | 25 | ||||
-rwxr-xr-x | process_bug.cgi | 27 | ||||
-rwxr-xr-x | query.cgi | 6 | ||||
-rwxr-xr-x | sanitycheck.cgi | 14 | ||||
-rwxr-xr-x | token.cgi | 21 | ||||
-rwxr-xr-x | userprefs.cgi | 7 | ||||
-rwxr-xr-x | votes.cgi | 31 | ||||
-rwxr-xr-x | whine.pl | 13 |
23 files changed, 232 insertions, 192 deletions
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 3ef3cc634..a3e16251c 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -66,6 +66,8 @@ use base qw(Exporter); DEFAULT_QUERY_NAME COMMENT_COLS + + UNLOCK_ABORT ); @Bugzilla::Constants::EXPORT_OK = qw(contenttypes); @@ -217,4 +219,8 @@ use constant DEFAULT_QUERY_NAME => '(Default query)'; # The column length for displayed (and wrapped) bug comments. use constant COMMENT_COLS => 80; +# used by Bugzilla::DB to indicate that tables are being unlocked +# because of error +use constant UNLOCK_ABORT => 1; + 1; diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 3e3f45c66..d1ecfcb2e 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -501,8 +501,8 @@ formatted SQL command have prefix C<sql_>. All other methods have prefix C<bz_>. set even without locking tables first without raising an error to simplify error handling. Abstract method, should be overriden by database specific code. - Params: $abort = true (1) if the operation on locked tables failed - (if transactions are supported, the action will be rolled + Params: $abort = UNLOCK_ABORT (true, 1) if the operation on locked tables + failed (if transactions are supported, the action will be rolled back). False (0) or no param if the operation succeeded. Returns: none diff --git a/Bugzilla/Error.pm b/Bugzilla/Error.pm index 96017f368..e86b1c41a 100644 --- a/Bugzilla/Error.pm +++ b/Bugzilla/Error.pm @@ -27,6 +27,7 @@ use base qw(Exporter); @Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError); use Bugzilla::Config; +use Bugzilla::Constants; use Bugzilla::Util; use Date::Format; @@ -37,7 +38,7 @@ sub _throw_error { $vars->{error} = $error; - Bugzilla->dbh->do("UNLOCK TABLES") if $unlock_tables; + Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT) if $unlock_tables; # If a writable data/errorlog exists, log error details there. if (-w "data/errorlog") { diff --git a/Bugzilla/Series.pm b/Bugzilla/Series.pm index a4bd6654f..53e6fbabf 100644 --- a/Bugzilla/Series.pm +++ b/Bugzilla/Series.pm @@ -170,7 +170,7 @@ sub writeToDatabase { my $self = shift; my $dbh = Bugzilla->dbh; - $dbh->do("LOCK TABLES series_categories WRITE, series WRITE"); + $dbh->bz_lock_tables('series_categories WRITE', 'series WRITE'); my $category_id = getCategoryID($self->{'category'}); my $subcategory_id = getCategoryID($self->{'subcategory'}); @@ -210,7 +210,7 @@ sub writeToDatabase { || &::ThrowCodeError("missing_series_id", { 'series' => $self }); } - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); } # Check whether a series with this name, category and subcategory exists in diff --git a/Bugzilla/Token.pm b/Bugzilla/Token.pm index 90efe99bd..9caf91ab2 100644 --- a/Bugzilla/Token.pm +++ b/Bugzilla/Token.pm @@ -52,13 +52,14 @@ my $maxtokenage = 3; sub IssueEmailChangeToken { my ($userid, $old_email, $new_email) = @_; + my $dbh = Bugzilla->dbh; my $token_ts = time(); my $issuedate = time2str("%Y-%m-%d %H:%M", $token_ts); # Generate a unique token and insert it into the tokens table. # We have to lock the tokens table before generating the token, # since the database must be queried for token uniqueness. - &::SendSQL("LOCK TABLES tokens WRITE"); + $dbh->bz_lock_tables('tokens WRITE'); my $token = GenerateUniqueToken(); my $quotedtoken = &::SqlQuote($token); my $quoted_emails = &::SqlQuote($old_email . ":" . $new_email); @@ -72,7 +73,7 @@ sub IssueEmailChangeToken { tokentype , eventdata ) VALUES ( $userid , '$issuedate' , $quotedtoken , 'emailnew' , $quoted_emails )"); - &::SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # Mail the user the token along with instructions for using it. @@ -110,6 +111,8 @@ sub IssuePasswordToken { my ($loginname) = @_; + my $dbh = Bugzilla->dbh; + # Retrieve the user's ID from the database. my $quotedloginname = &::SqlQuote($loginname); &::SendSQL("SELECT profiles.userid, tokens.issuedate FROM profiles @@ -129,13 +132,13 @@ sub IssuePasswordToken { # Generate a unique token and insert it into the tokens table. # We have to lock the tokens table before generating the token, # since the database must be queried for token uniqueness. - &::SendSQL("LOCK TABLES tokens WRITE"); + $dbh->bz_lock_tables('tokens WRITE'); my $token = GenerateUniqueToken(); my $quotedtoken = &::SqlQuote($token); my $quotedipaddr = &::SqlQuote($::ENV{'REMOTE_ADDR'}); &::SendSQL("INSERT INTO tokens ( userid , issuedate , token , tokentype , eventdata ) VALUES ( $userid , NOW() , $quotedtoken , 'password' , $quotedipaddr )"); - &::SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # Mail the user the token along with instructions for using it. @@ -158,10 +161,11 @@ sub IssuePasswordToken { sub CleanTokenTable { - &::SendSQL("LOCK TABLES tokens WRITE"); + my $dbh = Bugzilla->dbh; + $dbh->bz_lock_tables('tokens WRITE'); &::SendSQL("DELETE FROM tokens WHERE TO_DAYS(NOW()) - TO_DAYS(issuedate) >= " . $maxtokenage); - &::SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); } @@ -198,6 +202,8 @@ sub Cancel { my ($token, $cancelaction) = @_; + my $dbh = Bugzilla->dbh; + # Quote the token for inclusion in SQL statements. my $quotedtoken = &::SqlQuote($token); @@ -232,9 +238,9 @@ sub Cancel { Bugzilla::BugMail::MessageToMTA($message); # Delete the token from the database. - &::SendSQL("LOCK TABLES tokens WRITE"); + $dbh->bz_lock_tables('tokens WRITE'); &::SendSQL("DELETE FROM tokens WHERE token = $quotedtoken"); - &::SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); } sub DeletePasswordTokens { diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm index 8f5f6a762..67b79f168 100644 --- a/Bugzilla/User.pm +++ b/Bugzilla/User.pm @@ -384,10 +384,9 @@ sub derive_groups { my $sth; - $dbh->do(q{LOCK TABLES profiles WRITE, - user_group_map WRITE, - group_group_map READ, - groups READ}) unless $already_locked; + $dbh->bz_lock_tables('profiles WRITE', 'user_group_map WRITE', + 'group_group_map READ', + 'groups READ') unless $already_locked; # avoid races, we are only up to date as of the BEGINNING of this process my $time = $dbh->selectrow_array("SELECT NOW()"); @@ -459,7 +458,7 @@ sub derive_groups { undef, $time, $id); - $dbh->do("UNLOCK TABLES") unless $already_locked; + $dbh->bz_unlock_tables() unless $already_locked; } sub can_bless { diff --git a/attachment.cgi b/attachment.cgi index d58395efc..5e10d8fee 100755 --- a/attachment.cgi +++ b/attachment.cgi @@ -1051,15 +1051,16 @@ sub edit sub update { # Updates an attachment record. + my $dbh = Bugzilla->dbh; # Get the bug ID for the bug to which this attachment is attached. SendSQL("SELECT bug_id FROM attachments WHERE attach_id = $::FORM{'id'}"); my $bugid = FetchSQLData(); - + # Lock database tables in preparation for updating the attachment. - SendSQL("LOCK TABLES attachments WRITE , flags WRITE , " . - "flagtypes READ , fielddefs READ , bugs_activity WRITE, " . - "flaginclusions AS i READ, flagexclusions AS e READ, " . + $dbh->bz_lock_tables('attachments WRITE', 'flags WRITE' , + 'flagtypes READ', 'fielddefs READ', 'bugs_activity WRITE', + 'flaginclusions AS i READ', 'flagexclusions AS e READ', # cc, bug_group_map, user_group_map, and groups are in here so we # can check the permissions of flag requestees and email addresses # on the flag type cc: lists via the CanSeeBug @@ -1067,10 +1068,10 @@ sub update # Bugzilla::User needs to rederive groups. profiles and # user_group_map would be READ locks instead of WRITE locks if it # weren't for derive_groups, which needs to write to those tables. - "bugs READ, profiles WRITE, " . - "cc READ, bug_group_map READ, user_group_map WRITE, " . - "group_group_map READ, groups READ"); - + 'bugs READ', 'profiles WRITE', + 'cc READ', 'bug_group_map READ', 'user_group_map WRITE', + 'group_group_map READ', 'groups READ'); + # Get a copy of the attachment record before we make changes # so we can record those changes in the activity table. SendSQL("SELECT description, mimetype, filename, ispatch, isobsolete, isprivate @@ -1138,9 +1139,9 @@ sub update # Update flags. my $target = Bugzilla::Flag::GetTarget(undef, $::FORM{'id'}); Bugzilla::Flag::process($target, $timestamp, \%::FORM); - + # Unlock all database tables now that we are finished updating the database. - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # If the user submitted a comment while editing the attachment, # add the comment to the bug. diff --git a/buglist.cgi b/buglist.cgi index f6869b349..891926d4e 100755 --- a/buglist.cgi +++ b/buglist.cgi @@ -250,7 +250,7 @@ sub InsertNamedQuery ($$$;$) { # it when we display it to the user. trick_taint($query); - $dbh->do("LOCK TABLES namedqueries WRITE"); + $dbh->bz_lock_tables('namedqueries WRITE'); my $result = $dbh->selectrow_array("SELECT userid FROM namedqueries" . " WHERE userid = ? AND name = ?" @@ -269,7 +269,7 @@ sub InsertNamedQuery ($$$;$) { , undef, ($userid, $query_name, $query, $link_in_footer)); } - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); return $query_existed_before; } diff --git a/checksetup.pl b/checksetup.pl index c99beb3a5..79095ee3a 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -2722,7 +2722,7 @@ if (GetFieldDef('bugs', 'long_desc')) { print "bugs to process; a line of dots will be printed for each 50.\n\n"; $| = 1; - $dbh->do("LOCK TABLES bugs write, longdescs write, profiles write"); + $dbh->bz_lock_tables('bugs write', 'longdescs write', 'profiles write'); $dbh->do('DELETE FROM longdescs'); @@ -2823,7 +2823,7 @@ if (GetFieldDef('bugs', 'long_desc')) { DropField('bugs', 'long_desc'); - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); } @@ -2836,7 +2836,7 @@ if (GetFieldDef('bugs_activity', 'field')) { 'mediumint not null, ADD INDEX (fieldid)'); print "Populating new fieldid field ...\n"; - $dbh->do("LOCK TABLES bugs_activity WRITE, fielddefs WRITE"); + $dbh->bz_lock_tables('bugs_activity WRITE', 'fielddefs WRITE'); my $sth = $dbh->prepare('SELECT DISTINCT field FROM bugs_activity'); $sth->execute(); @@ -2856,7 +2856,7 @@ if (GetFieldDef('bugs_activity', 'field')) { } $dbh->do("UPDATE bugs_activity SET fieldid = $id WHERE field = $q"); } - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); DropField('bugs_activity', 'field'); } diff --git a/editclassifications.cgi b/editclassifications.cgi index 777e76f75..fd02befef 100755 --- a/editclassifications.cgi +++ b/editclassifications.cgi @@ -205,7 +205,7 @@ if ($action eq 'delete') { } # lock the tables before we start to change everything: - $dbh->do("LOCK TABLES classifications WRITE, products WRITE"); + $dbh->bz_lock_tables('classifications WRITE', 'products WRITE'); # delete $sth = $dbh->prepare("DELETE FROM classifications WHERE id=?"); @@ -217,7 +217,7 @@ if ($action eq 'delete') { WHERE classification_id=?"); $sth->execute($classification_id); - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); unlink "data/versioncache"; @@ -283,7 +283,7 @@ if ($action eq 'update') { # above so it will remain static even after we rename the # classification in the database. - $dbh->do("LOCK TABLES classifications WRITE"); + $dbh->bz_lock_tables('classifications WRITE'); if ($description ne $descriptionold) { $sth = $dbh->prepare("UPDATE classifications @@ -295,12 +295,12 @@ if ($action eq 'update') { if ($classification ne $classificationold) { unless ($classification) { - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError("classification_not_specified") } if (TestClassification($classification)) { - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError("classification_already_exists", { name => $classification }); } $sth = $dbh->prepare("UPDATE classifications @@ -308,7 +308,7 @@ if ($action eq 'update') { $sth->execute($classification,$classification_id); $vars->{'updated_classification'} = 1; } - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); unlink "data/versioncache"; LoadTemplate($action); diff --git a/editcomponents.cgi b/editcomponents.cgi index f1d20fbd5..08cfab14c 100755 --- a/editcomponents.cgi +++ b/editcomponents.cgi @@ -39,6 +39,7 @@ use Bugzilla::Util; use vars qw($template $vars); my $cgi = Bugzilla->cgi; +my $dbh = Bugzilla->dbh; my $showbugcounts = (defined $cgi->param('showbugcounts')); @@ -445,13 +446,13 @@ if ($action eq 'delete') { # lock the tables before we start to change everything: - SendSQL("LOCK TABLES attachments WRITE, - bugs WRITE, - bugs_activity WRITE, - components WRITE, - dependencies WRITE, - flaginclusions WRITE, - flagexclusions WRITE"); + $dbh->bz_lock_tables('attachments WRITE', + 'bugs WRITE', + 'bugs_activity WRITE', + 'components WRITE', + 'dependencies WRITE', + 'flaginclusions WRITE', + 'flagexclusions WRITE'); # According to MySQL doc I cannot do a DELETE x.* FROM x JOIN Y, # so I have to iterate over bugs and delete all the indivial entries @@ -491,7 +492,7 @@ if ($action eq 'delete') { SendSQL("DELETE FROM components WHERE id=$component_id"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); unlink "$datadir/versioncache"; @@ -575,14 +576,15 @@ if ($action eq 'update') { # Note that the order of this tests is important. If you change # them, be sure to test for WHERE='$component' or WHERE='$componentold' - SendSQL("LOCK TABLES components WRITE, products READ, profiles READ"); + $dbh->bz_lock_tables('components WRITE', 'products READ', + 'profiles READ'); CheckComponent($product, $componentold); my $component_id = get_component_id(get_product_id($product), $componentold); if ($description ne $descriptionold) { unless ($description) { - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('component_blank_description', {'name' => $componentold}); exit; @@ -600,7 +602,7 @@ if ($action eq 'update') { my $initialownerid = DBname_to_id($initialowner); unless ($initialownerid) { - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('component_need_valid_initialowner', {'name' => $componentold}); exit; @@ -618,7 +620,7 @@ if ($action eq 'update') { if (Param('useqacontact') && $initialqacontact ne $initialqacontactold) { my $initialqacontactid = DBname_to_id($initialqacontact); if (!$initialqacontactid && $initialqacontact ne '') { - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('component_need_valid_initialqacontact', {'name' => $componentold}); exit; @@ -635,13 +637,13 @@ if ($action eq 'update') { if ($component ne $componentold) { unless ($component) { - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('component_must_have_a_name', {'name' => $componentold}); exit; } if (TestComponent($product, $component)) { - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('component_already_exists', {'name' => $component}); exit; @@ -655,7 +657,7 @@ if ($action eq 'update') { } - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); $vars->{'name'} = $component; $vars->{'product'} = $product; diff --git a/editflagtypes.cgi b/editflagtypes.cgi index 48074863a..c28fda4ba 100755 --- a/editflagtypes.cgi +++ b/editflagtypes.cgi @@ -220,15 +220,18 @@ sub insert { validateIsRequesteeble(); validateAllowMultiple(); validateGroups(); - + + my $dbh = Bugzilla->dbh; + my $name = SqlQuote($::FORM{'name'}); my $description = SqlQuote($::FORM{'description'}); my $cc_list = SqlQuote($::FORM{'cc_list'}); my $target_type = $::FORM{'target_type'} eq "bug" ? "b" : "a"; - - SendSQL("LOCK TABLES flagtypes WRITE, products READ, components READ, " . - "flaginclusions WRITE, flagexclusions WRITE"); - + + $dbh->bz_lock_tables('flagtypes WRITE', 'products READ', + 'components READ', 'flaginclusions WRITE', + 'flagexclusions WRITE'); + # Determine the new flag type's unique identifier. SendSQL("SELECT MAX(id) FROM flagtypes"); my $id = FetchSQLData() + 1; @@ -255,8 +258,8 @@ sub insert { "component_id) VALUES ($id, $product_id, $component_id)"); } } - - SendSQL("UNLOCK TABLES"); + + $dbh->bz_unlock_tables(); $vars->{'name'} = $::FORM{'name'}; $vars->{'message'} = "flag_type_created"; @@ -282,13 +285,16 @@ sub update { validateIsRequesteeble(); validateAllowMultiple(); validateGroups(); - + + my $dbh = Bugzilla->dbh; + my $name = SqlQuote($::FORM{'name'}); my $description = SqlQuote($::FORM{'description'}); my $cc_list = SqlQuote($::FORM{'cc_list'}); - - SendSQL("LOCK TABLES flagtypes WRITE, products READ, components READ, " . - "flaginclusions WRITE, flagexclusions WRITE"); + + $dbh->bz_lock_tables('flagtypes WRITE', 'products READ', + 'components READ', 'flaginclusions WRITE', + 'flagexclusions WRITE'); SendSQL("UPDATE flagtypes SET name = $name , description = $description , @@ -316,7 +322,7 @@ sub update { } } - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # Clear existing flags for bugs/attachments in categories no longer on # the list of inclusions or that have been added to the list of exclusions. @@ -384,9 +390,11 @@ sub confirmDelete sub deleteType { validateID(); - - SendSQL("LOCK TABLES flagtypes WRITE, flags WRITE, " . - "flaginclusions WRITE, flagexclusions WRITE"); + + my $dbh = Bugzilla->dbh; + + $dbh->bz_lock_tables('flagtypes WRITE', 'flags WRITE', + 'flaginclusions WRITE', 'flagexclusions WRITE'); # Get the name of the flag type so we can tell users # what was deleted. @@ -397,7 +405,7 @@ sub deleteType { SendSQL("DELETE FROM flaginclusions WHERE type_id = $::FORM{'id'}"); SendSQL("DELETE FROM flagexclusions WHERE type_id = $::FORM{'id'}"); SendSQL("DELETE FROM flagtypes WHERE id = $::FORM{'id'}"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); $vars->{'message'} = "flag_type_deleted"; @@ -413,10 +421,12 @@ sub deleteType { sub deactivate { validateID(); validateIsActive(); - - SendSQL("LOCK TABLES flagtypes WRITE"); + + my $dbh = Bugzilla->dbh; + + $dbh->bz_lock_tables('flagtypes WRITE'); SendSQL("UPDATE flagtypes SET is_active = 0 WHERE id = $::FORM{'id'}"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); $vars->{'message'} = "flag_type_deactivated"; $vars->{'flag_type'} = Bugzilla::FlagType::get($::FORM{'id'}); diff --git a/editgroups.cgi b/editgroups.cgi index 818997114..c3be719c7 100755 --- a/editgroups.cgi +++ b/editgroups.cgi @@ -483,10 +483,8 @@ if (($action eq 'remove_all_regexp') || ($action eq 'remove_all')) { WHERE id = ?"); $sth->execute($gid); my ($name, $regexp) = $sth->fetchrow_array(); - $dbh->do("LOCK TABLES - groups WRITE, - profiles READ, - user_group_map WRITE"); + $dbh->bz_lock_tables('groups WRITE', 'profiles READ', + 'user_group_map WRITE'); $sth = $dbh->prepare("SELECT user_group_map.user_id, profiles.login_name FROM user_group_map, profiles WHERE user_group_map.user_id = profiles.userid @@ -516,7 +514,7 @@ if (($action eq 'remove_all_regexp') || ($action eq 'remove_all')) { SET last_changed = NOW() WHERE id = ?"); $sth->execute($gid); - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); $vars->{'users'} = \@users; $vars->{'name'} = $name; @@ -545,9 +543,9 @@ sub doGroupChanges { my $dbh = Bugzilla->dbh; my $sth; - $dbh->do("LOCK TABLES groups WRITE, group_group_map WRITE, - user_group_map WRITE, profiles READ, - namedqueries READ, whine_queries READ"); + $dbh->bz_lock_tables('groups WRITE', 'group_group_map WRITE', + 'user_group_map WRITE', 'profiles READ', + 'namedqueries READ', 'whine_queries READ'); # Check that the given group ID and regular expression are valid. # If tests are successful, trimmed values are returned by CheckGroup*. @@ -651,6 +649,6 @@ sub doGroupChanges { # mark the changes SendSQL("UPDATE groups SET last_changed = NOW() WHERE id = $gid"); } - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); return $gid, $chgs, $name, $regexp; } diff --git a/editmilestones.cgi b/editmilestones.cgi index 4da121848..7364d4d06 100755 --- a/editmilestones.cgi +++ b/editmilestones.cgi @@ -360,11 +360,11 @@ if ($action eq 'delete') { # lock the tables before we start to change everything: - $dbh->do('LOCK TABLES attachments WRITE, - bugs WRITE, - bugs_activity WRITE, - milestones WRITE, - dependencies WRITE'); + $dbh->bz_lock_tables('attachments WRITE', + 'bugs WRITE', + 'bugs_activity WRITE', + 'milestones WRITE', + 'dependencies WRITE'); # According to MySQL doc I cannot do a DELETE x.* FROM x JOIN Y, # so I have to iterate over bugs and delete all the indivial entries @@ -425,7 +425,7 @@ if ($action eq 'delete') { $product_id, $milestone); - $dbh->do('UNLOCK TABLES'); + $dbh->bz_unlock_tables(); unlink "$datadir/versioncache"; @@ -497,9 +497,9 @@ if ($action eq 'update') { my $dbh = Bugzilla->dbh; - $dbh->do("LOCK TABLES bugs WRITE, - milestones WRITE, - products WRITE"); + $dbh->bz_lock_tables('bugs WRITE', + 'milestones WRITE', + 'products WRITE'); # Need to store because detaint_natural() will delete this if # invalid @@ -507,7 +507,7 @@ if ($action eq 'update') { if ($sortkey != $sortkeyold) { if (!detaint_natural($sortkey)) { - $dbh->do('UNLOCK TABLES'); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('milestone_sortkey_invalid', {'name' => $milestone, 'sortkey' => $stored_sortkey}); @@ -532,12 +532,12 @@ if ($action eq 'update') { if ($milestone ne $milestoneold) { unless ($milestone) { - $dbh->do('UNLOCK TABLES'); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('milestone_blank_name'); exit; } if (TestMilestone($product, $milestone)) { - $dbh->do('UNLOCK TABLES'); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('milestone_already_exists', {'name' => $milestone, 'product' => $product}); @@ -579,7 +579,7 @@ if ($action eq 'update') { $vars->{'updated_name'} = 1; } - $dbh->do('UNLOCK TABLES'); + $dbh->bz_unlock_tables(); $vars->{'name'} = $milestone; $vars->{'product'} = $product; diff --git a/editproducts.cgi b/editproducts.cgi index 0fa2ddbae..f066f7029 100755 --- a/editproducts.cgi +++ b/editproducts.cgi @@ -231,7 +231,6 @@ sub EmitFormElements ($$$$$$$$$) sub PutTrailer (@) { my (@links) = ("Back to the <A HREF=\"query.cgi\">query page</A>", @_); - SendSQL("UNLOCK TABLES"); my $count = $#links; my $num = 0; @@ -281,6 +280,7 @@ my $headerdone = 0; my $localtrailer = "<A HREF=\"editproducts.cgi\">edit</A> more products"; my $classhtmlvarstart = ""; my $classhtmlvar = ""; +my $dbh = Bugzilla->dbh; if (Param('useclassification') && (defined $classification)) { $classhtmlvar = "&classification=" . url_quote($classification); @@ -336,7 +336,6 @@ unless ($action) { CheckClassificationNew($classification); } - my $dbh = Bugzilla->dbh; my @execute_params = (); my @products = (); @@ -786,19 +785,19 @@ if ($action eq 'delete') { # lock the tables before we start to change everything: - SendSQL("LOCK TABLES attachments WRITE, - bugs WRITE, - bugs_activity WRITE, - components WRITE, - dependencies WRITE, - versions WRITE, - products WRITE, - groups WRITE, - group_control_map WRITE, - profiles WRITE, - milestones WRITE, - flaginclusions WRITE, - flagexclusions WRITE"); + $dbh->bz_lock_tables('attachments WRITE', + 'bugs WRITE', + 'bugs_activity WRITE', + 'components WRITE', + 'dependencies WRITE', + 'versions WRITE', + 'products WRITE', + 'groups WRITE', + 'group_control_map WRITE', + 'profiles WRITE', + 'milestones WRITE', + 'flaginclusions WRITE', + 'flagexclusions WRITE'); # According to MySQL doc I cannot do a DELETE x.* FROM x JOIN Y, # so I have to iterate over bugs and delete all the indivial entries @@ -854,6 +853,8 @@ if ($action eq 'delete') { WHERE id=$product_id"); print "Product '$product' deleted.<BR>\n"; + $dbh->bz_unlock_tables(); + unlink "$datadir/versioncache"; PutTrailer($localtrailer); exit; @@ -1107,12 +1108,12 @@ if ($action eq 'updategroupcontrols') { header_done => 1}); } } - SendSQL("LOCK TABLES groups READ, - group_control_map WRITE, - bugs WRITE, - bugs_activity WRITE, - bug_group_map WRITE, - fielddefs READ"); + $dbh->bz_lock_tables('groups READ', + 'group_control_map WRITE', + 'bugs WRITE', + 'bugs_activity WRITE', + 'bug_group_map WRITE', + 'fielddefs READ'); SendSQL("SELECT id, name, entry, membercontrol, othercontrol, canedit " . "FROM groups " . "LEFT JOIN group_control_map " . @@ -1234,6 +1235,8 @@ if ($action eq 'updategroupcontrols') { } print "added $count bugs<p>\n"; } + $dbh->bz_unlock_tables(); + print "Group control updates done<P>\n"; PutTrailer($localtrailer); @@ -1289,12 +1292,12 @@ if ($action eq 'update') { # Note that we got the $product_id using $productold above so it will # remain static even after we rename the product in the database. - SendSQL("LOCK TABLES products WRITE, - versions READ, - groups WRITE, - group_control_map WRITE, - profiles WRITE, - milestones READ"); + $dbh->bz_lock_tables('products WRITE', + 'versions READ', + 'groups WRITE', + 'group_control_map WRITE', + 'profiles WRITE', + 'milestones READ'); if ($disallownew ne $disallownewold) { $disallownew = $disallownew ? 1 : 0; @@ -1307,6 +1310,7 @@ if ($action eq 'update') { if ($description ne $descriptionold) { unless ($description) { print "Sorry, I can't delete the description."; + $dbh->bz_unlock_tables(UNLOCK_ABORT); PutTrailer($localtrailer); exit; } @@ -1357,6 +1361,7 @@ if ($action eq 'update') { " AND product_id = $product_id"); if (!FetchOneColumn()) { print "Sorry, the milestone $defaultmilestone must be defined first."; + $dbh->bz_unlock_tables(UNLOCK_ABORT); PutTrailer($localtrailer); exit; } @@ -1372,7 +1377,7 @@ if ($action eq 'update') { if ($product ne $productold) { unless ($product) { print "Sorry, I can't delete the product name."; - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); PutTrailer($localtrailer); exit; } @@ -1380,7 +1385,7 @@ if ($action eq 'update') { if (lc($product) ne lc($productold) && TestProduct($product)) { print "Sorry, product name '$product' is already in use."; - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); PutTrailer($localtrailer); exit; } @@ -1388,8 +1393,8 @@ if ($action eq 'update') { SendSQL("UPDATE products SET name=$qp WHERE id=$product_id"); print "Updated product name.<BR>\n"; } + $dbh->bz_unlock_tables(); unlink "$datadir/versioncache"; - SendSQL("UNLOCK TABLES"); if ($checkvotes) { # 1. too many votes for a single user on a single bug. diff --git a/editversions.cgi b/editversions.cgi index 222e7dd8e..ee4a83d77 100755 --- a/editversions.cgi +++ b/editversions.cgi @@ -39,6 +39,7 @@ use Bugzilla::Config qw(:DEFAULT $datadir); use vars qw($template $vars); my $cgi = Bugzilla->cgi; +my $dbh = Bugzilla->dbh; # TestProduct: just returns if the specified product does exists # CheckProduct: same check, optionally emit an error text @@ -303,11 +304,11 @@ if ($action eq 'delete') { # lock the tables before we start to change everything: - SendSQL("LOCK TABLES attachments WRITE, - bugs WRITE, - bugs_activity WRITE, - versions WRITE, - dependencies WRITE"); + $dbh->bz_lock_tables('attachments WRITE', + 'bugs WRITE', + 'bugs_activity WRITE', + 'versions WRITE', + 'dependencies WRITE'); # According to MySQL doc I cannot do a DELETE x.* FROM x JOIN Y, # so I have to iterate over bugs and delete all the indivial entries @@ -347,7 +348,7 @@ if ($action eq 'delete') { WHERE product_id = $product_id AND value = " . SqlQuote($version)); - SendSQL("UNLOCK TABLES;"); + $dbh->bz_unlock_tables(); unlink "$datadir/versioncache"; @@ -399,18 +400,18 @@ if ($action eq 'update') { # Note that the order of this tests is important. If you change # them, be sure to test for WHERE='$version' or WHERE='$versionold' - SendSQL("LOCK TABLES bugs WRITE, - versions WRITE, - products READ"); + $dbh->bz_lock_tables('bugs WRITE', + 'versions WRITE', + 'products READ'); if ($version ne $versionold) { unless ($version) { - SendSQL('UNLOCK TABLES'); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('version_blank_name'); exit; } if (TestVersion($product,$version)) { - SendSQL('UNLOCK TABLES'); + $dbh->bz_unlock_tables(UNLOCK_ABORT); ThrowUserError('version_already_exists', {'name' => $version, 'product' => $product}); @@ -430,7 +431,7 @@ if ($action eq 'update') { $vars->{'updated_name'} = 1; } - SendSQL('UNLOCK TABLES'); + $dbh->bz_unlock_tables(); $vars->{'name'} = $version; $vars->{'product'} = $product; diff --git a/process_bug.cgi b/process_bug.cgi index 6daa6d64e..abbad43f9 100755 --- a/process_bug.cgi +++ b/process_bug.cgi @@ -60,6 +60,7 @@ my $user = Bugzilla->login(LOGIN_REQUIRED); my $whoid = $user->id; my $cgi = Bugzilla->cgi; +my $dbh = Bugzilla->dbh; my $requiremilestone = 0; @@ -1134,22 +1135,22 @@ foreach my $id (@idlist) { $bug_changed = 0; my $write = "WRITE"; # Might want to make a param to control # whether we do LOW_PRIORITY ... - SendSQL("LOCK TABLES bugs $write, bugs_activity $write, cc $write, " . - "cc AS selectVisible_cc $write, " . - "profiles $write, dependencies $write, votes $write, " . - "products READ, components READ, " . - "keywords $write, longdescs $write, fielddefs $write, " . - "bug_group_map $write, flags $write, duplicates $write," . + $dbh->bz_lock_tables("bugs $write", "bugs_activity $write", + "cc $write", "cc AS selectVisible_cc $write", + "profiles $write", "dependencies $write", "votes $write", + "products READ", "components READ", + "keywords $write", "longdescs $write", "fielddefs $write", + "bug_group_map $write", "flags $write", "duplicates $write", # user_group_map would be a READ lock except that Flag::process # may call Flag::notify, which creates a new user object, # which might call derive_groups, which wants a WRITE lock on that # table. group_group_map is in here at all because derive_groups # needs it. - "user_group_map $write, group_group_map READ, flagtypes READ, " . - "flaginclusions AS i READ, flagexclusions AS e READ, " . - "keyworddefs READ, groups READ, attachments READ, " . - "group_control_map AS oldcontrolmap READ, " . - "group_control_map AS newcontrolmap READ, " . + "user_group_map $write", "group_group_map READ", "flagtypes READ", + "flaginclusions AS i READ", "flagexclusions AS e READ", + "keyworddefs READ", "groups READ", "attachments READ", + "group_control_map AS oldcontrolmap READ", + "group_control_map AS newcontrolmap READ", "group_control_map READ"); # Fun hack. @::log_columns only contains the component_id, # not the name (since bug 43600 got fixed). So, we need to have @@ -1270,7 +1271,7 @@ foreach my $id (@idlist) { $vars->{'bug_id'} = $id; - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(UNLOCK_ABORT); # Warn the user about the mid-air collision and ask them what to do. $template->process("bug/process/midair.html.tmpl", $vars) @@ -1773,7 +1774,7 @@ foreach my $id (@idlist) { if ($bug_changed) { SendSQL("UPDATE bugs SET delta_ts = $sql_timestamp WHERE bug_id = $id"); } - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); $vars->{'mailrecipients'} = { 'cc' => \@ccRemoved, 'owner' => $origOwner, @@ -88,7 +88,7 @@ if ($userid) { # If the query name contains invalid characters, don't import. $name =~ /[<>&]/ && next; trick_taint($name); - $dbh->do("LOCK TABLES namedqueries WRITE"); + $dbh->bz_lock_tables('namedqueries WRITE'); my $query = $dbh->selectrow_array( "SELECT query FROM namedqueries " . "WHERE userid = ? AND name = ?", @@ -98,7 +98,7 @@ if ($userid) { "(userid, name, query) VALUES " . "(?, ?, ?)", undef, ($userid, $name, $value)); } - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); } $cgi->send_cookie(-name => $cookiename, -expires => "Fri, 01-Jan-2038 00:00:00 GMT"); @@ -358,7 +358,7 @@ $vars->{'bug_severity'} = \@::legal_severity; # Boolean charts my @fields; push(@fields, { name => "noop", description => "---" }); -push(@fields, Bugzilla->dbh->bz_get_field_defs()); +push(@fields, $dbh->bz_get_field_defs()); $vars->{'fields'} = \@fields; # Creating new charts - if the cmd-add value is there, we define the field diff --git a/sanitycheck.cgi b/sanitycheck.cgi index 7bd42d22d..81afe79c5 100755 --- a/sanitycheck.cgi +++ b/sanitycheck.cgi @@ -71,6 +71,7 @@ sub BugListLinks { Bugzilla->login(LOGIN_REQUIRED); my $cgi = Bugzilla->cgi; +my $dbh = Bugzilla->dbh; # Make sure the user is authorized to access sanitycheck.cgi. Access # is restricted to logged-in users who have "editbugs" privileges, @@ -95,7 +96,7 @@ PutHeader("Bugzilla Sanity Check"); if (defined $cgi->param('rebuildvotecache')) { Status("OK, now rebuilding vote cache."); - SendSQL("LOCK TABLES bugs WRITE, votes READ"); + $dbh->bz_lock_tables('bugs WRITE', 'votes READ'); SendSQL("UPDATE bugs SET votes = 0"); SendSQL("SELECT bug_id, SUM(vote_count) FROM votes GROUP BY bug_id"); my %votes; @@ -106,7 +107,7 @@ if (defined $cgi->param('rebuildvotecache')) { foreach my $id (keys %votes) { SendSQL("UPDATE bugs SET votes = $votes{$id} WHERE bug_id = $id"); } - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); Status("Vote cache has been rebuilt."); } @@ -148,7 +149,7 @@ if (defined $cgi->param('cleangroupsnow')) { Status("Cutoff is $cutoff"); SendSQL("SELECT COUNT(*) FROM user_group_map"); (my $before) = FetchSQLData(); - SendSQL("LOCK TABLES user_group_map WRITE, profiles WRITE"); + $dbh->bz_lock_tables('user_group_map WRITE', 'profiles WRITE'); SendSQL("SELECT userid FROM profiles " . "WHERE refreshed_when > 0 " . "AND refreshed_when < " . SqlQuote($cutoff) . @@ -162,7 +163,7 @@ if (defined $cgi->param('cleangroupsnow')) { SendSQL("UPDATE profiles SET refreshed_when = 0 WHERE userid = $id"); PopGlobalSQLState(); } - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); SendSQL("SELECT COUNT(*) FROM user_group_map"); (my $after) = FetchSQLData(); Status("Cleaned table for $count users " . @@ -537,7 +538,8 @@ Status("Checking cached keywords"); my %realk; if (defined $cgi->param('rebuildkeywordcache')) { - SendSQL("LOCK TABLES bugs write, keywords read, keyworddefs read"); + $dbh->bz_lock_tables('bugs write', 'keywords read', + 'keyworddefs read'); } SendSQL("SELECT keywords.bug_id, keyworddefs.name " . @@ -596,7 +598,7 @@ if (@badbugs) { } if (defined $cgi->param('rebuildkeywordcache')) { - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); } ########################################################################### @@ -192,6 +192,8 @@ sub cancelChangePassword { } sub changePassword { + my $dbh = Bugzilla->dbh; + # Quote the password and token for inclusion into SQL statements. my $cryptedpassword = bz_crypt($cgi->param('password')); my $quotedpassword = SqlQuote($cryptedpassword); @@ -202,12 +204,12 @@ sub changePassword { # Update the user's password in the profiles table and delete the token # from the tokens table. - SendSQL("LOCK TABLES profiles WRITE , tokens WRITE"); + $dbh->bz_lock_tables('profiles WRITE', 'tokens WRITE'); SendSQL("UPDATE profiles SET cryptpassword = $quotedpassword WHERE userid = $userid"); SendSQL("DELETE FROM tokens WHERE token = $::quotedtoken"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); Bugzilla->logout_user_by_id($userid); @@ -229,6 +231,7 @@ sub confirmChangeEmail { } sub changeEmail { + my $dbh = Bugzilla->dbh; # Get the user's ID from the tokens table. SendSQL("SELECT userid, eventdata FROM tokens @@ -251,14 +254,14 @@ sub changeEmail { # Update the user's login name in the profiles table and delete the token # from the tokens table. - SendSQL("LOCK TABLES profiles WRITE , tokens WRITE"); + $dbh->bz_lock_tables('profiles WRITE', 'tokens WRITE'); SendSQL("UPDATE profiles SET login_name = $quotednewemail WHERE userid = $userid"); SendSQL("DELETE FROM tokens WHERE token = $::quotedtoken"); SendSQL("DELETE FROM tokens WHERE userid = $userid AND tokentype = 'emailnew'"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # The email address has been changed, so we need to rederive the groups my $user = new Bugzilla::User($userid); @@ -276,6 +279,8 @@ sub changeEmail { } sub cancelChangeEmail { + my $dbh = Bugzilla->dbh; + # Get the user's ID from the tokens table. SendSQL("SELECT userid, tokentype, eventdata FROM tokens WHERE token = $::quotedtoken"); @@ -292,11 +297,11 @@ sub cancelChangeEmail { if($actualemail ne $old_email) { my $quotedoldemail = SqlQuote($old_email); - SendSQL("LOCK TABLES profiles WRITE"); + $dbh->bz_lock_tables('profiles WRITE'); SendSQL("UPDATE profiles SET login_name = $quotedoldemail WHERE userid = $userid"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # email has changed, so rederive groups # Note that this is done _after_ the tables are unlocked @@ -318,11 +323,11 @@ sub cancelChangeEmail { $vars->{'new_email'} = $new_email; Bugzilla::Token::Cancel($::token, $vars->{'message'}); - SendSQL("LOCK TABLES tokens WRITE"); + $dbh->bz_lock_tables('tokens WRITE'); SendSQL("DELETE FROM tokens WHERE userid = $userid AND tokentype = 'emailold' OR tokentype = 'emailnew'"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # Return HTTP response headers. print $cgi->header(); diff --git a/userprefs.cgi b/userprefs.cgi index f62f02500..193a4d73f 100755 --- a/userprefs.cgi +++ b/userprefs.cgi @@ -195,7 +195,8 @@ sub DoEmail { sub SaveEmail { my $updateString = ""; my $cgi = Bugzilla->cgi; - + my $dbh = Bugzilla->dbh; + if (defined $cgi->param('ExcludeSelf')) { $updateString .= 'ExcludeSelf~on'; } else { @@ -226,7 +227,7 @@ sub SaveEmail { # we don't really care if anyone reads the watch table. So # some small amount of contention could be gotten rid of by # using user-defined locks rather than table locking. - SendSQL("LOCK TABLES watch WRITE, profiles READ"); + $dbh->bz_lock_tables('watch WRITE', 'profiles READ'); # what the db looks like now my $origWatchedUsers = new Bugzilla::RelationSet; @@ -244,7 +245,7 @@ sub SaveEmail { ($CCDELTAS[0] eq "") || SendSQL($CCDELTAS[0]); ($CCDELTAS[1] eq "") || SendSQL($CCDELTAS[1]); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); } } @@ -118,8 +118,9 @@ sub show_bug { # doing the viewing, give them the option to edit them too. sub show_user { GetVersionTable(); - + my $cgi = Bugzilla->cgi; + my $dbh = Bugzilla->dbh; # If a bug_id is given, and we're editing, we'll add it to the votes list. $bug_id ||= ""; @@ -129,11 +130,11 @@ sub show_user { my $userid = Bugzilla->user->id; my $canedit = (Param('usevotes') && $userid == $who) ? 1 : 0; - - SendSQL("LOCK TABLES bugs READ, products READ, votes WRITE, - cc READ, bug_group_map READ, user_group_map READ, - cc AS selectVisible_cc READ, groups READ"); - + + $dbh->bz_lock_tables('bugs READ', 'products READ', 'votes WRITE', + 'cc READ', 'bug_group_map READ', 'user_group_map READ', + 'cc AS selectVisible_cc READ', 'groups READ'); + if ($canedit && $bug_id) { # Make sure there is an entry for this bug # in the vote table, just so that things display right. @@ -212,7 +213,7 @@ sub show_user { } SendSQL("DELETE FROM votes WHERE vote_count <= 0"); - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); $vars->{'canedit'} = $canedit; $vars->{'voting_user'} = { "login" => $name }; @@ -231,6 +232,7 @@ sub record_votes { ############################################################################ my $cgi = Bugzilla->cgi; + my $dbh = Bugzilla->dbh; # Build a list of bug IDs for which votes have been submitted. Votes # are submitted in form fields in which the field names are the bug @@ -314,12 +316,13 @@ sub record_votes { # for products that only allow one vote per bug). In that case, we still # need to clear the user's votes from the database. my %affected; - SendSQL("LOCK TABLES bugs WRITE, bugs_activity WRITE, votes WRITE, - longdescs WRITE, profiles READ, products READ, components READ, - cc READ, dependencies READ, groups READ, fielddefs READ, - namedqueries READ, whine_queries READ, watch READ, - profiles AS watchers READ, profiles AS watched READ, - user_group_map READ, bug_group_map READ"); + $dbh->bz_lock_tables('bugs WRITE', 'bugs_activity WRITE', + 'votes WRITE', 'longdescs WRITE', 'profiles READ', + 'products READ', 'components READ', 'cc READ', + 'dependencies READ', 'groups READ', 'fielddefs READ', + 'namedqueries READ', 'whine_queries READ', 'watch READ', + 'profiles AS watchers READ', 'profiles AS watched READ', + 'user_group_map READ', 'bug_group_map READ'); # Take note of, and delete the user's old votes from the database. SendSQL("SELECT bug_id FROM votes WHERE who = $who"); @@ -349,7 +352,7 @@ sub record_votes { $vars->{'header_done'} = 1 if $confirmed; } - SendSQL("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); $vars->{'votes_recorded'} = 1; } @@ -220,12 +220,11 @@ sub get_next_event { # Loop until there's something to return until (scalar keys %{$event}) { - $dbh->do("LOCK TABLE " . - "whine_schedules WRITE, " . - "whine_events READ, " . - "profiles READ, " . - "groups READ, " . - "user_group_map READ"); + $dbh->bz_lock_tables('whine_schedules WRITE', + 'whine_events READ', + 'profiles READ', + 'groups READ', + 'user_group_map READ'); # Get the event ID for the first pending schedule $sth_next_scheduled_event->execute; @@ -262,7 +261,7 @@ sub get_next_event { reset_timer($sid); } - $dbh->do("UNLOCK TABLES"); + $dbh->bz_unlock_tables(); # Only set $event if the user is allowed to do whining if ($owner->in_group('bz_canusewhines')) { |