diff options
author | wurblzap%gmail.com <> | 2006-01-02 06:25:04 +0100 |
---|---|---|
committer | wurblzap%gmail.com <> | 2006-01-02 06:25:04 +0100 |
commit | 5f4feeeaf9d42587e27d300ad0cec099097d8ed1 (patch) | |
tree | c05abc90fc35f4dd0a22147b91156312b8945487 | |
parent | 418fb4bfb5a14eded370f1981d014ea8fd1f62d1 (diff) | |
download | bugzilla-5f4feeeaf9d42587e27d300ad0cec099097d8ed1.tar.gz bugzilla-5f4feeeaf9d42587e27d300ad0cec099097d8ed1.tar.xz |
Bug 300473: "All Closed" for components missing bug_status= in series.query.
Patch by Marc Schumann <wurblzap@gmail.com>,
r=wicked, a=justdave
-rwxr-xr-x | checksetup.pl | 123 | ||||
-rwxr-xr-x | editcomponents.cgi | 22 | ||||
-rw-r--r-- | template/en/default/admin/components/create.html.tmpl | 2 |
3 files changed, 134 insertions, 13 deletions
diff --git a/checksetup.pl b/checksetup.pl index a7ebd953c..0e4779314 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -34,6 +34,7 @@ # Joel Peshkin <bugreport@peshkin.net> # Lance Larsh <lance.larsh@oracle.com> # A. Karl Kornel <karl@kornel.name> +# Marc Schumann <wurblzap@gmail.com> # # # @@ -4089,6 +4090,128 @@ if ($dbh->bz_column_info("attachments", "thedata")) { $dbh->bz_drop_column("attachments", "thedata"); } +# 2005-11-26 - wurblzap@gmail.com - Bug 300473 +# Repair broken automatically generated series queries for non-open bugs. +my $broken_series_indicator = + 'field0-0-0=resolution&type0-0-0=notequals&value0-0-0=---'; +my $broken_nonopen_series = + $dbh->selectall_arrayref("SELECT series_id, query FROM series + WHERE query LIKE '$broken_series_indicator%'"); +if (@$broken_nonopen_series) { + print 'Repairing broken series...'; + my $sth_nuke = + $dbh->prepare('DELETE FROM series_data WHERE series_id = ?'); + # This statement is used to repair a series by replacing the broken query + # with the correct one. + my $sth_repair = + $dbh->prepare('UPDATE series SET query = ? WHERE series_id = ?'); + # The corresponding series for open bugs look like one of these two + # variations (bug 225687 changed the order of bug states). + # This depends on the set of bug states representing open bugs not to have + # changed since series creation. + my $open_bugs_query_base_old = + join("&", map { "bug_status=" . url_quote($_) } + ('UNCONFIRMED', 'NEW', 'ASSIGNED', 'REOPENED')); + my $open_bugs_query_base_new = + join("&", map { "bug_status=" . url_quote($_) } OpenStates()); + my $sth_openbugs_series = + $dbh->prepare("SELECT series_id FROM series + WHERE query IN (?, ?)"); + # Statement to find the series which has collected the most data. + my $sth_data_collected = + $dbh->prepare('SELECT count(*) FROM series_data WHERE series_id = ?'); + # Statement to select a broken non-open bugs count data entry. + my $sth_select_broken_nonopen_data = + $dbh->prepare('SELECT series_date, series_value FROM series_data' . + ' WHERE series_id = ?'); + # Statement to select an open bugs count data entry. + my $sth_select_open_data = + $dbh->prepare('SELECT series_value FROM series_data' . + ' WHERE series_id = ? AND series_date = ?'); + # Statement to fix a broken non-open bugs count data entry. + my $sth_fix_broken_nonopen_data = + $dbh->prepare('UPDATE series_data SET series_value = ?' . + ' WHERE series_id = ? AND series_date = ?'); + # Statement to delete an unfixable broken non-open bugs count data entry. + my $sth_delete_broken_nonopen_data = + $dbh->prepare('DELETE FROM series_data' . + ' WHERE series_id = ? AND series_date = ?'); + + foreach (@$broken_nonopen_series) { + my ($broken_series_id, $nonopen_bugs_query) = @$_; + + # Determine the product-and-component part of the query. + if ($nonopen_bugs_query =~ /^$broken_series_indicator(.*)$/) { + my $prodcomp = $1; + + # If there is more than one series for the corresponding open-bugs + # series, we pick the one with the most data, which should be the + # one which was generated on creation. + # It's a pity we can't do subselects. + $sth_openbugs_series->execute($open_bugs_query_base_old . $prodcomp, + $open_bugs_query_base_new . $prodcomp); + my ($found_open_series_id, $datacount) = (undef, -1); + foreach my $open_series_id ($sth_openbugs_series->fetchrow_array()) { + $sth_data_collected->execute($open_series_id); + my ($this_datacount) = $sth_data_collected->fetchrow_array(); + if ($this_datacount > $datacount) { + $datacount = $this_datacount; + $found_open_series_id = $open_series_id; + } + } + + if ($found_open_series_id) { + # Move along corrupted series data and correct it. The + # corruption consists of it being the number of all bugs + # instead of the number of non-open bugs, so we calculate the + # correct count by subtracting the number of open bugs. + # If there is no corresponding open-bugs count for some reason + # (shouldn't happen), we drop the data entry. + print " $broken_series_id..."; + $sth_select_broken_nonopen_data->execute($broken_series_id); + while (my $rowref = + $sth_select_broken_nonopen_data->fetchrow_arrayref()) { + my ($date, $broken_value) = @$rowref; + my ($openbugs_value) = + $dbh->selectrow_array($sth_select_open_data, undef, + $found_open_series_id, $date); + if (defined($openbugs_value)) { + $sth_fix_broken_nonopen_data->execute + ($broken_value - $openbugs_value, + $broken_series_id, $date); + } + else { + print "\nWARNING - During repairs of series " . + "$broken_series_id, the irreparable data\n" . + "entry for date $date was encountered and is " . + "being deleted.\n" . + "Continuing repairs..."; + $sth_delete_broken_nonopen_data->execute + ($broken_series_id, $date); + } + } + + # Fix the broken query so that it collects correct data in the + # future. + $nonopen_bugs_query =~ + s/^$broken_series_indicator/field0-0-0=resolution&type0-0-0=regexp&value0-0-0=./; + $sth_repair->execute($nonopen_bugs_query, $broken_series_id); + } + else { + print "\nWARNING - Series $broken_series_id was meant to\n" . + "collect non-open bug counts, but it has counted\n" . + "all bugs instead. It cannot be repaired\n" . + "automatically because no series that collected open\n" . + "bug counts was found. You'll probably want to delete\n" . + "or repair collected data for series $broken_series_id " . + "manually.\n" . + "Continuing repairs..."; + } + } + } + print " done.\n"; +} + # 2005-09-15 lance.larsh@oracle.com Bug 308717 if ($dbh->bz_column_info("series", "public")) { # PUBLIC is a reserved word in Oracle, so renaming the column diff --git a/editcomponents.cgi b/editcomponents.cgi index d514fb3bf..c65fd3167 100755 --- a/editcomponents.cgi +++ b/editcomponents.cgi @@ -185,23 +185,21 @@ if ($action eq 'new') { # For localisation reasons, we get the title of the queries from the # submitted form. my $open_name = $cgi->param('open_name'); - my $closed_name = $cgi->param('closed_name'); - my @openedstatuses = OpenStates(); - my $statuses = - join("&", map { "bug_status=" . url_quote($_) } @openedstatuses) . - $prodcomp; - my $resolved = "field0-0-0=resolution&type0-0-0=notequals&value0-0-0=---" . - $prodcomp; + my $nonopen_name = $cgi->param('nonopen_name'); + my $open_query = "field0-0-0=resolution&type0-0-0=notregexp&value0-0-0=." . + $prodcomp; + my $nonopen_query = "field0-0-0=resolution&type0-0-0=regexp&value0-0-0=." . + $prodcomp; # trick_taint is ok here, as these variables aren't used as a command # or in SQL unquoted trick_taint($open_name); - trick_taint($closed_name); - trick_taint($statuses); - trick_taint($resolved); + trick_taint($nonopen_name); + trick_taint($open_query); + trick_taint($nonopen_query); - push(@series, [$open_name, $statuses]); - push(@series, [$closed_name, $resolved]); + push(@series, [$open_name, $open_query]); + push(@series, [$nonopen_name, $nonopen_query]); foreach my $sdata (@series) { my $series = new Bugzilla::Series(undef, $product->name, diff --git a/template/en/default/admin/components/create.html.tmpl b/template/en/default/admin/components/create.html.tmpl index 769b61ca1..fcb57bb03 100644 --- a/template/en/default/admin/components/create.html.tmpl +++ b/template/en/default/admin/components/create.html.tmpl @@ -76,7 +76,7 @@ <input type="submit" value="Add"> <input type="hidden" name="action" value="new"> <input type="hidden" name='open_name' value='All Open'> - <input type="hidden" name='closed_name' value='All Closed'> + <input type="hidden" name='nonopen_name' value='All Closed'> <input type="hidden" name='product' value="[% product FILTER html %]"> </form> |