diff options
Diffstat (limited to 'sanitycheck.cgi')
-rwxr-xr-x | sanitycheck.cgi | 1074 |
1 files changed, 593 insertions, 481 deletions
diff --git a/sanitycheck.cgi b/sanitycheck.cgi index 7ac6c2467..fda287c7a 100755 --- a/sanitycheck.cgi +++ b/sanitycheck.cgi @@ -26,26 +26,29 @@ use Bugzilla::Token; ########################################################################### sub get_string { - my ($san_tag, $vars) = @_; - $vars->{'san_tag'} = $san_tag; - return get_text('sanitycheck', $vars); + my ($san_tag, $vars) = @_; + $vars->{'san_tag'} = $san_tag; + return get_text('sanitycheck', $vars); } sub Status { - my ($san_tag, $vars, $alert) = @_; - my $cgi = Bugzilla->cgi; - return if (!$alert && Bugzilla->usage_mode == USAGE_MODE_CMDLINE && !$cgi->param('verbose')); - - if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { - my $output = $cgi->param('output') || ''; - my $linebreak = $alert ? "\nALERT: " : "\n"; - $cgi->param('error_found', 1) if $alert; - $cgi->param('output', $output . $linebreak . get_string($san_tag, $vars)); - } - else { - my $start_tag = $alert ? '<p class="alert">' : '<p>'; - print $start_tag . get_string($san_tag, $vars) . "</p>\n"; - } + my ($san_tag, $vars, $alert) = @_; + my $cgi = Bugzilla->cgi; + return + if (!$alert + && Bugzilla->usage_mode == USAGE_MODE_CMDLINE + && !$cgi->param('verbose')); + + if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { + my $output = $cgi->param('output') || ''; + my $linebreak = $alert ? "\nALERT: " : "\n"; + $cgi->param('error_found', 1) if $alert; + $cgi->param('output', $output . $linebreak . get_string($san_tag, $vars)); + } + else { + my $start_tag = $alert ? '<p class="alert">' : '<p>'; + print $start_tag . get_string($san_tag, $vars) . "</p>\n"; + } } ########################################################################### @@ -54,28 +57,29 @@ sub Status { my $user = Bugzilla->login(LOGIN_REQUIRED); -my $cgi = Bugzilla->cgi; -my $dbh = Bugzilla->dbh; +my $cgi = Bugzilla->cgi; +my $dbh = Bugzilla->dbh; my $hooks_only = $cgi->param('hooks_only'); + # If the result of the sanity check is sent per email, then we have to # take the user prefs into account rather than querying the web browser. my $template; if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { - $template = Bugzilla->template_inner($user->setting('lang')); + $template = Bugzilla->template_inner($user->setting('lang')); } else { - $template = Bugzilla->template; - - # Only check the token if we are running this script from the - # web browser and a parameter is passed to the script. - # XXX - Maybe these two parameters should be deleted once logged in? - $cgi->delete('GoAheadAndLogIn', 'Bugzilla_restrictlogin', 'hooks_only'); - if (scalar($cgi->param())) { - my $token = $cgi->param('token'); - check_hash_token($token, ['sanitycheck']); - } + $template = Bugzilla->template; + + # Only check the token if we are running this script from the + # web browser and a parameter is passed to the script. + # XXX - Maybe these two parameters should be deleted once logged in? + $cgi->delete('GoAheadAndLogIn', 'Bugzilla_restrictlogin', 'hooks_only'); + if (scalar($cgi->param())) { + my $token = $cgi->param('token'); + check_hash_token($token, ['sanitycheck']); + } } -my $vars = {}; +my $vars = {}; my $clear_memcached = 0; print $cgi->header() unless Bugzilla->usage_mode == USAGE_MODE_CMDLINE; @@ -84,13 +88,12 @@ print $cgi->header() unless Bugzilla->usage_mode == USAGE_MODE_CMDLINE; # As this script can now alter the group_control_map table, we no longer # let users with editbugs privs run it anymore. $user->in_group("editcomponents") - || ThrowUserError("auth_failure", {group => "editcomponents", - action => "run", - object => "sanity_check"}); + || ThrowUserError("auth_failure", + {group => "editcomponents", action => "run", object => "sanity_check"}); unless (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { - $template->process('admin/sanitycheck/list.html.tmpl', $vars) - || ThrowTemplateError($template->error()); + $template->process('admin/sanitycheck/list.html.tmpl', $vars) + || ThrowTemplateError($template->error()); } goto REPAIR_HOOKS if $hooks_only; @@ -100,25 +103,28 @@ goto REPAIR_HOOKS if $hooks_only; ########################################################################### if ($cgi->param('createmissinggroupcontrolmapentries')) { - Status('group_control_map_entries_creation'); + Status('group_control_map_entries_creation'); - my $na = CONTROLMAPNA; - my $shown = CONTROLMAPSHOWN; - my $insertsth = $dbh->prepare( - qq{INSERT INTO group_control_map + my $na = CONTROLMAPNA; + my $shown = CONTROLMAPSHOWN; + my $insertsth = $dbh->prepare( + qq{INSERT INTO group_control_map (group_id, product_id, membercontrol, othercontrol) - VALUES (?, ?, $shown, $na)}); + VALUES (?, ?, $shown, $na)} + ); - my $updatesth = $dbh->prepare(qq{UPDATE group_control_map + my $updatesth = $dbh->prepare( + qq{UPDATE group_control_map SET membercontrol = $shown WHERE group_id = ? - AND product_id = ?}); - my $counter = 0; - - # Find all group/product combinations used for bugs but not set up - # correctly in group_control_map - my $invalid_combinations = $dbh->selectall_arrayref( - qq{ SELECT bugs.product_id, + AND product_id = ?} + ); + my $counter = 0; + + # Find all group/product combinations used for bugs but not set up + # correctly in group_control_map + my $invalid_combinations = $dbh->selectall_arrayref( + qq{ SELECT bugs.product_id, bgm.group_id, gcm.membercontrol, groups.name, @@ -134,28 +140,32 @@ if ($cgi->param('createmissinggroupcontrolmapentries')) { ON bugs.product_id = gcm.product_id AND bgm.group_id = gcm.group_id WHERE COALESCE(gcm.membercontrol, $na) = $na - } . $dbh->sql_group_by('bugs.product_id, bgm.group_id', - 'gcm.membercontrol, groups.name, products.name')); - - foreach (@$invalid_combinations) { - my ($product_id, $group_id, $currentmembercontrol, - $group_name, $product_name) = @$_; - - $counter++; - if (defined($currentmembercontrol)) { - Status('group_control_map_entries_update', - {group_name => $group_name, product_name => $product_name}); - $updatesth->execute($group_id, $product_id); - } - else { - Status('group_control_map_entries_generation', - {group_name => $group_name, product_name => $product_name}); - $insertsth->execute($group_id, $product_id); - } + } + . $dbh->sql_group_by( + 'bugs.product_id, bgm.group_id', + 'gcm.membercontrol, groups.name, products.name' + ) + ); + + foreach (@$invalid_combinations) { + my ($product_id, $group_id, $currentmembercontrol, $group_name, $product_name) + = @$_; + + $counter++; + if (defined($currentmembercontrol)) { + Status('group_control_map_entries_update', + {group_name => $group_name, product_name => $product_name}); + $updatesth->execute($group_id, $product_id); } + else { + Status('group_control_map_entries_generation', + {group_name => $group_name, product_name => $product_name}); + $insertsth->execute($group_id, $product_id); + } + } - Status('group_control_map_entries_repaired', {counter => $counter}); - $clear_memcached = 1 if $counter; + Status('group_control_map_entries_repaired', {counter => $counter}); + $clear_memcached = 1 if $counter; } ########################################################################### @@ -163,26 +173,32 @@ if ($cgi->param('createmissinggroupcontrolmapentries')) { ########################################################################### if ($cgi->param('repair_creation_date')) { - Status('bug_creation_date_start'); - - my $bug_ids = $dbh->selectcol_arrayref('SELECT bug_id FROM bugs - WHERE creation_ts IS NULL'); - - my $sth_UpdateDate = $dbh->prepare('UPDATE bugs SET creation_ts = ? - WHERE bug_id = ?'); - - # All bugs have an entry in the 'longdescs' table when they are created, - # even if no comment is required. - my $sth_getDate = $dbh->prepare('SELECT MIN(bug_when) FROM longdescs - WHERE bug_id = ?'); - - foreach my $bugid (@$bug_ids) { - $sth_getDate->execute($bugid); - my $date = $sth_getDate->fetchrow_array; - $sth_UpdateDate->execute($date, $bugid); - } - Status('bug_creation_date_fixed', {bug_count => scalar(@$bug_ids)}); - $clear_memcached = 1 if @$bug_ids; + Status('bug_creation_date_start'); + + my $bug_ids = $dbh->selectcol_arrayref( + 'SELECT bug_id FROM bugs + WHERE creation_ts IS NULL' + ); + + my $sth_UpdateDate = $dbh->prepare( + 'UPDATE bugs SET creation_ts = ? + WHERE bug_id = ?' + ); + + # All bugs have an entry in the 'longdescs' table when they are created, + # even if no comment is required. + my $sth_getDate = $dbh->prepare( + 'SELECT MIN(bug_when) FROM longdescs + WHERE bug_id = ?' + ); + + foreach my $bugid (@$bug_ids) { + $sth_getDate->execute($bugid); + my $date = $sth_getDate->fetchrow_array; + $sth_UpdateDate->execute($date, $bugid); + } + Status('bug_creation_date_fixed', {bug_count => scalar(@$bug_ids)}); + $clear_memcached = 1 if @$bug_ids; } ########################################################################### @@ -190,16 +206,19 @@ if ($cgi->param('repair_creation_date')) { ########################################################################### if ($cgi->param('repair_everconfirmed')) { - Status('everconfirmed_start'); + Status('everconfirmed_start'); - my @confirmed_open_states = grep {$_ ne 'UNCONFIRMED'} BUG_STATE_OPEN; - my $confirmed_open_states = join(', ', map {$dbh->quote($_)} @confirmed_open_states); + my @confirmed_open_states = grep { $_ ne 'UNCONFIRMED' } BUG_STATE_OPEN; + my $confirmed_open_states + = join(', ', map { $dbh->quote($_) } @confirmed_open_states); - $dbh->do("UPDATE bugs SET everconfirmed = 0 WHERE bug_status = 'UNCONFIRMED'"); - $dbh->do("UPDATE bugs SET everconfirmed = 1 WHERE bug_status IN ($confirmed_open_states)"); + $dbh->do("UPDATE bugs SET everconfirmed = 0 WHERE bug_status = 'UNCONFIRMED'"); + $dbh->do( + "UPDATE bugs SET everconfirmed = 1 WHERE bug_status IN ($confirmed_open_states)" + ); - Status('everconfirmed_end'); - $clear_memcached = 1; + Status('everconfirmed_end'); + $clear_memcached = 1; } ########################################################################### @@ -207,20 +226,22 @@ if ($cgi->param('repair_everconfirmed')) { ########################################################################### if ($cgi->param('repair_bugs_fulltext')) { - Status('bugs_fulltext_start'); + Status('bugs_fulltext_start'); - my $bug_ids = $dbh->selectcol_arrayref('SELECT bugs.bug_id + my $bug_ids = $dbh->selectcol_arrayref( + 'SELECT bugs.bug_id FROM bugs LEFT JOIN bugs_fulltext ON bugs_fulltext.bug_id = bugs.bug_id - WHERE bugs_fulltext.bug_id IS NULL'); + WHERE bugs_fulltext.bug_id IS NULL' + ); - foreach my $bugid (@$bug_ids) { - Bugzilla::Bug->new($bugid)->_sync_fulltext( new_bug => 1 ); - } + foreach my $bugid (@$bug_ids) { + Bugzilla::Bug->new($bugid)->_sync_fulltext(new_bug => 1); + } - Status('bugs_fulltext_fixed', {bug_count => scalar(@$bug_ids)}); - $clear_memcached = 1 if @$bug_ids; + Status('bugs_fulltext_fixed', {bug_count => scalar(@$bug_ids)}); + $clear_memcached = 1 if @$bug_ids; } ########################################################################### @@ -228,44 +249,46 @@ if ($cgi->param('repair_bugs_fulltext')) { ########################################################################### if ($cgi->param('rescanallBugMail')) { - require Bugzilla::BugMail; + require Bugzilla::BugMail; - Status('send_bugmail_start'); - my $time = $dbh->sql_date_math('NOW()', '-', 30, 'MINUTE'); + Status('send_bugmail_start'); + my $time = $dbh->sql_date_math('NOW()', '-', 30, 'MINUTE'); - my $list = $dbh->selectcol_arrayref(qq{ + my $list = $dbh->selectcol_arrayref( + qq{ SELECT bug_id FROM bugs WHERE (lastdiffed IS NULL OR lastdiffed < delta_ts) AND delta_ts < $time - ORDER BY bug_id}); - - Status('send_bugmail_status', {bug_count => scalar(@$list)}); - - # We cannot simply look at the bugs_activity table to find who did the - # last change in a given bug, as e.g. adding a comment doesn't add any - # entry to this table. And some other changes may be private - # (such as time-related changes or private attachments or comments) - # and so choosing this user as being the last one having done a change - # for the bug may be problematic. So the best we can do at this point - # is to choose the currently logged in user for email notification. - $vars->{'changer'} = Bugzilla->user; - - foreach my $bugid (@$list) { - Bugzilla::BugMail::Send($bugid, $vars); - } - - if (@$list) { - Status('send_bugmail_end'); - Bugzilla->memcached->clear_all(); - } - - unless (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { - $template->process('global/footer.html.tmpl', $vars) - || ThrowTemplateError($template->error()); - } - exit; + ORDER BY bug_id} + ); + + Status('send_bugmail_status', {bug_count => scalar(@$list)}); + + # We cannot simply look at the bugs_activity table to find who did the + # last change in a given bug, as e.g. adding a comment doesn't add any + # entry to this table. And some other changes may be private + # (such as time-related changes or private attachments or comments) + # and so choosing this user as being the last one having done a change + # for the bug may be problematic. So the best we can do at this point + # is to choose the currently logged in user for email notification. + $vars->{'changer'} = Bugzilla->user; + + foreach my $bugid (@$list) { + Bugzilla::BugMail::Send($bugid, $vars); + } + + if (@$list) { + Status('send_bugmail_end'); + Bugzilla->memcached->clear_all(); + } + + unless (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { + $template->process('global/footer.html.tmpl', $vars) + || ThrowTemplateError($template->error()); + } + exit; } ########################################################################### @@ -273,32 +296,37 @@ if ($cgi->param('rescanallBugMail')) { ########################################################################### if ($cgi->param('remove_invalid_bug_references')) { - Status('bug_reference_deletion_start'); + Status('bug_reference_deletion_start'); - $dbh->bz_start_transaction(); + $dbh->bz_start_transaction(); - foreach my $pair ('attachments/', 'bug_group_map/', 'bugs_activity/', - 'bugs_fulltext/', 'cc/', - 'dependencies/blocked', 'dependencies/dependson', - 'duplicates/dupe', 'duplicates/dupe_of', - 'flags/', 'keywords/', 'longdescs/') { + foreach my $pair ( + 'attachments/', 'bug_group_map/', + 'bugs_activity/', 'bugs_fulltext/', + 'cc/', 'dependencies/blocked', + 'dependencies/dependson', 'duplicates/dupe', + 'duplicates/dupe_of', 'flags/', + 'keywords/', 'longdescs/' + ) + { - my ($table, $field) = split('/', $pair); - $field ||= "bug_id"; + my ($table, $field) = split('/', $pair); + $field ||= "bug_id"; - my $bug_ids = - $dbh->selectcol_arrayref("SELECT $table.$field FROM $table + my $bug_ids = $dbh->selectcol_arrayref( + "SELECT $table.$field FROM $table LEFT JOIN bugs ON $table.$field = bugs.bug_id - WHERE bugs.bug_id IS NULL"); + WHERE bugs.bug_id IS NULL" + ); - if (scalar(@$bug_ids)) { - $dbh->do("DELETE FROM $table WHERE $field IN (" . join(',', @$bug_ids) . ")"); - $clear_memcached = 1; - } + if (scalar(@$bug_ids)) { + $dbh->do("DELETE FROM $table WHERE $field IN (" . join(',', @$bug_ids) . ")"); + $clear_memcached = 1; } + } - $dbh->bz_commit_transaction(); - Status('bug_reference_deletion_end'); + $dbh->bz_commit_transaction(); + Status('bug_reference_deletion_end'); } ########################################################################### @@ -306,25 +334,26 @@ if ($cgi->param('remove_invalid_bug_references')) { ########################################################################### if ($cgi->param('remove_invalid_attach_references')) { - Status('attachment_reference_deletion_start'); + Status('attachment_reference_deletion_start'); - $dbh->bz_start_transaction(); + $dbh->bz_start_transaction(); - my $attach_ids = - $dbh->selectcol_arrayref('SELECT attach_data.id + my $attach_ids = $dbh->selectcol_arrayref( + 'SELECT attach_data.id FROM attach_data LEFT JOIN attachments ON attachments.attach_id = attach_data.id - WHERE attachments.attach_id IS NULL'); + WHERE attachments.attach_id IS NULL' + ); - if (scalar(@$attach_ids)) { - $dbh->do('DELETE FROM attach_data WHERE id IN (' . - join(',', @$attach_ids) . ')'); - } + if (scalar(@$attach_ids)) { + $dbh->do( + 'DELETE FROM attach_data WHERE id IN (' . join(',', @$attach_ids) . ')'); + } - $dbh->bz_commit_transaction(); - Status('attachment_reference_deletion_end'); - $clear_memcached = 1 if @$attach_ids; + $dbh->bz_commit_transaction(); + Status('attachment_reference_deletion_end'); + $clear_memcached = 1 if @$attach_ids; } ########################################################################### @@ -332,30 +361,33 @@ if ($cgi->param('remove_invalid_attach_references')) { ########################################################################### if ($cgi->param('remove_old_whine_targets')) { - Status('whines_obsolete_target_deletion_start'); + Status('whines_obsolete_target_deletion_start'); - $dbh->bz_start_transaction(); + $dbh->bz_start_transaction(); - foreach my $target (['groups', 'id', MAILTO_GROUP], - ['profiles', 'userid', MAILTO_USER]) - { - my ($table, $col, $type) = @$target; - my $old_ids = - $dbh->selectcol_arrayref("SELECT DISTINCT mailto + foreach my $target (['groups', 'id', MAILTO_GROUP], + ['profiles', 'userid', MAILTO_USER]) + { + my ($table, $col, $type) = @$target; + my $old_ids = $dbh->selectcol_arrayref( + "SELECT DISTINCT mailto FROM whine_schedules LEFT JOIN $table ON $table.$col = whine_schedules.mailto - WHERE mailto_type = $type AND $table.$col IS NULL"); - - if (scalar(@$old_ids)) { - $dbh->do("DELETE FROM whine_schedules - WHERE mailto_type = $type AND mailto IN (" . - join(',', @$old_ids) . ")"); - $clear_memcached = 1; - } + WHERE mailto_type = $type AND $table.$col IS NULL" + ); + + if (scalar(@$old_ids)) { + $dbh->do( + "DELETE FROM whine_schedules + WHERE mailto_type = $type AND mailto IN (" + . join(',', @$old_ids) . ")" + ); + $clear_memcached = 1; } - $dbh->bz_commit_transaction(); - Status('whines_obsolete_target_deletion_end'); + } + $dbh->bz_commit_transaction(); + Status('whines_obsolete_target_deletion_end'); } # If any repairs were attempted or made, we need to clear memcached to ensure @@ -368,7 +400,7 @@ Bugzilla->memcached->clear_all() if $clear_memcached; REPAIR_HOOKS: -Bugzilla::Hook::process('sanitycheck_repair', { status => \&Status }); +Bugzilla::Hook::process('sanitycheck_repair', {status => \&Status}); goto CHECK_HOOKS if $hooks_only; ########################################################################### @@ -399,177 +431,206 @@ Status('checks_start'); # The same goes for series; no bug for that yet. sub CrossCheck { - my $table = shift @_; - my $field = shift @_; - my $dbh = Bugzilla->dbh; + my $table = shift @_; + my $field = shift @_; + my $dbh = Bugzilla->dbh; - Status('cross_check_to', {table => $table, field => $field}); + Status('cross_check_to', {table => $table, field => $field}); - while (@_) { - my $ref = shift @_; - my ($refertable, $referfield, $keyname, $exceptions) = @$ref; + while (@_) { + my $ref = shift @_; + my ($refertable, $referfield, $keyname, $exceptions) = @$ref; - $exceptions ||= []; - my %exceptions = map { $_ => 1 } @$exceptions; + $exceptions ||= []; + my %exceptions = map { $_ => 1 } @$exceptions; - Status('cross_check_from', {table => $refertable, field => $referfield}); + Status('cross_check_from', {table => $refertable, field => $referfield}); - my $query = qq{SELECT DISTINCT $refertable.$referfield} . - ($keyname ? qq{, $refertable.$keyname } : q{}) . - qq{ FROM $refertable + my $query + = qq{SELECT DISTINCT $refertable.$referfield} + . ($keyname ? qq{, $refertable.$keyname } : q{}) + . qq{ FROM $refertable LEFT JOIN $table ON $refertable.$referfield = $table.$field WHERE $table.$field IS NULL AND $refertable.$referfield IS NOT NULL}; - my $sth = $dbh->prepare($query); - $sth->execute; - - my $has_bad_references = 0; - - while (my ($value, $key) = $sth->fetchrow_array) { - next if $exceptions{$value}; - Status('cross_check_alert', {value => $value, table => $refertable, - field => $referfield, keyname => $keyname, - key => $key}, 'alert'); - $has_bad_references = 1; - } - # References to non existent bugs can be safely removed, bug 288461 - if ($table eq 'bugs' && $has_bad_references) { - Status('cross_check_bug_has_references'); - } - # References to non existent attachments can be safely removed. - if ($table eq 'attachments' && $has_bad_references) { - Status('cross_check_attachment_has_references'); - } + my $sth = $dbh->prepare($query); + $sth->execute; + + my $has_bad_references = 0; + + while (my ($value, $key) = $sth->fetchrow_array) { + next if $exceptions{$value}; + Status( + 'cross_check_alert', + { + value => $value, + table => $refertable, + field => $referfield, + keyname => $keyname, + key => $key + }, + 'alert' + ); + $has_bad_references = 1; + } + + # References to non existent bugs can be safely removed, bug 288461 + if ($table eq 'bugs' && $has_bad_references) { + Status('cross_check_bug_has_references'); } + + # References to non existent attachments can be safely removed. + if ($table eq 'attachments' && $has_bad_references) { + Status('cross_check_attachment_has_references'); + } + } } -CrossCheck('classifications', 'id', - ['products', 'classification_id']); - -CrossCheck("keyworddefs", "id", - ["keywords", "keywordid"]); - -CrossCheck("fielddefs", "id", - ["bugs_activity", "fieldid"], - ['profiles_activity', 'fieldid']); - -CrossCheck("flagtypes", "id", - ["flags", "type_id"], - ["flagexclusions", "type_id"], - ["flaginclusions", "type_id"]); - -CrossCheck("bugs", "bug_id", - ["bugs_activity", "bug_id"], - ["bug_group_map", "bug_id"], - ["bugs_fulltext", "bug_id"], - ["attachments", "bug_id"], - ["cc", "bug_id"], - ["longdescs", "bug_id"], - ["dependencies", "blocked"], - ["dependencies", "dependson"], - ['flags', 'bug_id'], - ["keywords", "bug_id"], - ["duplicates", "dupe_of", "dupe"], - ["duplicates", "dupe", "dupe_of"]); - -CrossCheck("groups", "id", - ["bug_group_map", "group_id"], - ['category_group_map', 'group_id'], - ["group_group_map", "grantor_id"], - ["group_group_map", "member_id"], - ["group_control_map", "group_id"], - ["namedquery_group_map", "group_id"], - ["user_group_map", "group_id"], - ["flagtypes", "grant_group_id"], - ["flagtypes", "request_group_id"]); - -CrossCheck("namedqueries", "id", - ["namedqueries_link_in_footer", "namedquery_id"], - ["namedquery_group_map", "namedquery_id"], - ); - -CrossCheck("profiles", "userid", - ['profiles_activity', 'userid'], - ['profiles_activity', 'who'], - ['email_setting', 'user_id'], - ['profile_setting', 'user_id'], - ["bugs", "reporter", "bug_id"], - ["bugs", "assigned_to", "bug_id"], - ["bugs", "qa_contact", "bug_id"], - ["attachments", "submitter_id", "bug_id"], - ['flags', 'setter_id', 'bug_id'], - ['flags', 'requestee_id', 'bug_id'], - ["bugs_activity", "who", "bug_id"], - ["cc", "who", "bug_id"], - ['quips', 'userid'], - ["longdescs", "who", "bug_id"], - ["logincookies", "userid"], - ["namedqueries", "userid"], - ["namedqueries_link_in_footer", "user_id"], - ['series', 'creator', 'series_id'], - ["watch", "watcher"], - ["watch", "watched"], - ['whine_events', 'owner_userid'], - ["tokens", "userid"], - ["user_group_map", "user_id"], - ["components", "initialowner", "name"], - ["components", "initialqacontact", "name"], - ["component_cc", "user_id"]); - -CrossCheck("products", "id", - ["bugs", "product_id", "bug_id"], - ["components", "product_id", "name"], - ["milestones", "product_id", "value"], - ["versions", "product_id", "value"], - ["group_control_map", "product_id"], - ["flaginclusions", "product_id", "type_id"], - ["flagexclusions", "product_id", "type_id"]); - -CrossCheck("components", "id", - ["component_cc", "component_id"], - ["flagexclusions", "component_id", "type_id"], - ["flaginclusions", "component_id", "type_id"]); +CrossCheck('classifications', 'id', ['products', 'classification_id']); + +CrossCheck("keyworddefs", "id", ["keywords", "keywordid"]); + +CrossCheck( + "fielddefs", "id", + ["bugs_activity", "fieldid"], + ['profiles_activity', 'fieldid'] +); + +CrossCheck( + "flagtypes", "id", + ["flags", "type_id"], + ["flagexclusions", "type_id"], + ["flaginclusions", "type_id"] +); + +CrossCheck( + "bugs", + "bug_id", + ["bugs_activity", "bug_id"], + ["bug_group_map", "bug_id"], + ["bugs_fulltext", "bug_id"], + ["attachments", "bug_id"], + ["cc", "bug_id"], + ["longdescs", "bug_id"], + ["dependencies", "blocked"], + ["dependencies", "dependson"], + ['flags', 'bug_id'], + ["keywords", "bug_id"], + ["duplicates", "dupe_of", "dupe"], + ["duplicates", "dupe", "dupe_of"] +); + +CrossCheck( + "groups", + "id", + ["bug_group_map", "group_id"], + ['category_group_map', 'group_id'], + ["group_group_map", "grantor_id"], + ["group_group_map", "member_id"], + ["group_control_map", "group_id"], + ["namedquery_group_map", "group_id"], + ["user_group_map", "group_id"], + ["flagtypes", "grant_group_id"], + ["flagtypes", "request_group_id"] +); + +CrossCheck( + "namedqueries", "id", + ["namedqueries_link_in_footer", "namedquery_id"], + ["namedquery_group_map", "namedquery_id"], +); + +CrossCheck( + "profiles", + "userid", + ['profiles_activity', 'userid'], + ['profiles_activity', 'who'], + ['email_setting', 'user_id'], + ['profile_setting', 'user_id'], + ["bugs", "reporter", "bug_id"], + ["bugs", "assigned_to", "bug_id"], + ["bugs", "qa_contact", "bug_id"], + ["attachments", "submitter_id", "bug_id"], + ['flags', 'setter_id', 'bug_id'], + ['flags', 'requestee_id', 'bug_id'], + ["bugs_activity", "who", "bug_id"], + ["cc", "who", "bug_id"], + ['quips', 'userid'], + ["longdescs", "who", "bug_id"], + ["logincookies", "userid"], + ["namedqueries", "userid"], + ["namedqueries_link_in_footer", "user_id"], + ['series', 'creator', 'series_id'], + ["watch", "watcher"], + ["watch", "watched"], + ['whine_events', 'owner_userid'], + ["tokens", "userid"], + ["user_group_map", "user_id"], + ["components", "initialowner", "name"], + ["components", "initialqacontact", "name"], + ["component_cc", "user_id"] +); + +CrossCheck( + "products", + "id", + ["bugs", "product_id", "bug_id"], + ["components", "product_id", "name"], + ["milestones", "product_id", "value"], + ["versions", "product_id", "value"], + ["group_control_map", "product_id"], + ["flaginclusions", "product_id", "type_id"], + ["flagexclusions", "product_id", "type_id"] +); + +CrossCheck( + "components", "id", + ["component_cc", "component_id"], + ["flagexclusions", "component_id", "type_id"], + ["flaginclusions", "component_id", "type_id"] +); # Check the former enum types -mkanat@bugzilla.org -CrossCheck("bug_status", "value", - ["bugs", "bug_status", "bug_id"]); +CrossCheck("bug_status", "value", ["bugs", "bug_status", "bug_id"]); -CrossCheck("resolution", "value", - ["bugs", "resolution", "bug_id"]); +CrossCheck("resolution", "value", ["bugs", "resolution", "bug_id"]); -CrossCheck("bug_severity", "value", - ["bugs", "bug_severity", "bug_id"]); +CrossCheck("bug_severity", "value", ["bugs", "bug_severity", "bug_id"]); -CrossCheck("op_sys", "value", - ["bugs", "op_sys", "bug_id"]); +CrossCheck("op_sys", "value", ["bugs", "op_sys", "bug_id"]); -CrossCheck("priority", "value", - ["bugs", "priority", "bug_id"]); +CrossCheck("priority", "value", ["bugs", "priority", "bug_id"]); -CrossCheck("rep_platform", "value", - ["bugs", "rep_platform", "bug_id"]); +CrossCheck("rep_platform", "value", ["bugs", "rep_platform", "bug_id"]); -CrossCheck('series', 'series_id', - ['series_data', 'series_id']); +CrossCheck('series', 'series_id', ['series_data', 'series_id']); -CrossCheck('series_categories', 'id', - ['series', 'category'], - ["category_group_map", "category_id"], - ["series", "subcategory"]); +CrossCheck( + 'series_categories', 'id', + ['series', 'category'], + ["category_group_map", "category_id"], + ["series", "subcategory"] +); -CrossCheck('whine_events', 'id', - ['whine_queries', 'eventid'], - ['whine_schedules', 'eventid']); +CrossCheck( + 'whine_events', 'id', + ['whine_queries', 'eventid'], + ['whine_schedules', 'eventid'] +); -CrossCheck('attachments', 'attach_id', - ['attach_data', 'id'], - ['bugs_activity', 'attach_id']); +CrossCheck( + 'attachments', 'attach_id', + ['attach_data', 'id'], + ['bugs_activity', 'attach_id'] +); -CrossCheck('bug_status', 'id', - ['status_workflow', 'old_status'], - ['status_workflow', 'new_status']); +CrossCheck( + 'bug_status', 'id', + ['status_workflow', 'old_status'], + ['status_workflow', 'new_status'] +); ########################################################################### # Perform double field referential (cross) checks @@ -590,60 +651,77 @@ CrossCheck('bug_status', 'id', # table to display when the check fails sub DoubleCrossCheck { - my $table = shift @_; - my $field1 = shift @_; - my $field2 = shift @_; - my $dbh = Bugzilla->dbh; + my $table = shift @_; + my $field1 = shift @_; + my $field2 = shift @_; + my $dbh = Bugzilla->dbh; - Status('double_cross_check_to', - {table => $table, field1 => $field1, field2 => $field2}); + Status('double_cross_check_to', + {table => $table, field1 => $field1, field2 => $field2}); - while (@_) { - my $ref = shift @_; - my ($refertable, $referfield1, $referfield2, $keyname) = @$ref; + while (@_) { + my $ref = shift @_; + my ($refertable, $referfield1, $referfield2, $keyname) = @$ref; - Status('double_cross_check_from', - {table => $refertable, field1 => $referfield1, field2 =>$referfield2}); + Status('double_cross_check_from', + {table => $refertable, field1 => $referfield1, field2 => $referfield2}); - my $d_cross_check = $dbh->selectall_arrayref(qq{ + my $d_cross_check = $dbh->selectall_arrayref( + qq{ SELECT DISTINCT $refertable.$referfield1, - $refertable.$referfield2 } . - ($keyname ? qq{, $refertable.$keyname } : q{}) . - qq{ FROM $refertable + $refertable.$referfield2 } + . ($keyname ? qq{, $refertable.$keyname } : q{}) . qq{ FROM $refertable LEFT JOIN $table ON $refertable.$referfield1 = $table.$field1 AND $refertable.$referfield2 = $table.$field2 WHERE $table.$field1 IS NULL AND $table.$field2 IS NULL AND $refertable.$referfield1 IS NOT NULL - AND $refertable.$referfield2 IS NOT NULL}); - - foreach my $check (@$d_cross_check) { - my ($value1, $value2, $key) = @$check; - Status('double_cross_check_alert', - {value1 => $value1, value2 => $value2, - table => $refertable, - field1 => $referfield1, field2 => $referfield2, - keyname => $keyname, key => $key}, 'alert'); - } + AND $refertable.$referfield2 IS NOT NULL} + ); + + foreach my $check (@$d_cross_check) { + my ($value1, $value2, $key) = @$check; + Status( + 'double_cross_check_alert', + { + value1 => $value1, + value2 => $value2, + table => $refertable, + field1 => $referfield1, + field2 => $referfield2, + keyname => $keyname, + key => $key + }, + 'alert' + ); } + } } -DoubleCrossCheck('attachments', 'bug_id', 'attach_id', - ['flags', 'bug_id', 'attach_id'], - ['bugs_activity', 'bug_id', 'attach_id']); - -DoubleCrossCheck("components", "product_id", "id", - ["bugs", "product_id", "component_id", "bug_id"], - ['flagexclusions', 'product_id', 'component_id'], - ['flaginclusions', 'product_id', 'component_id']); +DoubleCrossCheck( + 'attachments', 'bug_id', 'attach_id', + ['flags', 'bug_id', 'attach_id'], + ['bugs_activity', 'bug_id', 'attach_id'] +); + +DoubleCrossCheck( + "components", + "product_id", + "id", + ["bugs", "product_id", "component_id", "bug_id"], + ['flagexclusions', 'product_id', 'component_id'], + ['flaginclusions', 'product_id', 'component_id'] +); DoubleCrossCheck("versions", "product_id", "value", - ["bugs", "product_id", "version", "bug_id"]); + ["bugs", "product_id", "version", "bug_id"]); -DoubleCrossCheck("milestones", "product_id", "value", - ["bugs", "product_id", "target_milestone", "bug_id"], - ["products", "id", "defaultmilestone", "name"]); +DoubleCrossCheck( + "milestones", "product_id", "value", + ["bugs", "product_id", "target_milestone", "bug_id"], + ["products", "id", "defaultmilestone", "name"] +); ########################################################################### # Perform login checks @@ -655,8 +733,8 @@ my $sth = $dbh->prepare(q{SELECT userid, login_name FROM profiles}); $sth->execute; while (my ($id, $email) = $sth->fetchrow_array) { - validate_email_syntax($email) - || Status('profile_login_alert', {id => $id, email => $email}, 'alert'); + validate_email_syntax($email) + || Status('profile_login_alert', {id => $id, email => $email}, 'alert'); } ########################################################################### @@ -664,42 +742,46 @@ while (my ($id, $email) = $sth->fetchrow_array) { ########################################################################### sub check_keywords { - my $dbh = Bugzilla->dbh; - my $cgi = Bugzilla->cgi; - - Status('keyword_check_start'); - - my %keywordids; - my $keywords = $dbh->selectall_arrayref(q{SELECT id, name - FROM keyworddefs}); - - foreach (@$keywords) { - my ($id, $name) = @$_; - if ($keywordids{$id}) { - Status('keyword_check_alert', {id => $id}, 'alert'); - } - $keywordids{$id} = 1; - if ($name =~ /[\s,]/) { - Status('keyword_check_invalid_name', {id => $id}, 'alert'); - } + my $dbh = Bugzilla->dbh; + my $cgi = Bugzilla->cgi; + + Status('keyword_check_start'); + + my %keywordids; + my $keywords = $dbh->selectall_arrayref( + q{SELECT id, name + FROM keyworddefs} + ); + + foreach (@$keywords) { + my ($id, $name) = @$_; + if ($keywordids{$id}) { + Status('keyword_check_alert', {id => $id}, 'alert'); } + $keywordids{$id} = 1; + if ($name =~ /[\s,]/) { + Status('keyword_check_invalid_name', {id => $id}, 'alert'); + } + } - my $sth = $dbh->prepare(q{SELECT bug_id, keywordid + my $sth = $dbh->prepare( + q{SELECT bug_id, keywordid FROM keywords - ORDER BY bug_id, keywordid}); - $sth->execute; - my $lastid; - my $lastk; - while (my ($id, $k) = $sth->fetchrow_array) { - if (!$keywordids{$k}) { - Status('keyword_check_invalid_id', {id => $k}, 'alert'); - } - if (defined $lastid && $id eq $lastid && $k eq $lastk) { - Status('keyword_check_duplicated_ids', {id => $id}, 'alert'); - } - $lastid = $id; - $lastk = $k; + ORDER BY bug_id, keywordid} + ); + $sth->execute; + my $lastid; + my $lastk; + while (my ($id, $k) = $sth->fetchrow_array) { + if (!$keywordids{$k}) { + Status('keyword_check_invalid_id', {id => $k}, 'alert'); + } + if (defined $lastid && $id eq $lastid && $k eq $lastk) { + Status('keyword_check_duplicated_ids', {id => $id}, 'alert'); } + $lastid = $id; + $lastk = $k; + } } ########################################################################### @@ -709,7 +791,7 @@ sub check_keywords { Status('flag_check_start'); my $invalid_flags = $dbh->selectall_arrayref( - 'SELECT DISTINCT flags.id, flags.bug_id, flags.attach_id + 'SELECT DISTINCT flags.id, flags.bug_id, flags.attach_id FROM flags INNER JOIN bugs ON flags.bug_id = bugs.bug_id @@ -717,40 +799,42 @@ my $invalid_flags = $dbh->selectall_arrayref( ON flags.type_id = i.type_id AND (bugs.product_id = i.product_id OR i.product_id IS NULL) AND (bugs.component_id = i.component_id OR i.component_id IS NULL) - WHERE i.type_id IS NULL'); + WHERE i.type_id IS NULL' +); my @invalid_flags = @$invalid_flags; $invalid_flags = $dbh->selectall_arrayref( - 'SELECT DISTINCT flags.id, flags.bug_id, flags.attach_id + 'SELECT DISTINCT flags.id, flags.bug_id, flags.attach_id FROM flags INNER JOIN bugs ON flags.bug_id = bugs.bug_id INNER JOIN flagexclusions AS e ON flags.type_id = e.type_id WHERE (bugs.product_id = e.product_id OR e.product_id IS NULL) - AND (bugs.component_id = e.component_id OR e.component_id IS NULL)'); + AND (bugs.component_id = e.component_id OR e.component_id IS NULL)' +); push(@invalid_flags, @$invalid_flags); if (scalar(@invalid_flags)) { - if ($cgi->param('remove_invalid_flags')) { - Status('flag_deletion_start'); - my @flag_ids = map {$_->[0]} @invalid_flags; - # Silently delete these flags, with no notification to requesters/setters. - $dbh->do('DELETE FROM flags WHERE id IN (' . join(',', @flag_ids) .')'); - Status('flag_deletion_end'); - Bugzilla->memcached->clear_all(); - } - else { - foreach my $flag (@$invalid_flags) { - my ($flag_id, $bug_id, $attach_id) = @$flag; - Status('flag_alert', - {flag_id => $flag_id, attach_id => $attach_id, bug_id => $bug_id}, - 'alert'); - } - Status('flag_fix'); + if ($cgi->param('remove_invalid_flags')) { + Status('flag_deletion_start'); + my @flag_ids = map { $_->[0] } @invalid_flags; + + # Silently delete these flags, with no notification to requesters/setters. + $dbh->do('DELETE FROM flags WHERE id IN (' . join(',', @flag_ids) . ')'); + Status('flag_deletion_end'); + Bugzilla->memcached->clear_all(); + } + else { + foreach my $flag (@$invalid_flags) { + my ($flag_id, $bug_id, $attach_id) = @$flag; + Status('flag_alert', + {flag_id => $flag_id, attach_id => $attach_id, bug_id => $bug_id}, 'alert'); } + Status('flag_fix'); + } } ########################################################################### @@ -758,45 +842,58 @@ if (scalar(@invalid_flags)) { ########################################################################### sub BugCheck { - my ($middlesql, $errortext, $repairparam, $repairtext) = @_; - my $dbh = Bugzilla->dbh; + my ($middlesql, $errortext, $repairparam, $repairtext) = @_; + my $dbh = Bugzilla->dbh; - my $badbugs = $dbh->selectcol_arrayref(qq{SELECT DISTINCT bugs.bug_id + my $badbugs = $dbh->selectcol_arrayref( + qq{SELECT DISTINCT bugs.bug_id FROM $middlesql - ORDER BY bugs.bug_id}); - - if (scalar(@$badbugs)) { - Status('bug_check_alert', - {errortext => get_string($errortext), badbugs => $badbugs}, - 'alert'); - - if ($repairparam) { - $repairtext ||= 'repair_bugs'; - Status('bug_check_repair', - {param => $repairparam, text => get_string($repairtext)}); - } + ORDER BY bugs.bug_id} + ); + + if (scalar(@$badbugs)) { + Status('bug_check_alert', + {errortext => get_string($errortext), badbugs => $badbugs}, 'alert'); + + if ($repairparam) { + $repairtext ||= 'repair_bugs'; + Status('bug_check_repair', + {param => $repairparam, text => get_string($repairtext)}); } + } } Status('bug_check_creation_date'); -BugCheck("bugs WHERE creation_ts IS NULL", 'bug_check_creation_date_error_text', - 'repair_creation_date', 'bug_check_creation_date_repair_text'); +BugCheck( + "bugs WHERE creation_ts IS NULL", 'bug_check_creation_date_error_text', + 'repair_creation_date', 'bug_check_creation_date_repair_text' +); Status('bug_check_bugs_fulltext'); -BugCheck("bugs LEFT JOIN bugs_fulltext ON bugs_fulltext.bug_id = bugs.bug_id " . - "WHERE bugs_fulltext.bug_id IS NULL", 'bug_check_bugs_fulltext_error_text', - 'repair_bugs_fulltext', 'bug_check_bugs_fulltext_repair_text'); +BugCheck( + "bugs LEFT JOIN bugs_fulltext ON bugs_fulltext.bug_id = bugs.bug_id " + . "WHERE bugs_fulltext.bug_id IS NULL", + 'bug_check_bugs_fulltext_error_text', + 'repair_bugs_fulltext', + 'bug_check_bugs_fulltext_repair_text' +); Status('bug_check_res_dupl'); -BugCheck("bugs INNER JOIN duplicates ON bugs.bug_id = duplicates.dupe " . - "WHERE bugs.resolution != 'DUPLICATE'", 'bug_check_res_dupl_error_text'); +BugCheck( + "bugs INNER JOIN duplicates ON bugs.bug_id = duplicates.dupe " + . "WHERE bugs.resolution != 'DUPLICATE'", + 'bug_check_res_dupl_error_text' +); -BugCheck("bugs LEFT JOIN duplicates ON bugs.bug_id = duplicates.dupe WHERE " . - "bugs.resolution = 'DUPLICATE' AND " . - "duplicates.dupe IS NULL", 'bug_check_res_dupl_error_text2'); +BugCheck( + "bugs LEFT JOIN duplicates ON bugs.bug_id = duplicates.dupe WHERE " + . "bugs.resolution = 'DUPLICATE' AND " + . "duplicates.dupe IS NULL", + 'bug_check_res_dupl_error_text2' +); Status('bug_check_status_res'); @@ -804,20 +901,27 @@ my @open_states = map($dbh->quote($_), BUG_STATE_OPEN); my $open_states = join(', ', @open_states); BugCheck("bugs WHERE bug_status IN ($open_states) AND resolution != ''", - 'bug_check_status_res_error_text'); + 'bug_check_status_res_error_text'); BugCheck("bugs WHERE bug_status NOT IN ($open_states) AND resolution = ''", - 'bug_check_status_res_error_text2'); + 'bug_check_status_res_error_text2'); Status('bug_check_status_everconfirmed'); -BugCheck("bugs WHERE bug_status = 'UNCONFIRMED' AND everconfirmed = 1", - 'bug_check_status_everconfirmed_error_text', 'repair_everconfirmed'); +BugCheck( + "bugs WHERE bug_status = 'UNCONFIRMED' AND everconfirmed = 1", + 'bug_check_status_everconfirmed_error_text', + 'repair_everconfirmed' +); -my @confirmed_open_states = grep {$_ ne 'UNCONFIRMED'} BUG_STATE_OPEN; -my $confirmed_open_states = join(', ', map {$dbh->quote($_)} @confirmed_open_states); +my @confirmed_open_states = grep { $_ ne 'UNCONFIRMED' } BUG_STATE_OPEN; +my $confirmed_open_states + = join(', ', map { $dbh->quote($_) } @confirmed_open_states); -BugCheck("bugs WHERE bug_status IN ($confirmed_open_states) AND everconfirmed = 0", - 'bug_check_status_everconfirmed_error_text2', 'repair_everconfirmed'); +BugCheck( + "bugs WHERE bug_status IN ($confirmed_open_states) AND everconfirmed = 0", + 'bug_check_status_everconfirmed_error_text2', + 'repair_everconfirmed' +); ########################################################################### # Control Values @@ -826,8 +930,8 @@ BugCheck("bugs WHERE bug_status IN ($confirmed_open_states) AND everconfirmed = # Checks for values that are invalid OR # not among the 9 valid combinations Status('bug_check_control_values'); -my $groups = join(", ", (CONTROLMAPNA, CONTROLMAPSHOWN, CONTROLMAPDEFAULT, -CONTROLMAPMANDATORY)); +my $groups = join(", ", + (CONTROLMAPNA, CONTROLMAPSHOWN, CONTROLMAPDEFAULT, CONTROLMAPMANDATORY)); my $query = qq{ SELECT COUNT(product_id) FROM group_control_map @@ -839,10 +943,12 @@ my $query = qq{ OR (othercontrol = } . CONTROLMAPSHOWN . q{)))}; my $entries = $dbh->selectrow_array($query); -Status('bug_check_control_values_alert', {entries => $entries}, 'alert') if $entries; +Status('bug_check_control_values_alert', {entries => $entries}, 'alert') + if $entries; Status('bug_check_control_values_violation'); -BugCheck("bugs +BugCheck( + "bugs INNER JOIN bug_group_map ON bugs.bug_id = bug_group_map.bug_id LEFT JOIN group_control_map @@ -850,11 +956,12 @@ BugCheck("bugs AND bug_group_map.group_id = group_control_map.group_id WHERE ((group_control_map.membercontrol = " . CONTROLMAPNA . ") OR (group_control_map.membercontrol IS NULL))", - 'bug_check_control_values_error_text', - 'createmissinggroupcontrolmapentries', - 'bug_check_control_values_repair_text'); + 'bug_check_control_values_error_text', 'createmissinggroupcontrolmapentries', + 'bug_check_control_values_repair_text' +); -BugCheck("bugs +BugCheck( + "bugs INNER JOIN group_control_map ON bugs.product_id = group_control_map.product_id INNER JOIN groups @@ -864,8 +971,8 @@ BugCheck("bugs AND group_control_map.group_id = bug_group_map.group_id WHERE group_control_map.membercontrol = " . CONTROLMAPMANDATORY . " AND bug_group_map.group_id IS NULL - AND groups.isactive != 0", - 'bug_check_control_values_error_text2'); + AND groups.isactive != 0", 'bug_check_control_values_error_text2' +); ########################################################################### # Unsent mail @@ -874,17 +981,19 @@ BugCheck("bugs Status('unsent_bugmail_check'); my $time = $dbh->sql_date_math('NOW()', '-', 30, 'MINUTE'); -my $badbugs = $dbh->selectcol_arrayref(qq{ +my $badbugs = $dbh->selectcol_arrayref( + qq{ SELECT bug_id FROM bugs WHERE (lastdiffed IS NULL OR lastdiffed < delta_ts) AND delta_ts < $time - ORDER BY bug_id}); + ORDER BY bug_id} +); if (scalar(@$badbugs > 0)) { - Status('unsent_bugmail_alert', {badbugs => $badbugs}, 'alert'); - Status('unsent_bugmail_fix'); + Status('unsent_bugmail_alert', {badbugs => $badbugs}, 'alert'); + Status('unsent_bugmail_fix'); } ########################################################################### @@ -895,19 +1004,22 @@ Status('whines_obsolete_target_start'); my $display_repair_whines_link = 0; foreach my $target (['groups', 'id', MAILTO_GROUP], - ['profiles', 'userid', MAILTO_USER]) + ['profiles', 'userid', MAILTO_USER]) { - my ($table, $col, $type) = @$target; - my $old = $dbh->selectall_arrayref("SELECT whine_schedules.id, mailto + my ($table, $col, $type) = @$target; + my $old = $dbh->selectall_arrayref( + "SELECT whine_schedules.id, mailto FROM whine_schedules LEFT JOIN $table ON $table.$col = whine_schedules.mailto - WHERE mailto_type = $type AND $table.$col IS NULL"); - - if (scalar(@$old)) { - Status('whines_obsolete_target_alert', {schedules => $old, type => $type}, 'alert'); - $display_repair_whines_link = 1; - } + WHERE mailto_type = $type AND $table.$col IS NULL" + ); + + if (scalar(@$old)) { + Status('whines_obsolete_target_alert', + {schedules => $old, type => $type}, 'alert'); + $display_repair_whines_link = 1; + } } Status('whines_obsolete_target_fix') if $display_repair_whines_link; @@ -915,7 +1027,7 @@ Status('whines_obsolete_target_fix') if $display_repair_whines_link; # Check hook ########################################################################### CHECK_HOOKS: -Bugzilla::Hook::process('sanitycheck_check', { status => \&Status }); +Bugzilla::Hook::process('sanitycheck_check', {status => \&Status}); ########################################################################### # End @@ -924,6 +1036,6 @@ Bugzilla::Hook::process('sanitycheck_check', { status => \&Status }); Status('checks_completed'); unless (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { - $template->process('global/footer.html.tmpl', $vars) - || ThrowTemplateError($template->error()); + $template->process('global/footer.html.tmpl', $vars) + || ThrowTemplateError($template->error()); } |