From 678ad6b0f33fbd05da033ce04f14e14951aa7a9e Mon Sep 17 00:00:00 2001 From: Dave Lawrence Date: Tue, 7 Jan 2014 00:10:18 -0500 Subject: Bug 956052 - backport upstream bug 945535 to bmo/4.2 for performance improvement in bugs with large number of attachments --- Bugzilla/Attachment.pm | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/Bugzilla/Attachment.pm b/Bugzilla/Attachment.pm index 1a12e65b1..bb0f83aba 100644 --- a/Bugzilla/Attachment.pm +++ b/Bugzilla/Attachment.pm @@ -62,6 +62,7 @@ use Bugzilla::Hook; use File::Copy; use List::Util qw(max); +use Storable qw(dclone); use base qw(Bugzilla::Object); @@ -635,12 +636,12 @@ sub _check_is_private { =over -=item C +=item C Description: retrieves and returns the attachments the currently logged in user can view for the given bug. -Params: C<$bug_id> - integer - the ID of the bug for which +Params: C<$bug> - Bugzilla::Bug object - the bug for which to retrieve and return attachments. Returns: a reference to an array of attachment objects. @@ -648,14 +649,14 @@ Returns: a reference to an array of attachment objects. =cut sub get_attachments_by_bug { - my ($class, $bug_id, $vars) = @_; + my ($class, $bug, $vars) = @_; my $user = Bugzilla->user; my $dbh = Bugzilla->dbh; # By default, private attachments are not accessible, unless the user # is in the insider group or submitted the attachment. my $and_restriction = ''; - my @values = ($bug_id); + my @values = ($bug->id); unless ($user->is_insider) { $and_restriction = 'AND (isprivate = 0 OR submitter_id = ?)'; @@ -672,17 +673,22 @@ sub get_attachments_by_bug { # attachment listed here, we collect all the data at once and # populate $attachment->{flags} ourselves. if ($vars->{preload}) { - $_->{flags} = [] foreach @$attachments; - my %att = map { $_->id => $_ } @$attachments; + # Preload flag types and flags + my $vars = { target_type => 'attachment', + product_id => $bug->product_id, + component_id => $bug->component_id, + attach_id => $attach_ids }; + my $flag_types = Bugzilla::Flag->_flag_types($vars); - my $flags = Bugzilla::Flag->match({ bug_id => $bug_id, - target_type => 'attachment' }); - - # Exclude flags for private attachments you cannot see. - @$flags = grep {exists $att{$_->attach_id}} @$flags; - - push(@{$att{$_->attach_id}->{flags}}, $_) foreach @$flags; - $attachments = [sort {$a->id <=> $b->id} values %att]; + foreach my $attachment (@$attachments) { + $attachment->{flag_types} = []; + my $new_types = dclone($flag_types); + foreach my $new_type (@$new_types) { + $new_type->{flags} = [ grep($_->attach_id == $attachment->id, + @{ $new_type->{flags} }) ]; + push(@{ $attachment->{flag_types} }, $new_type); + } + } # Preload attachers. my %user_ids = map { $_->{submitter_id} => 1 } @$attachments; @@ -697,7 +703,7 @@ sub get_attachments_by_bug { $dbh->selectall_hashref('SELECT attach_id, LENGTH(thedata) AS datasize FROM attachments LEFT JOIN attach_data ON attach_id = id WHERE bug_id = ?', - 'attach_id', undef, $bug_id); + 'attach_id', undef, $bug->id); # Force the size of attachments not in the DB to be recalculated. $_->{datasize} = $sizes->{$_->id}->{datasize} || undef foreach @$attachments; -- cgit v1.2.3-24-g4f1b