DEFAULT_QUERY_NAME
COMMENT_COLS
+
+ UNLOCK_ABORT
);
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
# 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;
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
@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError);
use Bugzilla::Config;
+use Bugzilla::Constants;
use Bugzilla::Util;
use Date::Format;
$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") {
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'});
|| &::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
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);
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.
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
# 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.
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();
}
my ($token, $cancelaction) = @_;
+ my $dbh = Bugzilla->dbh;
+
# Quote the token for inclusion in SQL statements.
my $quotedtoken = &::SqlQuote($token);
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 {
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()");
undef,
$time,
$id);
- $dbh->do("UNLOCK TABLES") unless $already_locked;
+ $dbh->bz_unlock_tables() unless $already_locked;
}
sub can_bless {
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
# 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
# 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.
# 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 = ?"
, undef, ($userid, $query_name, $query, $link_in_footer));
}
- $dbh->do("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
return $query_existed_before;
}
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');
DropField('bugs', 'long_desc');
- $dbh->do("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
}
'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();
}
$dbh->do("UPDATE bugs_activity SET fieldid = $id WHERE field = $q");
}
- $dbh->do("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
DropField('bugs_activity', 'field');
}
}
# 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=?");
WHERE classification_id=?");
$sth->execute($classification_id);
- $dbh->do("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
unlink "data/versioncache";
# 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
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
$sth->execute($classification,$classification_id);
$vars->{'updated_classification'} = 1;
}
- $dbh->do("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
unlink "data/versioncache";
LoadTemplate($action);
use vars qw($template $vars);
my $cgi = Bugzilla->cgi;
+my $dbh = Bugzilla->dbh;
my $showbugcounts = (defined $cgi->param('showbugcounts'));
# 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
SendSQL("DELETE FROM components
WHERE id=$component_id");
- SendSQL("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
unlink "$datadir/versioncache";
# 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;
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;
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;
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;
}
- SendSQL("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
$vars->{'name'} = $component;
$vars->{'product'} = $product;
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;
"component_id) VALUES ($id, $product_id, $component_id)");
}
}
-
- SendSQL("UNLOCK TABLES");
+
+ $dbh->bz_unlock_tables();
$vars->{'name'} = $::FORM{'name'};
$vars->{'message'} = "flag_type_created";
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 ,
}
}
- 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.
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.
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";
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'});
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
SET last_changed = NOW()
WHERE id = ?");
$sth->execute($gid);
- $dbh->do("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
$vars->{'users'} = \@users;
$vars->{'name'} = $name;
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*.
# 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;
}
# 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
$product_id,
$milestone);
- $dbh->do('UNLOCK TABLES');
+ $dbh->bz_unlock_tables();
unlink "$datadir/versioncache";
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
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});
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});
$vars->{'updated_name'} = 1;
}
- $dbh->do('UNLOCK TABLES');
+ $dbh->bz_unlock_tables();
$vars->{'name'} = $milestone;
$vars->{'product'} = $product;
sub PutTrailer (@)
{
my (@links) = ("Back to the <A HREF=\"query.cgi\">query page</A>", @_);
- SendSQL("UNLOCK TABLES");
my $count = $#links;
my $num = 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);
CheckClassificationNew($classification);
}
- my $dbh = Bugzilla->dbh;
my @execute_params = ();
my @products = ();
# 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
WHERE id=$product_id");
print "Product '$product' deleted.<BR>\n";
+ $dbh->bz_unlock_tables();
+
unlink "$datadir/versioncache";
PutTrailer($localtrailer);
exit;
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 " .
}
print "added $count bugs<p>\n";
}
+ $dbh->bz_unlock_tables();
+
print "Group control updates done<P>\n";
PutTrailer($localtrailer);
# 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;
if ($description ne $descriptionold) {
unless ($description) {
print "Sorry, I can't delete the description.";
+ $dbh->bz_unlock_tables(UNLOCK_ABORT);
PutTrailer($localtrailer);
exit;
}
" 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;
}
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;
}
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;
}
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.
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
# 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
WHERE product_id = $product_id
AND value = " . SqlQuote($version));
- SendSQL("UNLOCK TABLES;");
+ $dbh->bz_unlock_tables();
unlink "$datadir/versioncache";
# 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});
$vars->{'updated_name'} = 1;
}
- SendSQL('UNLOCK TABLES');
+ $dbh->bz_unlock_tables();
$vars->{'name'} = $version;
$vars->{'product'} = $product;
my $whoid = $user->id;
my $cgi = Bugzilla->cgi;
+my $dbh = Bugzilla->dbh;
my $requiremilestone = 0;
$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
$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)
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,
# 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 = ?",
"(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");
# 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
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,
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;
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.");
}
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) .
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 " .
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 " .
}
if (defined $cgi->param('rebuildkeywordcache')) {
- SendSQL("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
}
###########################################################################
}
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);
# 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);
}
sub changeEmail {
+ my $dbh = Bugzilla->dbh;
# Get the user's ID from the tokens table.
SendSQL("SELECT userid, eventdata FROM tokens
# 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);
}
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");
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
$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();
sub SaveEmail {
my $updateString = "";
my $cgi = Bugzilla->cgi;
-
+ my $dbh = Bugzilla->dbh;
+
if (defined $cgi->param('ExcludeSelf')) {
$updateString .= 'ExcludeSelf~on';
} else {
# 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;
($CCDELTAS[0] eq "") || SendSQL($CCDELTAS[0]);
($CCDELTAS[1] eq "") || SendSQL($CCDELTAS[1]);
- SendSQL("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
}
}
# 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 ||= "";
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.
}
SendSQL("DELETE FROM votes WHERE vote_count <= 0");
- SendSQL("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
$vars->{'canedit'} = $canedit;
$vars->{'voting_user'} = { "login" => $name };
############################################################################
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
# 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");
$vars->{'header_done'} = 1 if $confirmed;
}
- SendSQL("UNLOCK TABLES");
+ $dbh->bz_unlock_tables();
$vars->{'votes_recorded'} = 1;
}
# 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;
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')) {