| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #  Copyright 2014 - present MongoDB, Inc. | 
| 2 |  |  |  |  |  |  | # | 
| 3 |  |  |  |  |  |  | #  Licensed under the Apache License, Version 2.0 (the "License"); | 
| 4 |  |  |  |  |  |  | #  you may not use this file except in compliance with the License. | 
| 5 |  |  |  |  |  |  | #  You may obtain a copy of the License at | 
| 6 |  |  |  |  |  |  | # | 
| 7 |  |  |  |  |  |  | #  http://www.apache.org/licenses/LICENSE-2.0 | 
| 8 |  |  |  |  |  |  | # | 
| 9 |  |  |  |  |  |  | #  Unless required by applicable law or agreed to in writing, software | 
| 10 |  |  |  |  |  |  | #  distributed under the License is distributed on an "AS IS" BASIS, | 
| 11 |  |  |  |  |  |  | #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 12 |  |  |  |  |  |  | #  See the License for the specific language governing permissions and | 
| 13 |  |  |  |  |  |  | #  limitations under the License. | 
| 14 |  |  |  |  |  |  |  | 
| 15 | 59 |  |  | 59 |  | 1156 | use strict; | 
|  | 59 |  |  |  |  | 141 |  | 
|  | 59 |  |  |  |  | 1805 |  | 
| 16 | 59 |  |  | 59 |  | 338 | use warnings; | 
|  | 59 |  |  |  |  | 147 |  | 
|  | 59 |  |  |  |  | 2006 |  | 
| 17 |  |  |  |  |  |  | package MongoDB::BulkWriteResult; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | # ABSTRACT: MongoDB bulk write result document | 
| 20 |  |  |  |  |  |  |  | 
| 21 | 59 |  |  | 59 |  | 347 | use version; | 
|  | 59 |  |  |  |  | 176 |  | 
|  | 59 |  |  |  |  | 352 |  | 
| 22 |  |  |  |  |  |  | our $VERSION = 'v2.2.0'; | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | # empty superclass for backcompatibility; add a variable to the | 
| 25 |  |  |  |  |  |  | # package namespace so Perl thinks it's a real package | 
| 26 |  |  |  |  |  |  | $MongoDB::WriteResult::VERSION = $VERSION; | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 59 |  |  | 59 |  | 5695 | use Moo; | 
|  | 59 |  |  |  |  | 140 |  | 
|  | 59 |  |  |  |  | 398 |  | 
| 29 | 59 |  |  | 59 |  | 18631 | use MongoDB::Error; | 
|  | 59 |  |  |  |  | 227 |  | 
|  | 59 |  |  |  |  | 6192 |  | 
| 30 | 59 |  |  | 59 |  | 450 | use MongoDB::_Constants; | 
|  | 59 |  |  |  |  | 152 |  | 
|  | 59 |  |  |  |  | 7669 |  | 
| 31 | 59 |  |  |  |  | 517 | use MongoDB::_Types qw( | 
| 32 |  |  |  |  |  |  | ArrayOfHashRef | 
| 33 |  |  |  |  |  |  | Numish | 
| 34 | 59 |  |  | 59 |  | 481 | ); | 
|  | 59 |  |  |  |  | 149 |  | 
| 35 | 59 |  |  |  |  | 438 | use Types::Standard qw( | 
| 36 |  |  |  |  |  |  | HashRef | 
| 37 |  |  |  |  |  |  | Undef | 
| 38 | 59 |  |  | 59 |  | 70180 | ); | 
|  | 59 |  |  |  |  | 167 |  | 
| 39 | 59 |  |  | 59 |  | 47256 | use namespace::clean; | 
|  | 59 |  |  |  |  | 147 |  | 
|  | 59 |  |  |  |  | 432 |  | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | # fake empty superclass for backcompat | 
| 42 |  |  |  |  |  |  | our @ISA; | 
| 43 |  |  |  |  |  |  | push @ISA, 'MongoDB::WriteResult'; | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | with $_ for qw( | 
| 46 |  |  |  |  |  |  | MongoDB::Role::_PrivateConstructor | 
| 47 |  |  |  |  |  |  | MongoDB::Role::_WriteResult | 
| 48 |  |  |  |  |  |  | ); | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | has [qw/upserted inserted/] => ( | 
| 51 |  |  |  |  |  |  | is       => 'ro', | 
| 52 |  |  |  |  |  |  | required => 1, | 
| 53 |  |  |  |  |  |  | isa      => ArrayOfHashRef, | 
| 54 |  |  |  |  |  |  | ); | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | has inserted_ids => ( | 
| 57 |  |  |  |  |  |  | is       => 'lazy', | 
| 58 |  |  |  |  |  |  | builder  => '_build_inserted_ids', | 
| 59 |  |  |  |  |  |  | init_arg => undef, | 
| 60 |  |  |  |  |  |  | isa      => HashRef, | 
| 61 |  |  |  |  |  |  | ); | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | sub _build_inserted_ids { | 
| 64 | 0 |  |  | 0 |  |  | my ($self) = @_; | 
| 65 | 0 |  |  |  |  |  | return { map { $_->{index}, $_->{_id} } @{ $self->inserted } }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | } | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | has upserted_ids => ( | 
| 69 |  |  |  |  |  |  | is       => 'lazy', | 
| 70 |  |  |  |  |  |  | builder  => '_build_upserted_ids', | 
| 71 |  |  |  |  |  |  | init_arg => undef, | 
| 72 |  |  |  |  |  |  | isa      => HashRef, | 
| 73 |  |  |  |  |  |  | ); | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | sub _build_upserted_ids { | 
| 76 | 0 |  |  | 0 |  |  | my ($self) = @_; | 
| 77 | 0 |  |  |  |  |  | return { map { $_->{index}, $_->{_id} } @{ $self->upserted } }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | } | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | for my $attr (qw/inserted_count upserted_count matched_count deleted_count/) { | 
| 81 |  |  |  |  |  |  | has $attr => ( | 
| 82 |  |  |  |  |  |  | is       => 'ro', | 
| 83 |  |  |  |  |  |  | writer   => "_set_$attr", | 
| 84 |  |  |  |  |  |  | required => 1, | 
| 85 |  |  |  |  |  |  | isa      => Numish, | 
| 86 |  |  |  |  |  |  | ); | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | # This should always be initialized either as a number or as undef so that | 
| 90 |  |  |  |  |  |  | # merges accumulate correctly.  It should be undef if talking to a server < 2.6 | 
| 91 |  |  |  |  |  |  | # or if talking to a mongos and not getting the field back from an update.  The | 
| 92 |  |  |  |  |  |  | # default is undef, which will be sticky and ensure this field stays undef. | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | has modified_count => ( | 
| 95 |  |  |  |  |  |  | is       => 'ro', | 
| 96 |  |  |  |  |  |  | writer   => '_set_modified_count', | 
| 97 |  |  |  |  |  |  | required => 1, | 
| 98 |  |  |  |  |  |  | isa      => (Numish|Undef), | 
| 99 |  |  |  |  |  |  | ); | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | sub has_modified_count { | 
| 102 | 0 |  |  | 0 | 0 |  | my ($self) = @_; | 
| 103 | 0 |  |  |  |  |  | return defined( $self->modified_count ); | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | has op_count => ( | 
| 107 |  |  |  |  |  |  | is       => 'ro', | 
| 108 |  |  |  |  |  |  | writer   => '_set_op_count', | 
| 109 |  |  |  |  |  |  | required => 1, | 
| 110 |  |  |  |  |  |  | isa      => Numish, | 
| 111 |  |  |  |  |  |  | ); | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | has batch_count => ( | 
| 114 |  |  |  |  |  |  | is       => 'ro', | 
| 115 |  |  |  |  |  |  | writer   => '_set_batch_count', | 
| 116 |  |  |  |  |  |  | required => 1, | 
| 117 |  |  |  |  |  |  | isa      => Numish, | 
| 118 |  |  |  |  |  |  | ); | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 121 |  |  |  |  |  |  | # emulate old API | 
| 122 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | my %OLD_API_ALIASING = ( | 
| 125 |  |  |  |  |  |  | nInserted                => 'inserted_count', | 
| 126 |  |  |  |  |  |  | nUpserted                => 'upserted_count', | 
| 127 |  |  |  |  |  |  | nMatched                 => 'matched_count', | 
| 128 |  |  |  |  |  |  | nModified                => 'modified_count', | 
| 129 |  |  |  |  |  |  | nRemoved                 => 'deleted_count', | 
| 130 |  |  |  |  |  |  | writeErrors              => 'write_errors', | 
| 131 |  |  |  |  |  |  | writeConcernErrors       => 'write_concern_errors', | 
| 132 |  |  |  |  |  |  | count_writeErrors        => 'count_write_errors', | 
| 133 |  |  |  |  |  |  | count_writeConcernErrors => 'count_write_concern_errors', | 
| 134 |  |  |  |  |  |  | ); | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | while ( my ( $old, $new ) = each %OLD_API_ALIASING ) { | 
| 137 | 59 |  |  | 59 |  | 75463 | no strict 'refs'; | 
|  | 59 |  |  |  |  | 156 |  | 
|  | 59 |  |  |  |  | 66864 |  | 
| 138 |  |  |  |  |  |  | *{$old} = \&{$new}; | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 142 |  |  |  |  |  |  | # private functions | 
| 143 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | # defines how an logical operation type gets mapped to a result | 
| 146 |  |  |  |  |  |  | # field from the actual command result | 
| 147 |  |  |  |  |  |  | my %op_map = ( | 
| 148 |  |  |  |  |  |  | insert => [ inserted_count => sub { $_[0]->{n} } ], | 
| 149 |  |  |  |  |  |  | delete => [ deleted_count  => sub { $_[0]->{n} } ], | 
| 150 |  |  |  |  |  |  | update => [ matched_count  => sub { $_[0]->{n} } ], | 
| 151 |  |  |  |  |  |  | upsert => [ matched_count  => sub { $_[0]->{n} - @{ $_[0]->{upserted} || [] } } ], | 
| 152 |  |  |  |  |  |  | ); | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | my @op_map_keys = sort keys %op_map; | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | sub _parse_cmd_result { | 
| 157 | 0 |  |  | 0 |  |  | my $class = shift; | 
| 158 | 0 | 0 |  |  |  |  | my $args = ref $_[0] eq 'HASH' ? shift : {@_}; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 0 | 0 |  |  |  |  | unless ( 2 == grep { exists $args->{$_} } qw/op result/ ) { | 
|  | 0 |  |  |  |  |  |  | 
| 161 | 0 |  |  |  |  |  | MongoDB::UsageError->throw("parse requires 'op' and 'result' arguments"); | 
| 162 |  |  |  |  |  |  | } | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | my ( $op, $op_count, $batch_count, $result, $cmd_doc ) = | 
| 165 | 0 |  |  |  |  |  | @{$args}{qw/op op_count batch_count result cmd_doc/}; | 
|  | 0 |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | $result = $result->output | 
| 168 | 0 | 0 |  |  |  |  | if eval { $result->isa("MongoDB::CommandResult") }; | 
|  | 0 |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | MongoDB::UsageError->throw("op argument to parse must be one of: @op_map_keys") | 
| 171 | 0 | 0 |  |  |  |  | unless grep { $op eq $_ } @op_map_keys; | 
|  | 0 |  |  |  |  |  |  | 
| 172 | 0 | 0 |  |  |  |  | MongoDB::UsageError->throw("results argument to parse must be a hash reference") | 
| 173 |  |  |  |  |  |  | unless ref $result eq 'HASH'; | 
| 174 |  |  |  |  |  |  |  | 
| 175 | 0 | 0 | 0 |  |  |  | my %attrs = ( | 
| 176 |  |  |  |  |  |  | batch_count => $batch_count || 1, | 
| 177 |  |  |  |  |  |  | $op_count ? ( op_count => $op_count ) : (), | 
| 178 |  |  |  |  |  |  | inserted_count => 0, | 
| 179 |  |  |  |  |  |  | upserted_count => 0, | 
| 180 |  |  |  |  |  |  | matched_count  => 0, | 
| 181 |  |  |  |  |  |  | deleted_count  => 0, | 
| 182 |  |  |  |  |  |  | upserted       => [], | 
| 183 |  |  |  |  |  |  | inserted       => [], | 
| 184 |  |  |  |  |  |  | ); | 
| 185 |  |  |  |  |  |  |  | 
| 186 | 0 | 0 |  |  |  |  | $attrs{write_errors} = $result->{writeErrors} ? $result->{writeErrors} : []; | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | # rename writeConcernError -> write_concern_errors; coerce it to arrayref | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | $attrs{write_concern_errors} = | 
| 191 | 0 | 0 |  |  |  |  | $result->{writeConcernError} ? [ $result->{writeConcernError} ] : []; | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | # if we have upserts, change type to calculate differently | 
| 194 | 0 | 0 |  |  |  |  | if ( $result->{upserted} ) { | 
| 195 | 0 |  |  |  |  |  | $op                      = 'upsert'; | 
| 196 | 0 |  |  |  |  |  | $attrs{upserted}       = $result->{upserted}; | 
| 197 | 0 |  |  |  |  |  | $attrs{upserted_count} = @{ $result->{upserted} }; | 
|  | 0 |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | } | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | # recover _ids from documents | 
| 201 | 0 | 0 | 0 |  |  |  | if ( exists($result->{n}) && $op eq 'insert' ) { | 
| 202 | 0 |  |  |  |  |  | my @pairs; | 
| 203 | 0 |  |  |  |  |  | my $docs = {@$cmd_doc}->{documents}; | 
| 204 | 0 |  |  |  |  |  | for my $i ( 0 .. $result->{n}-1 ) { | 
| 205 | 0 |  |  |  |  |  | push @pairs, { index => $i, _id => $docs->[$i]{metadata}{_id} }; | 
| 206 |  |  |  |  |  |  | } | 
| 207 | 0 |  |  |  |  |  | $attrs{inserted} = \@pairs; | 
| 208 |  |  |  |  |  |  | } | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | # change 'n' into an op-specific count | 
| 211 | 0 | 0 |  |  |  |  | if ( exists $result->{n} ) { | 
| 212 | 0 |  |  |  |  |  | my ( $key, $builder ) = @{ $op_map{$op} }; | 
|  | 0 |  |  |  |  |  |  | 
| 213 | 0 |  |  |  |  |  | $attrs{$key} = $builder->($result); | 
| 214 |  |  |  |  |  |  | } | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | # for an update/upsert we want the exact response whether numeric or undef | 
| 217 |  |  |  |  |  |  | # so that new undef responses become sticky; for all other updates, we | 
| 218 |  |  |  |  |  |  | # consider it 0 and let it get sorted out in the merging | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | $attrs{modified_count} = ( $op eq 'update' || $op eq 'upsert' ) ? | 
| 221 | 0 | 0 | 0 |  |  |  | $result->{nModified} : 0; | 
| 222 |  |  |  |  |  |  |  | 
| 223 | 0 |  |  |  |  |  | return $class->_new(%attrs); | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | # these are for single results only | 
| 227 |  |  |  |  |  |  | sub _parse_write_op { | 
| 228 | 0 |  |  | 0 |  |  | my $class = shift; | 
| 229 | 0 |  |  |  |  |  | my $op    = shift; | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 0 |  |  |  |  |  | my %attrs = ( | 
| 232 |  |  |  |  |  |  | batch_count  => 1, | 
| 233 |  |  |  |  |  |  | op_count     => 1, | 
| 234 |  |  |  |  |  |  | write_errors => $op->write_errors, | 
| 235 |  |  |  |  |  |  | write_concern_errors => $op->write_concern_errors, | 
| 236 |  |  |  |  |  |  | inserted_count       => 0, | 
| 237 |  |  |  |  |  |  | upserted_count       => 0, | 
| 238 |  |  |  |  |  |  | matched_count        => 0, | 
| 239 |  |  |  |  |  |  | modified_count       => undef, | 
| 240 |  |  |  |  |  |  | deleted_count        => 0, | 
| 241 |  |  |  |  |  |  | upserted             => [], | 
| 242 |  |  |  |  |  |  | inserted             => [], | 
| 243 |  |  |  |  |  |  | ); | 
| 244 |  |  |  |  |  |  |  | 
| 245 | 0 |  |  |  |  |  | my $has_write_error = @{ $attrs{write_errors} }; | 
|  | 0 |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | # parse by type | 
| 248 | 0 |  |  |  |  |  | my $type = ref($op); | 
| 249 | 0 | 0 |  |  |  |  | if ( $type eq 'MongoDB::InsertOneResult' ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 250 | 0 | 0 |  |  |  |  | if ( $has_write_error ) { | 
| 251 | 0 |  |  |  |  |  | $attrs{inserted_count} = 0; | 
| 252 | 0 |  |  |  |  |  | $attrs{inserted} = []; | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  | else { | 
| 255 | 0 |  |  |  |  |  | $attrs{inserted_count} = 1; | 
| 256 | 0 |  |  |  |  |  | $attrs{inserted} = [ { index => 0, _id => $op->inserted_id } ]; | 
| 257 |  |  |  |  |  |  | } | 
| 258 |  |  |  |  |  |  | } | 
| 259 |  |  |  |  |  |  | elsif ( $type eq 'MongoDB::DeleteResult' ) { | 
| 260 | 0 |  |  |  |  |  | $attrs{deleted_count} = $op->deleted_count; | 
| 261 |  |  |  |  |  |  | } | 
| 262 |  |  |  |  |  |  | elsif ( $type eq 'MongoDB::UpdateResult' ) { | 
| 263 | 0 | 0 |  |  |  |  | if ( defined $op->upserted_id ) { | 
| 264 | 0 |  |  |  |  |  | my $upsert = { index => 0, _id => $op->upserted_id }; | 
| 265 | 0 |  |  |  |  |  | $attrs{upserted}       = [$upsert]; | 
| 266 | 0 |  |  |  |  |  | $attrs{upserted_count} = 1; | 
| 267 |  |  |  |  |  |  | # modified_count *must* always be defined for 2.6+ servers | 
| 268 |  |  |  |  |  |  | # matched_count is here for clarity and consistency | 
| 269 | 0 |  |  |  |  |  | $attrs{matched_count}  = 0; | 
| 270 | 0 |  |  |  |  |  | $attrs{modified_count} = 0; | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  | else { | 
| 273 | 0 |  |  |  |  |  | $attrs{matched_count}  = $op->matched_count; | 
| 274 | 0 |  |  |  |  |  | $attrs{modified_count} = $op->modified_count; | 
| 275 |  |  |  |  |  |  | } | 
| 276 |  |  |  |  |  |  | } | 
| 277 |  |  |  |  |  |  | else { | 
| 278 | 0 |  |  |  |  |  | MongoDB::InternalError->throw("can't parse unknown result class $op"); | 
| 279 |  |  |  |  |  |  | } | 
| 280 |  |  |  |  |  |  |  | 
| 281 | 0 |  |  |  |  |  | return $class->_new(%attrs); | 
| 282 |  |  |  |  |  |  | } | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | sub _merge_result { | 
| 285 | 0 |  |  | 0 |  |  | my ( $self, $result ) = @_; | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | # Add simple counters | 
| 288 | 0 |  |  |  |  |  | for my $attr (qw/inserted_count upserted_count matched_count deleted_count/) { | 
| 289 | 0 |  |  |  |  |  | my $setter = "_set_$attr"; | 
| 290 | 0 |  |  |  |  |  | $self->$setter( $self->$attr + $result->$attr ); | 
| 291 |  |  |  |  |  |  | } | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | # If modified_count is defined in both results we're merging, then we're | 
| 294 |  |  |  |  |  |  | # talking to a 2.6+ mongod or we're talking to a 2.6+ mongos and have only | 
| 295 |  |  |  |  |  |  | # seen responses with modified_count.  In any other case, we set | 
| 296 |  |  |  |  |  |  | # modified_count to undef, which then becomes "sticky" | 
| 297 |  |  |  |  |  |  |  | 
| 298 | 0 | 0 | 0 |  |  |  | if ( defined $self->modified_count && defined $result->modified_count ) { | 
| 299 | 0 |  |  |  |  |  | $self->_set_modified_count( $self->modified_count + $result->modified_count ); | 
| 300 |  |  |  |  |  |  | } | 
| 301 |  |  |  |  |  |  | else { | 
| 302 | 0 |  |  |  |  |  | $self->_set_modified_count(undef); | 
| 303 |  |  |  |  |  |  | } | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | # Append error and upsert docs, but modify index based on op count | 
| 306 | 0 |  |  |  |  |  | my $op_count = $self->op_count; | 
| 307 | 0 |  |  |  |  |  | for my $attr (qw/write_errors upserted inserted/) { | 
| 308 | 0 |  |  |  |  |  | for my $doc ( @{ $result->$attr } ) { | 
|  | 0 |  |  |  |  |  |  | 
| 309 | 0 |  |  |  |  |  | $doc->{index} += $op_count; | 
| 310 |  |  |  |  |  |  | } | 
| 311 | 0 |  |  |  |  |  | push @{ $self->$attr }, @{ $result->$attr }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | } | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | # Append write concern errors without modification (they have no index) | 
| 315 | 0 |  |  |  |  |  | push @{ $self->write_concern_errors }, @{ $result->write_concern_errors }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 0 |  |  |  |  |  | $self->_set_op_count( $op_count + $result->op_count ); | 
| 318 | 0 |  |  |  |  |  | $self->_set_batch_count( $self->batch_count + $result->batch_count ); | 
| 319 |  |  |  |  |  |  |  | 
| 320 | 0 |  |  |  |  |  | return 1; | 
| 321 |  |  |  |  |  |  | } | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | 1; | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | __END__ |