our
$VERSION
=
'v0.999.999.2'
;
has
db_name
=> (
is
=>
'ro'
,
isa
=> Str,
required
=> 1,
);
has
coll_name
=> (
is
=>
'ro'
,
isa
=> Str,
required
=> 1,
);
has
filter
=> (
is
=>
'ro'
,
isa
=> IxHash,
coerce
=> 1,
required
=> 1,
);
has
update
=> (
is
=>
'ro'
,
isa
=> Any,
required
=> 1,
);
has
is_replace
=> (
is
=>
'ro'
,
isa
=> Bool,
required
=> 1,
);
has
multi
=> (
is
=>
'ro'
,
isa
=> Bool,
);
has
upsert
=> (
is
=>
'ro'
,
isa
=> Bool,
);
with
$_
for
qw/MongoDB::Role::_WriteOp MongoDB::Role::_UpdatePreEncoder/
;
sub
execute {
my
(
$self
,
$link
) =
@_
;
my
$update_op
= {
q
=>
$self
->filter,
u
=>
$self
->update,
multi
=> boolean(
$self
->multi),
upsert
=> boolean(
$self
->upsert),
};
my
$orig_op
= {
%$update_op
};
$update_op
->{u} =
$self
->_pre_encode(
$link
,
$update_op
->{u},
$self
->is_replace );
my
$res
=
$link
->accepts_wire_version(2)
?
$self
->_command_update(
$link
,
$update_op
,
$orig_op
)
:
$self
->_legacy_op_update(
$link
,
$update_op
,
$orig_op
);
$res
->assert;
return
$res
;
}
sub
_command_update {
my
(
$self
,
$link
,
$op_doc
,
$orig_doc
) =
@_
;
my
$cmd
= Tie::IxHash->new(
update
=>
$self
->coll_name,
updates
=> [
$op_doc
],
writeConcern
=>
$self
->write_concern->as_struct,
);
return
$self
->_send_write_command(
$link
,
$cmd
,
$orig_doc
,
"MongoDB::UpdateResult"
);
}
sub
_legacy_op_update {
my
(
$self
,
$link
,
$op_doc
,
$orig_doc
) =
@_
;
my
$flags
= {};
@{
$flags
}{
qw/upsert multi/
} = @{
$op_doc
}{
qw/upsert multi/
};
my
$ns
=
$self
->db_name .
"."
.
$self
->coll_name;
my
$query_bson
=
$self
->bson_codec->encode_one(
$op_doc
->{
q}, { invalid_chars => '' }
);
my
$update_bson
= ${
$op_doc
->{u} };
my
$op_bson
=
MongoDB::_Protocol::write_update(
$ns
,
$query_bson
,
$update_bson
,
$flags
);
return
$self
->_send_legacy_op_with_gle(
$link
,
$op_bson
,
$orig_doc
,
"MongoDB::UpdateResult"
);
}
sub
_parse_cmd {
my
(
$self
,
$res
) =
@_
;
return
(
matched_count
=>
$res
->{n} - @{
$res
->{upserted} || [] },
modified_count
=>
$res
->{nModified},
upserted_id
=>
$res
->{upserted} ?
$res
->{upserted}[0]{_id} :
undef
,
);
}
sub
_parse_gle {
my
(
$self
,
$res
,
$orig_doc
) =
@_
;
my
$upserted
=
$res
->{upserted};
if
(!
defined
(
$upserted
)
&&
exists
(
$res
->{updatedExisting} )
&& !
$res
->{updatedExisting}
&&
$res
->{n} == 1 )
{
$upserted
=
$orig_doc
->{u}->EXISTS(
"_id"
)
?
$orig_doc
->{u}->FETCH(
"_id"
)
:
$orig_doc
->{
q}->FETCH("_id");
}
return
(
matched_count
=> (
$upserted
? 0 :
$res
->{n}),
modified_count
=>
undef
,
upserted_id
=>
$upserted
,
);
}
1;