]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 300473: "All Closed" for components missing bug_status= in series.query.
authorwurblzap%gmail.com <>
Mon, 2 Jan 2006 05:19:21 +0000 (05:19 +0000)
committerwurblzap%gmail.com <>
Mon, 2 Jan 2006 05:19:21 +0000 (05:19 +0000)
Patch by Marc Schumann <wurblzap@gmail.com>,
r=wicked, a=justdave

checksetup.pl
editcomponents.cgi
template/en/default/admin/components/create.html.tmpl

index 1d445bec3035cf824fc0a459fcb248d80d5084c4..4d38c35533c79f14f0e56081b378ea66e74559c2 100755 (executable)
@@ -31,6 +31,7 @@
 #                 Erik Stambaugh <erik@dasbistro.com>
 #                 Dave Lawrence <dkl@redhat.com>
 #                 Max Kanat-Alexander <mkanat@bugzilla.org>
+#                 Marc Schumann <wurblzap@gmail.com>
 #
 #
 #
@@ -4045,6 +4046,128 @@ if (!exists $dbh->bz_column_info('whine_queries', 'title')->{DEFAULT}) {
                           NOTNULL => 1, DEFAULT => "''"});
 }
 
+# 2005-12-30 - 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";
+}
+
 
 # If you had to change the --TABLE-- definition in any way, then add your
 # differential change code *** A B O V E *** this comment.
index 6f8bc99f22efad1b068ab48f2b44a6ce9a62eaf5..1f42b04a72f8d6165fa8f91cf59b51167a26152e 100755 (executable)
@@ -332,23 +332,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, $component,
index 769b61ca15c5f01be0931f1e5dafb03563341f48..fcb57bb03cc92f8ddf0dc1a5ab555b897e6f31c5 100644 (file)
@@ -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>