]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 408172: [Oracle] Bug lists longer than 1000 bugs fail
authormkanat%bugzilla.org <>
Fri, 18 Jan 2008 21:56:53 +0000 (21:56 +0000)
committermkanat%bugzilla.org <>
Fri, 18 Jan 2008 21:56:53 +0000 (21:56 +0000)
Patch By Xiaoou Wu <xiaoou.wu@oracle.com> r=mkanat, a=mkanat

Bugzilla/Attachment.pm
Bugzilla/Bug.pm
Bugzilla/DB.pm
Bugzilla/DB/Oracle.pm
Bugzilla/Flag.pm
Bugzilla/Milestone.pm
Bugzilla/Object.pm
Bugzilla/Search.pm
buglist.cgi
process_bug.cgi

index f853cff049b5a0dc41ea28f89ad53a81bf308644..dafdf70ad54b127a12624030012f8b979a5359c4 100644 (file)
@@ -99,13 +99,14 @@ sub _retrieve {
         'attachments.isprivate AS isprivate'
     );
     my $columns = join(", ", @columns);
-
-    my $records = Bugzilla->dbh->selectall_arrayref("SELECT $columns
-                                                     FROM attachments
-                                                     WHERE attach_id IN (" .
-                                                     join(",", @$ids) . ")
-                                                     ORDER BY attach_id",
-                                                    { Slice => {} });
+    my $dbh = Bugzilla->dbh;
+    my $records = $dbh->selectall_arrayref(
+                      "SELECT $columns
+                         FROM attachments
+                        WHERE " 
+                       . Bugzilla->dbh->sql_in('attach_id', $ids) 
+                 . " ORDER BY attach_id",
+                       { Slice => {} });
     return $records;
 }
 
index 20e87c25c5bc3eff82180d41efcd300457919ce1..227cb1f6e81a038cd96eb4cb252a7a2db7e467cf 100755 (executable)
@@ -635,8 +635,8 @@ sub update_cc {
     my ($removed, $added) = diff_arrays(\@old_cc, \@new_cc);
     
     if (scalar @$removed) {
-        $dbh->do('DELETE FROM cc WHERE bug_id = ? AND who IN (' .
-                  join(',', @$removed) . ')', undef, $self->id);
+        $dbh->do('DELETE FROM cc WHERE bug_id = ? AND 
+                 . $dbh->sql_in('who', $removed), undef, $self->id);
     }
     foreach my $user_id (@$added) {
         $dbh->do('INSERT INTO cc (bug_id, who) VALUES (?,?)',
@@ -722,8 +722,8 @@ sub update_keywords {
     my ($removed, $added) = diff_arrays(\@old_ids, \@new_ids);
 
     if (scalar @$removed) {
-        $dbh->do('DELETE FROM keywords WHERE bug_id = ? AND keywordid IN ('
-                 . join(',', @$removed) . ')', undef, $self->id);
+        $dbh->do('DELETE FROM keywords WHERE bug_id = ? AND 
+                 . $dbh->sql_in('keywordid', $removed), undef, $self->id);
     }
     foreach my $keyword_id (@$added) {
         $dbh->do('INSERT INTO keywords (bug_id, keywordid) VALUES (?,?)',
@@ -798,8 +798,8 @@ sub remove_from_db {
                                   WHERE bug_id = ?", undef, $bug_id);
 
     if (scalar(@$attach_ids)) {
-        $dbh->do("DELETE FROM attach_data WHERE id IN (" .
-                 join(",", @$attach_ids) . ")");
+        $dbh->do("DELETE FROM attach_data WHERE 
+                 . $dbh->sql_in('id', $attach_ids));
     }
 
     # Several of the previous tables also depend on attach_id.
@@ -3018,7 +3018,7 @@ sub CountOpenDependencies {
     my $sth = $dbh->prepare(
           "SELECT blocked, COUNT(bug_status) " .
             "FROM bugs, dependencies " .
-           "WHERE blocked IN (" . (join "," , @bug_list) . ") " .
+           "WHERE " . $dbh->sql_in('blocked', \@bug_list) .
              "AND bug_id = dependson " .
              "AND bug_status IN (" . join(', ', map {$dbh->quote($_)} BUG_STATE_OPEN)  . ") " .
           $dbh->sql_group_by('blocked'));
index 40cd3e3a12b19d902cacc23623436b54bf2c9ce5..2a71bcd751fb68acbff82cb7c9b9644b8911be18 100644 (file)
@@ -391,6 +391,11 @@ sub sql_string_concat {
     return '(' . join(' || ', @params) . ')';
 }
 
+sub sql_in {
+    my ($self, $column_name, $in_list_ref) = @_;
+    return " $column_name IN (" . join(',', @$in_list_ref) . ") ";
+}
+
 sub sql_fulltext_search {
     my ($self, $column, $text) = @_;
 
@@ -1918,6 +1923,32 @@ will not be usually used unless it was created as LOWER(column).
 
 =back
 
+=item C<sql_in>
+
+=over
+
+=item B<Description>
+
+Returns SQL syntax for the C<IN ()> operator. 
+
+Only necessary where an C<IN> clause can have more than 1000 items.
+
+=item B<Params>
+
+=over
+
+=item C<$column_name> - Column name (e.g. C<bug_id>)
+
+=item C<$in_list_ref> - an arrayref containing values for C<IN ()>
+
+=back
+
+=item B<Returns>
+
+Formatted SQL for the C<IN> operator.
+
+=back
+
 =item C<bz_lock_tables>
 
 =over
index f89a72ab032a00fcc448dc569b38a1a39731cede..1695500873876beb0d57eb91c5ae6c7a107a6db6 100644 (file)
@@ -165,6 +165,22 @@ sub sql_position {
     my ($self, $fragment, $text) = @_;
     return "INSTR($text, $fragment)";
 }
+
+sub sql_in {
+    my ($self, $column_name, $in_list_ref) = @_;
+    my @in_list = @$in_list_ref;
+    return $self->SUPER::sql_in($column_name, $in_list_ref) if $#in_list < 1000;
+    my @in_str;
+    while (@in_list) {
+        my $length = $#in_list + 1;
+        my $splice = $length > 1000 ? 1000 : $length;
+        my @sub_in_list = splice(@in_list, 0, $splice);
+        push(@in_str, 
+             $self->SUPER::sql_in($column_name, \@sub_in_list)); 
+    }
+    return "( " . join(" OR ", @in_str) . " )";
+}
+
 sub _fix_empty {
     my ($string) = @_;
     $string = '' if $string eq EMPTY_STRING;
index 3a4d03df609ba7397ce5c24e58ef65e580f062fe..adc92cfd4404e9d5ddc210d47a88f437f4d22a6b 100644 (file)
@@ -295,11 +295,12 @@ sub validate {
         my $not = ($attach_id) ? "" : "NOT";
 
         my $invalid_data =
-            $dbh->selectrow_array("SELECT 1 FROM flags
-                                   WHERE id IN (" . join(',', @flag_ids) . ")
-                                   AND ($field != ? OR attach_id IS $not NULL) " .
-                                   $dbh->sql_limit(1),
-                                   undef, $field_id);
+            $dbh->selectrow_array(
+                      "SELECT 1 FROM flags
+                        WHERE " 
+                       . $dbh->sql_in('id', \@flag_ids) 
+                       . " AND ($field != ? OR attach_id IS $not NULL) "
+                       . $dbh->sql_limit(1), undef, $field_id);
 
         if ($invalid_data) {
             ThrowCodeError('invalid_flag_association',
index dda04c4f8e7489ba8625d2fb3b56244b66edb902..fc44cf1afd71940f3d0561b0468ef211cfd60dbf 100644 (file)
@@ -144,7 +144,7 @@ sub remove_from_db {
         my $timestamp = $dbh->selectrow_array('SELECT NOW()');
 
         $dbh->do('UPDATE bugs SET target_milestone = ?, delta_ts = ?
-                  WHERE bug_id IN (' . join(', ', @$bug_ids) . ')',
+                   WHERE ' . $dbh->sql_in('bug_id', $bug_ids),
                  undef, ($self->product->default_milestone, $timestamp));
 
         require Bugzilla::Bug;
index 2cf671bc2ce4bd7eaaa5ace7c09437abc6a9306a..23a88855f6ccc147079e13581ee84d7a53eab8b3 100644 (file)
@@ -145,8 +145,9 @@ sub new_from_list {
             push(@detainted_ids, $id);
         }
         $objects = $dbh->selectall_arrayref(
-            "SELECT $columns FROM $table WHERE $id_field IN (" 
-            . join(',', @detainted_ids) . ") ORDER BY $order", {Slice=>{}});
+            "SELECT $columns FROM $table WHERE " 
+            . $dbh->sql_in($id_field, \@detainted_ids) 
+            . "ORDER BY $order", {Slice=>{}});
     } else {
         return [];
     }
index b30f749118e2f68012c809d22614072a05ad8582..8fa27143b98bfe1f64ccf4a39325fcbd44623928 100644 (file)
@@ -352,8 +352,8 @@ sub init {
                     $extra .= " AND actcheck.added = $sql_chvalue";
                 }
                 push(@supptables, "LEFT JOIN bugs_activity AS actcheck " .
-                                  "ON $extra AND actcheck.fieldid IN (" .
-                                  join(",", @actlist) . ")");
+                                  "ON $extra AND 
+                                 . $dbh->sql_in('actcheck.fieldid', \@actlist));
             }
 
             # Now that we're done using @list to determine if there are any
@@ -1082,7 +1082,7 @@ sub init {
                  push(@list, $q);
              }
              if (@list) {
-                 $term = "$ff IN (" . join (',', @list) . ")";
+                 $term = $dbh->sql_in($ff, \@list);
              }
          },
          ",anywordssubstr" => sub {
@@ -1519,7 +1519,7 @@ sub build_subselect {
     my $dbh = Bugzilla->dbh;
     my $list = $dbh->selectcol_arrayref($q);
     return "1=2" unless @$list; # Could use boolean type on dbs which support it
-    return "$outer IN (" . join(',', @$list) . ")";
+    return $dbh->sql_in($outer, $list);
 }
 
 sub GetByWordList {
index 89b164dd8d8b9bfc043a80c5371f515661cb35b0..493f4b3a986a2bcb47c8b912693adcbb61adb4e0 100755 (executable)
@@ -1084,7 +1084,7 @@ if (@bugidlist) {
      "LEFT JOIN group_control_map " .
             "ON group_control_map.product_id = bugs.product_id " .
            "AND group_control_map.group_id = bug_group_map.group_id " .
-         "WHERE bugs.bug_id IN (" . join(',',@bugidlist) . ") " .
+         "WHERE " . $dbh->sql_in('bugs.bug_id', \@bugidlist) . 
             $dbh->sql_group_by('bugs.bug_id'));
     $sth->execute();
     while (my ($bug_id, $min_membercontrol) = $sth->fetchrow_array()) {
@@ -1161,19 +1161,23 @@ if ($dotweak) {
     my @bug_statuses = map {$dbh->quote($_)} keys %$bugstatuses;
     my $bug_status_ids =
       $dbh->selectcol_arrayref('SELECT id FROM bug_status
-                                WHERE value IN (' . join(', ', @bug_statuses) .')');
+                               WHERE ' . $dbh->sql_in('value', \@bug_statuses));
 
     # This query collects new statuses which are common to all current bug statuses.
     # It also accepts transitions where the bug status doesn't change.
     $bug_status_ids =
-      $dbh->selectcol_arrayref('SELECT DISTINCT new_status
-                                FROM status_workflow sw1
-                                WHERE NOT EXISTS (SELECT * FROM status_workflow sw2
-                                                  WHERE sw2.old_status != sw1.new_status
-                                                  AND sw2.old_status IN (' . join(', ', @$bug_status_ids) . ')
-                                                  AND NOT EXISTS (SELECT * FROM status_workflow sw3
-                                                                  WHERE sw3.new_status = sw1.new_status
-                                                                  AND sw3.old_status = sw2.old_status))');
+      $dbh->selectcol_arrayref(
+            'SELECT DISTINCT new_status
+               FROM status_workflow sw1
+              WHERE NOT EXISTS 
+                   (SELECT * FROM status_workflow sw2
+                     WHERE sw2.old_status != sw1.new_status 
+                           AND '
+                         . $dbh->sql_in('sw2.old_status', $bug_status_ids)
+                         . ' AND NOT EXISTS 
+                           (SELECT * FROM status_workflow sw3
+                             WHERE sw3.new_status = sw1.new_status
+                                   AND sw3.old_status = sw2.old_status))');
 
     $vars->{'current_bug_statuses'} = [keys %$bugstatuses];
     $vars->{'new_bug_statuses'} = Bugzilla::Status->new_from_list($bug_status_ids);
index 71be091685aa33cefe126975ab1f92a611185627..35d41ee0031005332ac4355d25c2d3c2ce53e919 100755 (executable)
@@ -327,11 +327,9 @@ if ($cgi->param('product') ne $cgi->param('dontchange')) {
     $product = Bugzilla::Product::check_product(scalar $cgi->param('product'));
     @newprod_ids = ($product->id);
 } else {
-    @newprod_ids = @{$dbh->selectcol_arrayref("SELECT DISTINCT product_id
-                                               FROM bugs 
-                                               WHERE bug_id IN (" .
-                                                   join(',', @idlist) . 
-                                               ")")};
+    @newprod_ids = @{$dbh->selectcol_arrayref(
+        "SELECT DISTINCT product_id FROM bugs WHERE " 
+        . $dbh->sql_in('bug_id', \@idlist))};
     if (scalar(@newprod_ids) == 1) {
         $product = new Bugzilla::Product($newprod_ids[0]);
     }