From 9946a759d339f48367b308697fc9f725131c1dd4 Mon Sep 17 00:00:00 2001 From: Thomas Bloor Date: Wed, 3 Jan 2018 16:47:43 +0000 Subject: [PATCH 1/4] PERL-787 Updated various CRUD data for testing --- t/data/CRUD/README.rst | 23 +++----- t/data/CRUD/read/aggregate-collation.json | 2 +- t/data/CRUD/read/aggregate-out.json | 53 ++++++++++++++++++- t/data/CRUD/read/aggregate-out.yml | 21 ++++++++ t/data/CRUD/read/aggregate.json | 2 +- t/data/CRUD/read/count-collation.json | 2 +- t/data/CRUD/read/count.json | 2 +- t/data/CRUD/read/distinct-collation.json | 2 +- t/data/CRUD/read/distinct.json | 2 +- t/data/CRUD/read/find-collation.json | 2 +- t/data/CRUD/read/find.json | 2 +- t/data/CRUD/write/deleteMany-collation.json | 2 +- t/data/CRUD/write/deleteMany.json | 2 +- t/data/CRUD/write/deleteOne-collation.json | 2 +- t/data/CRUD/write/deleteOne.json | 2 +- .../write/findOneAndDelete-collation.json | 2 +- t/data/CRUD/write/findOneAndDelete.json | 2 +- .../write/findOneAndReplace-collation.json | 2 +- .../CRUD/write/findOneAndReplace-upsert.json | 2 +- t/data/CRUD/write/findOneAndReplace.json | 2 +- .../write/findOneAndUpdate-collation.json | 2 +- t/data/CRUD/write/findOneAndUpdate.json | 2 +- t/data/CRUD/write/insertMany.json | 2 +- t/data/CRUD/write/insertOne.json | 2 +- t/data/CRUD/write/replaceOne-collation.json | 2 +- t/data/CRUD/write/replaceOne.json | 2 +- t/data/CRUD/write/updateMany-collation.json | 2 +- t/data/CRUD/write/updateMany.json | 2 +- t/data/CRUD/write/updateOne-collation.json | 2 +- t/data/CRUD/write/updateOne.json | 2 +- 30 files changed, 107 insertions(+), 44 deletions(-) diff --git a/t/data/CRUD/README.rst b/t/data/CRUD/README.rst index 3faed8bb..d52f5f6a 100644 --- a/t/data/CRUD/README.rst +++ b/t/data/CRUD/README.rst @@ -12,18 +12,6 @@ define and setup. Therefore, these YAML tests are in no way a replacement for more thorough testing. However, they can provide an initial verification of your implementation. -Converting to JSON -================== - -The tests are written in YAML because it is easier for humans to write and read, -and because YAML includes a standard comment format. A JSONified version of each -YAML file is included in this repository. Whenever a YAML file is modified, the -corresponding JSON file should be regenerated. One method to convert to JSON is -using `yamljs `_:: - - npm install -g yamljs - yaml2json -s -p -r . - Version ======= @@ -69,7 +57,11 @@ Each YAML file has the following keys: the collection after the operation is executed. This will have some or all of the following fields: - - ``result``: The return value from the operation. + - ``result``: The return value from the operation. Note that some tests + specify an ``upsertedCount`` field when the server does not provide + one in the result document. In these cases, an ``upsertedCount`` field + with a value of 0 should be manually added to the document received + from the server to facilitate comparison. - ``collection``: @@ -84,6 +76,5 @@ Use as integration tests Running these as integration tests will require a running mongod server. Each of these tests is valid against a standalone mongod, a replica set, and a sharded -system for server version 3.0.0. Many of them will run against 2.4 and 2.6, but -some will require conditional code. For instance, ``$out`` is not supported in -an aggregation pipeline in server 2.4, so that test must be skipped. +system for server version 3.0 and later. Many of them will run against 2.6, but +some will require conditional code. diff --git a/t/data/CRUD/read/aggregate-collation.json b/t/data/CRUD/read/aggregate-collation.json index 903a5834..85662a44 100644 --- a/t/data/CRUD/read/aggregate-collation.json +++ b/t/data/CRUD/read/aggregate-collation.json @@ -35,4 +35,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/aggregate-out.json b/t/data/CRUD/read/aggregate-out.json index cbc8ca47..205cf765 100644 --- a/t/data/CRUD/read/aggregate-out.json +++ b/t/data/CRUD/read/aggregate-out.json @@ -65,6 +65,57 @@ ] } } + }, + { + "description": "Aggregate with $out and batch size of 0", + "operation": { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$sort": { + "x": 1 + } + }, + { + "$match": { + "_id": { + "$gt": 1 + } + } + }, + { + "$out": "other_test_collection" + } + ], + "batchSize": 0 + } + }, + "outcome": { + "result": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection": { + "name": "other_test_collection", + "data": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/aggregate-out.yml b/t/data/CRUD/read/aggregate-out.yml index 82823867..747127c2 100644 --- a/t/data/CRUD/read/aggregate-out.yml +++ b/t/data/CRUD/read/aggregate-out.yml @@ -26,3 +26,24 @@ tests: data: - {_id: 2, x: 22} - {_id: 3, x: 33} + - + description: "Aggregate with $out and batch size of 0" + operation: + name: aggregate + arguments: + pipeline: + - $sort: {x: 1} + - $match: + _id: {$gt: 1} + - $out: "other_test_collection" + batchSize: 0 + + outcome: + result: + - {_id: 2, x: 22} + - {_id: 3, x: 33} + collection: + name: "other_test_collection" + data: + - {_id: 2, x: 22} + - {_id: 3, x: 33} diff --git a/t/data/CRUD/read/aggregate.json b/t/data/CRUD/read/aggregate.json index 479fcb9b..797a9223 100644 --- a/t/data/CRUD/read/aggregate.json +++ b/t/data/CRUD/read/aggregate.json @@ -50,4 +50,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/count-collation.json b/t/data/CRUD/read/count-collation.json index 46212094..6ea9ab81 100644 --- a/t/data/CRUD/read/count-collation.json +++ b/t/data/CRUD/read/count-collation.json @@ -26,4 +26,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/count.json b/t/data/CRUD/read/count.json index 85c17e11..5020771d 100644 --- a/t/data/CRUD/read/count.json +++ b/t/data/CRUD/read/count.json @@ -57,4 +57,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/distinct-collation.json b/t/data/CRUD/read/distinct-collation.json index 4d688cc3..0af0c67c 100644 --- a/t/data/CRUD/read/distinct-collation.json +++ b/t/data/CRUD/read/distinct-collation.json @@ -30,4 +30,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/distinct.json b/t/data/CRUD/read/distinct.json index 408d8a48..a57ee36a 100644 --- a/t/data/CRUD/read/distinct.json +++ b/t/data/CRUD/read/distinct.json @@ -52,4 +52,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/find-collation.json b/t/data/CRUD/read/find-collation.json index b2d268ae..53d0e949 100644 --- a/t/data/CRUD/read/find-collation.json +++ b/t/data/CRUD/read/find-collation.json @@ -31,4 +31,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/read/find.json b/t/data/CRUD/read/find.json index d92081d5..3597e37b 100644 --- a/t/data/CRUD/read/find.json +++ b/t/data/CRUD/read/find.json @@ -102,4 +102,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/deleteMany-collation.json b/t/data/CRUD/write/deleteMany-collation.json index 593ad685..d17bf3bc 100644 --- a/t/data/CRUD/write/deleteMany-collation.json +++ b/t/data/CRUD/write/deleteMany-collation.json @@ -44,4 +44,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/deleteMany.json b/t/data/CRUD/write/deleteMany.json index 885ebd20..7eee85e7 100644 --- a/t/data/CRUD/write/deleteMany.json +++ b/t/data/CRUD/write/deleteMany.json @@ -73,4 +73,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/deleteOne-collation.json b/t/data/CRUD/write/deleteOne-collation.json index 9f22b112..2f7f9211 100644 --- a/t/data/CRUD/write/deleteOne-collation.json +++ b/t/data/CRUD/write/deleteOne-collation.json @@ -48,4 +48,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/deleteOne.json b/t/data/CRUD/write/deleteOne.json index 50226bdd..a1106dea 100644 --- a/t/data/CRUD/write/deleteOne.json +++ b/t/data/CRUD/write/deleteOne.json @@ -93,4 +93,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/findOneAndDelete-collation.json b/t/data/CRUD/write/findOneAndDelete-collation.json index e848d754..1ff37d2e 100644 --- a/t/data/CRUD/write/findOneAndDelete-collation.json +++ b/t/data/CRUD/write/findOneAndDelete-collation.json @@ -56,4 +56,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/findOneAndDelete.json b/t/data/CRUD/write/findOneAndDelete.json index 2bfcc32c..e424e2aa 100644 --- a/t/data/CRUD/write/findOneAndDelete.json +++ b/t/data/CRUD/write/findOneAndDelete.json @@ -124,4 +124,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/findOneAndReplace-collation.json b/t/data/CRUD/write/findOneAndReplace-collation.json index 5227b0f8..babb2f7c 100644 --- a/t/data/CRUD/write/findOneAndReplace-collation.json +++ b/t/data/CRUD/write/findOneAndReplace-collation.json @@ -55,4 +55,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/findOneAndReplace-upsert.json b/t/data/CRUD/write/findOneAndReplace-upsert.json index e13eb9c2..0f07bf9c 100644 --- a/t/data/CRUD/write/findOneAndReplace-upsert.json +++ b/t/data/CRUD/write/findOneAndReplace-upsert.json @@ -198,4 +198,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/findOneAndReplace.json b/t/data/CRUD/write/findOneAndReplace.json index f8eb5ebb..70e5c3df 100644 --- a/t/data/CRUD/write/findOneAndReplace.json +++ b/t/data/CRUD/write/findOneAndReplace.json @@ -270,4 +270,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/findOneAndUpdate-collation.json b/t/data/CRUD/write/findOneAndUpdate-collation.json index 172149ac..04c1fe73 100644 --- a/t/data/CRUD/write/findOneAndUpdate-collation.json +++ b/t/data/CRUD/write/findOneAndUpdate-collation.json @@ -64,4 +64,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/findOneAndUpdate.json b/t/data/CRUD/write/findOneAndUpdate.json index c257b740..6da83252 100644 --- a/t/data/CRUD/write/findOneAndUpdate.json +++ b/t/data/CRUD/write/findOneAndUpdate.json @@ -376,4 +376,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/insertMany.json b/t/data/CRUD/write/insertMany.json index f604ef75..61c88eec 100644 --- a/t/data/CRUD/write/insertMany.json +++ b/t/data/CRUD/write/insertMany.json @@ -49,4 +49,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/insertOne.json b/t/data/CRUD/write/insertOne.json index 83597fca..525de75e 100644 --- a/t/data/CRUD/write/insertOne.json +++ b/t/data/CRUD/write/insertOne.json @@ -36,4 +36,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/replaceOne-collation.json b/t/data/CRUD/write/replaceOne-collation.json index c2a08c9b..a668fe73 100644 --- a/t/data/CRUD/write/replaceOne-collation.json +++ b/t/data/CRUD/write/replaceOne-collation.json @@ -50,4 +50,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/replaceOne.json b/t/data/CRUD/write/replaceOne.json index 580e3b93..101af25c 100644 --- a/t/data/CRUD/write/replaceOne.json +++ b/t/data/CRUD/write/replaceOne.json @@ -202,4 +202,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/updateMany-collation.json b/t/data/CRUD/write/updateMany-collation.json index d88ce60f..3cb49f22 100644 --- a/t/data/CRUD/write/updateMany-collation.json +++ b/t/data/CRUD/write/updateMany-collation.json @@ -59,4 +59,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/updateMany.json b/t/data/CRUD/write/updateMany.json index 533e3f30..a3c33998 100644 --- a/t/data/CRUD/write/updateMany.json +++ b/t/data/CRUD/write/updateMany.json @@ -180,4 +180,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/updateOne-collation.json b/t/data/CRUD/write/updateOne-collation.json index 8e45ff32..c49112d5 100644 --- a/t/data/CRUD/write/updateOne-collation.json +++ b/t/data/CRUD/write/updateOne-collation.json @@ -51,4 +51,4 @@ } } ] -} \ No newline at end of file +} diff --git a/t/data/CRUD/write/updateOne.json b/t/data/CRUD/write/updateOne.json index 1a51dff1..76d2086b 100644 --- a/t/data/CRUD/write/updateOne.json +++ b/t/data/CRUD/write/updateOne.json @@ -164,4 +164,4 @@ } } ] -} \ No newline at end of file +} From cde515a6d7af956f6640bf33a24a596f65569387 Mon Sep 17 00:00:00 2001 From: Thomas Bloor Date: Fri, 5 Jan 2018 15:58:43 +0000 Subject: [PATCH 2/4] PERL-787 add arrayFilters tests and modifications --- lib/MongoDB/BulkWriteView.pm | 29 +- lib/MongoDB/Collection.pm | 9 + lib/MongoDB/Op/_Update.pm | 7 + t/crud_spec.t | 40 +- t/data/CRUD/write/bulkWrite-arrayFilters.json | 110 +++++ t/data/CRUD/write/bulkWrite-arrayFilters.yml | 44 ++ .../write/findOneAndUpdate-arrayFilters.json | 203 +++++++++ .../write/findOneAndUpdate-arrayFilters.yml | 69 ++++ .../CRUD/write/updateMany-arrayFilters.json | 182 ++++++++ t/data/CRUD/write/updateMany-arrayFilters.yml | 63 +++ t/data/CRUD/write/updateOne-arrayFilters.json | 390 ++++++++++++++++++ t/data/CRUD/write/updateOne-arrayFilters.yml | 109 +++++ 12 files changed, 1252 insertions(+), 3 deletions(-) create mode 100644 t/data/CRUD/write/bulkWrite-arrayFilters.json create mode 100644 t/data/CRUD/write/bulkWrite-arrayFilters.yml create mode 100644 t/data/CRUD/write/findOneAndUpdate-arrayFilters.json create mode 100644 t/data/CRUD/write/findOneAndUpdate-arrayFilters.yml create mode 100644 t/data/CRUD/write/updateMany-arrayFilters.json create mode 100644 t/data/CRUD/write/updateMany-arrayFilters.yml create mode 100644 t/data/CRUD/write/updateOne-arrayFilters.json create mode 100644 t/data/CRUD/write/updateOne-arrayFilters.yml diff --git a/lib/MongoDB/BulkWriteView.pm b/lib/MongoDB/BulkWriteView.pm index d590bae6..fa9dfc69 100644 --- a/lib/MongoDB/BulkWriteView.pm +++ b/lib/MongoDB/BulkWriteView.pm @@ -33,6 +33,7 @@ use MongoDB::_Types qw( ); use Types::Standard qw( Maybe + ArrayRef InstanceOf ); use boolean; @@ -59,6 +60,11 @@ has _collation => ( isa => Maybe [Document], ); +has _array_filters => ( + is => 'ro', + isa => Maybe [ArrayRef[Document]], +); + has _upsert => ( is => 'ro', isa => Booleanpm, @@ -74,6 +80,11 @@ sub collation { return $self->new( %$self, _collation => $collation ); } +sub arrayFilters { + my ( $self, $array_filters ) = @_; + return $self->new( %$self, _array_filters => $array_filters ); +} + sub upsert { my ($self) = @_; unless ( @_ == 1 ) { @@ -122,6 +133,7 @@ sub _update { upsert => boolean( $self->_upsert ), is_replace => $method eq 'replace_one', (defined $self->_collation ? (collation => $self->_collation) : ()), + (defined $self->_array_filters ? (arrayFilters => $self->_array_filters) : ()), }; $self->_enqueue_write( [ update => $update ] ); @@ -137,6 +149,7 @@ sub delete_many { q => $self->_query, limit => 0, ( defined $self->_collation ? ( collation => $self->_collation ) : () ), + (defined $self->_array_filters ? (arrayFilters => $self->_array_filters) : ()), } ] ); @@ -151,6 +164,7 @@ sub delete_one { q => $self->_query, limit => 1, ( defined $self->_collation ? ( collation => $self->_collation ) : () ), + (defined $self->_array_filters ? (arrayFilters => $self->_array_filters) : ()), } ] ); @@ -224,6 +238,9 @@ __END__ # Remove all documents matching the selector bulk->find( { a => 5 } )->delete_many(); + # Update any arrays with the matching filter + bulk->find( {} )->arrayFilters([ { 'i.b' => 1 } ])->update_many( { '$set' => { 'y.$[i].b' => 2 } } ); + # Remove all documents matching the selector, with respect to a collation bulk->find( { a => { '$gte' => 'F' } )->collation($collation)->delete_many(); @@ -238,8 +255,16 @@ document. To instantiate a C, use the L method from L. -Except for L and L, all methods have an empty return on -success; an exception will be thrown on error. +Except for L, L and L, all methods have an +empty return on success; an exception will be thrown on error. + +=method arrayFilters + + $bulk->arrayFilters( $array_filters )->update_many( $modification ); + +Returns a new C object, where the specified arrayFilter +will be used to determine which array elements to modify for an update +operation on an array field. =method collation diff --git a/lib/MongoDB/Collection.pm b/lib/MongoDB/Collection.pm index 248d9528..31ddf51d 100644 --- a/lib/MongoDB/Collection.pm +++ b/lib/MongoDB/Collection.pm @@ -570,6 +570,9 @@ A hash reference of options may be provided. Valid options include: =for :list +* C - An array of filter documents that determines which array + elements to modify for an update operation on an array field. Only available + for MongoDB servers of version 3.6+. * C - skips document validation, if enabled; this is ignored for MongoDB servers older than version 3.2. * C - a L defining the collation for this operation. @@ -615,6 +618,9 @@ A hash reference of options may be provided. Valid options include: =for :list +* C - An array of filter documents that determines which array + elements to modify for an update operation on an array field. Only available + for MongoDB servers of version 3.6+. * C - skips document validation, if enabled; this is ignored for MongoDB servers older than version 3.2. * C - a L defining the collation for this operation. @@ -959,6 +965,9 @@ The update document must contain only field-update operators (e.g. C<$set>). A hash reference of options may be provided. Valid keys include: =for :list +* C - An array of filter documents that determines which array + elements to modify for an update operation on an array field. Only available + for MongoDB servers of version 3.6+. * C - skips document validation, if enabled; this is ignored for MongoDB servers older than version 3.2. * C - a L defining the collation for this operation. diff --git a/lib/MongoDB/Op/_Update.pm b/lib/MongoDB/Op/_Update.pm index 7d5c17bf..0338d7b7 100644 --- a/lib/MongoDB/Op/_Update.pm +++ b/lib/MongoDB/Op/_Update.pm @@ -33,6 +33,7 @@ use MongoDB::_Types qw( use Types::Standard qw( Bool Maybe + ArrayRef ); use Tie::IxHash; use boolean; @@ -71,6 +72,11 @@ has collation => ( isa => Maybe( [Document] ), ); +has arrayFilters => ( + is => 'ro', + isa => Maybe( [ArrayRef[Document]] ), +); + with $_ for qw( MongoDB::Role::_PrivateConstructor MongoDB::Role::_CollectionOp @@ -104,6 +110,7 @@ sub execute { multi => $self->multi ? $true : $false, upsert => $self->upsert ? $true : $false, ( defined $self->collation ? ( collation => $self->collation ) : () ), + ( defined $self->arrayFilters ? ( arrayFilters => $self->arrayFilters ) : () ), }; return ! $self->write_concern->is_acknowledged diff --git a/t/crud_spec.t b/t/crud_spec.t index cfebded6..5981dbbc 100644 --- a/t/crud_spec.t +++ b/t/crud_spec.t @@ -36,6 +36,10 @@ my $server_version = server_version($conn); my $server_type = server_type($conn); my $coll = $testdb->get_collection('test_collection'); +my $feature_comp = $conn->send_admin_command( + Tie::IxHash->new( getParameter => 1, featureCompatibilityVersion => 1 ) +); + for my $dir ( map { path("t/data/CRUD/$_") } qw/read write/ ) { my $iterator = $dir->iterator( { recurse => 1 } ); while ( my $path = $iterator->() ) { @@ -48,6 +52,12 @@ for my $dir ( map { path("t/data/CRUD/$_") } qw/read write/ ) { my $name = $path->relative($dir)->basename(".json"); subtest $name => sub { + if ( $name =~ 'arrayFilter' ) { + my $ver = $feature_comp->output->{featureCompatibilityVersion}; + $ver = $ver->{version} if ref($ver) eq 'HASH'; + plan skip_all => "requires featureCompatibilityVersion 3.6 - got $ver" + if $ver < 3.6; + } if ( exists $plan->{minServerVersion} ) { my $min_version = $plan->{minServerVersion}; $min_version = "v$min_version" unless $min_version =~ /^v/; @@ -69,7 +79,6 @@ for my $dir ( map { path("t/data/CRUD/$_") } qw/read write/ ) { }; } } - #--------------------------------------------------------------------------# # generic tests #--------------------------------------------------------------------------# @@ -166,6 +175,35 @@ BEGIN { # method-specific tests #--------------------------------------------------------------------------# +sub test_bulk_write { + my ( $class, $label, $method, $args, $outcome ) = @_; + + my $bulk; + + if ( $args->{options}->{ordered} ) { + $bulk = $coll->initialize_ordered_bulk_op; + } else { + $bulk = $coll->initialize_unordered_bulk_op; + } + + for my $request ( @{ $args->{requests} } ) { + my $req_method = $request->{name}; + my $arg = $request->{arguments}; + $req_method =~ s{([A-Z])}{_\L$1}g; + my $filter = delete $arg->{filter}; + my $update = delete $arg->{update}; + my $arr_filters = delete $arg->{arrayFilters}; + my $bulk_view = $bulk->find( $filter ); + if ( scalar( @$arr_filters ) ) { + $bulk_view = $bulk_view->arrayFilters( $arr_filters ); + } + $bulk_view->$req_method( $update ); + } + my $res = $bulk->execute; + + check_write_outcome( $label, $res, $outcome ); +} + sub test_aggregate { my ( $class, $label, $method, $args, $outcome ) = @_; diff --git a/t/data/CRUD/write/bulkWrite-arrayFilters.json b/t/data/CRUD/write/bulkWrite-arrayFilters.json new file mode 100644 index 00000000..90f32a6f --- /dev/null +++ b/t/data/CRUD/write/bulkWrite-arrayFilters.json @@ -0,0 +1,110 @@ +{ + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ], + "minServerVersion": "3.5.6", + "tests": [ + { + "description": "BulkWrite with arrayFilters", + "operation": { + "arguments": { + "options": { + "ordered": true + }, + "requests": [ + { + "arguments": { + "arrayFilters": [ + { + "i.b": 3 + } + ], + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + } + }, + "name": "updateOne" + }, + { + "arguments": { + "arrayFilters": [ + { + "i.b": 1 + } + ], + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + } + }, + "name": "updateMany" + } + ] + }, + "name": "bulkWrite" + }, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 2 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 2 + } + ] + } + ] + }, + "result": { + "deletedCount": 0, + "insertedIds": {}, + "matchedCount": 3, + "modifiedCount": 3, + "upsertedCount": 0, + "upsertedIds": {} + } + } + } + ] +} \ No newline at end of file diff --git a/t/data/CRUD/write/bulkWrite-arrayFilters.yml b/t/data/CRUD/write/bulkWrite-arrayFilters.yml new file mode 100644 index 00000000..a6511fa5 --- /dev/null +++ b/t/data/CRUD/write/bulkWrite-arrayFilters.yml @@ -0,0 +1,44 @@ +data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + +minServerVersion: '3.5.6' + +tests: + - + description: "BulkWrite with arrayFilters" + operation: + name: "bulkWrite" + arguments: + requests: + - + # UpdateOne when one document matches arrayFilters + name: "updateOne" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 3} + - + # UpdateMany when multiple documents match arrayFilters + name: "updateMany" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 1} + options: { ordered: true } + outcome: + result: + deletedCount: 0 + insertedIds: {} + matchedCount: 3 + modifiedCount: 3 + upsertedCount: 0 + upsertedIds: {} + collection: + data: + - {_id: 1, y: [{b: 2}, {b: 2}]} + - {_id: 2, y: [{b: 0}, {b: 2}]} diff --git a/t/data/CRUD/write/findOneAndUpdate-arrayFilters.json b/t/data/CRUD/write/findOneAndUpdate-arrayFilters.json new file mode 100644 index 00000000..1aa13b86 --- /dev/null +++ b/t/data/CRUD/write/findOneAndUpdate-arrayFilters.json @@ -0,0 +1,203 @@ +{ + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ], + "minServerVersion": "3.5.6", + "tests": [ + { + "description": "FindOneAndUpdate when no document matches arrayFilters", + "operation": { + "name": "findOneAndUpdate", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 4 + } + ] + } + }, + "outcome": { + "result": { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + } + }, + { + "description": "FindOneAndUpdate when one document matches arrayFilters", + "operation": { + "name": "findOneAndUpdate", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] + } + }, + "outcome": { + "result": { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + } + }, + { + "description": "FindOneAndUpdate when multiple documents match arrayFilters", + "operation": { + "name": "findOneAndUpdate", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 1 + } + ] + } + }, + "outcome": { + "result": { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 2 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + } + } + ] +} diff --git a/t/data/CRUD/write/findOneAndUpdate-arrayFilters.yml b/t/data/CRUD/write/findOneAndUpdate-arrayFilters.yml new file mode 100644 index 00000000..7665ad0c --- /dev/null +++ b/t/data/CRUD/write/findOneAndUpdate-arrayFilters.yml @@ -0,0 +1,69 @@ +data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} +minServerVersion: '3.5.6' + +tests: + - + description: "FindOneAndUpdate when no document matches arrayFilters" + operation: + name: findOneAndUpdate + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 4} + + outcome: + result: + _id: 1 + y: + - {b: 3} + - {b: 1} + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - + description: "FindOneAndUpdate when one document matches arrayFilters" + operation: + name: findOneAndUpdate + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 3} + + outcome: + result: + _id: 1 + y: + - {b: 3} + - {b: 1} + collection: + data: + - {_id: 1, y: [{b: 2}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - + description: "FindOneAndUpdate when multiple documents match arrayFilters" + operation: + name: findOneAndUpdate + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 1} + + outcome: + result: + _id: 1 + y: + - {b: 3} + - {b: 1} + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 2}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} diff --git a/t/data/CRUD/write/updateMany-arrayFilters.json b/t/data/CRUD/write/updateMany-arrayFilters.json new file mode 100644 index 00000000..a86be583 --- /dev/null +++ b/t/data/CRUD/write/updateMany-arrayFilters.json @@ -0,0 +1,182 @@ +{ + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ], + "minServerVersion": "3.5.6", + "tests": [ + { + "description": "UpdateMany when no documents match arrayFilters", + "operation": { + "name": "updateMany", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 4 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 2, + "modifiedCount": 0 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + } + }, + { + "description": "UpdateMany when one document matches arrayFilters", + "operation": { + "name": "updateMany", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 2, + "modifiedCount": 1 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + } + }, + { + "description": "UpdateMany when multiple documents match arrayFilters", + "operation": { + "name": "updateMany", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 1 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 2, + "modifiedCount": 2 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 2 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 2 + } + ] + } + ] + } + } + } + ] +} diff --git a/t/data/CRUD/write/updateMany-arrayFilters.yml b/t/data/CRUD/write/updateMany-arrayFilters.yml new file mode 100644 index 00000000..8fe67c5b --- /dev/null +++ b/t/data/CRUD/write/updateMany-arrayFilters.yml @@ -0,0 +1,63 @@ +data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} +minServerVersion: '3.5.6' + +tests: + - + description: "UpdateMany when no documents match arrayFilters" + operation: + name: "updateMany" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 4} + + outcome: + result: + matchedCount: 2 + modifiedCount: 0 + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - + description: "UpdateMany when one document matches arrayFilters" + operation: + name: "updateMany" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 3} + + outcome: + result: + matchedCount: 2 + modifiedCount: 1 + collection: + data: + - {_id: 1, y: [{b: 2}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - + description: "UpdateMany when multiple documents match arrayFilters" + operation: + name: "updateMany" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 1} + + outcome: + result: + matchedCount: 2 + modifiedCount: 2 + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 2}]} + - {_id: 2, y: [{b: 0}, {b: 2}]} diff --git a/t/data/CRUD/write/updateOne-arrayFilters.json b/t/data/CRUD/write/updateOne-arrayFilters.json new file mode 100644 index 00000000..7ac1986c --- /dev/null +++ b/t/data/CRUD/write/updateOne-arrayFilters.json @@ -0,0 +1,390 @@ +{ + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + }, + { + "_id": 3, + "y": [ + { + "b": 5, + "c": [ + { + "d": 2 + }, + { + "d": 1 + } + ] + } + ] + } + ], + "minServerVersion": "3.5.6", + "tests": [ + { + "description": "UpdateOne when no document matches arrayFilters", + "operation": { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 4 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 1, + "modifiedCount": 0 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + }, + { + "_id": 3, + "y": [ + { + "b": 5, + "c": [ + { + "d": 2 + }, + { + "d": 1 + } + ] + } + ] + } + ] + } + } + }, + { + "description": "UpdateOne when one document matches arrayFilters", + "operation": { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 1, + "modifiedCount": 1 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + }, + { + "_id": 3, + "y": [ + { + "b": 5, + "c": [ + { + "d": 2 + }, + { + "d": 1 + } + ] + } + ] + } + ] + } + } + }, + { + "description": "UpdateOne when multiple documents match arrayFilters", + "operation": { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 1 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 1, + "modifiedCount": 1 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 2 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + }, + { + "_id": 3, + "y": [ + { + "b": 5, + "c": [ + { + "d": 2 + }, + { + "d": 1 + } + ] + } + ] + } + ] + } + } + }, + { + "description": "UpdateOne when no documents match multiple arrayFilters", + "operation": { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 3 + }, + "update": { + "$set": { + "y.$[i].c.$[j].d": 0 + } + }, + "arrayFilters": [ + { + "i.b": 5 + }, + { + "j.d": 3 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 1, + "modifiedCount": 0 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + }, + { + "_id": 3, + "y": [ + { + "b": 5, + "c": [ + { + "d": 2 + }, + { + "d": 1 + } + ] + } + ] + } + ] + } + } + }, + { + "description": "UpdateOne when one document matches multiple arrayFilters", + "operation": { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 3 + }, + "update": { + "$set": { + "y.$[i].c.$[j].d": 0 + } + }, + "arrayFilters": [ + { + "i.b": 5 + }, + { + "j.d": 1 + } + ] + } + }, + "outcome": { + "result": { + "matchedCount": 1, + "modifiedCount": 1 + }, + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 3 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + }, + { + "_id": 3, + "y": [ + { + "b": 5, + "c": [ + { + "d": 2 + }, + { + "d": 0 + } + ] + } + ] + } + ] + } + } + } + ] +} diff --git a/t/data/CRUD/write/updateOne-arrayFilters.yml b/t/data/CRUD/write/updateOne-arrayFilters.yml new file mode 100644 index 00000000..b49dadec --- /dev/null +++ b/t/data/CRUD/write/updateOne-arrayFilters.yml @@ -0,0 +1,109 @@ +data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} +minServerVersion: '3.5.6' + +tests: + - + description: "UpdateOne when no document matches arrayFilters" + operation: + name: "updateOne" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 4} + + outcome: + result: + matchedCount: 1 + modifiedCount: 0 + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} + - + description: "UpdateOne when one document matches arrayFilters" + operation: + name: "updateOne" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 3} + + outcome: + result: + matchedCount: 1 + modifiedCount: 1 + collection: + data: + - {_id: 1, y: [{b: 2}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} + - + description: "UpdateOne when multiple documents match arrayFilters" + operation: + name: "updateOne" + arguments: + filter: {} + update: + $set: {"y.$[i].b": 2} + arrayFilters: + - {i.b: 1} + + outcome: + result: + matchedCount: 1 + modifiedCount: 1 + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 2}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} + - + description: "UpdateOne when no documents match multiple arrayFilters" + operation: + name: "updateOne" + arguments: + filter: {_id: 3} + update: + $set: {"y.$[i].c.$[j].d": 0} + arrayFilters: + - {i.b: 5} + - {j.d: 3} + + outcome: + result: + matchedCount: 1 + modifiedCount: 0 + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 1}] }]} + - + description: "UpdateOne when one document matches multiple arrayFilters" + operation: + name: "updateOne" + arguments: + filter: {_id: 3} + update: + $set: {"y.$[i].c.$[j].d": 0} + arrayFilters: + - {i.b: 5} + - {j.d: 1} + + outcome: + result: + matchedCount: 1 + modifiedCount: 1 + collection: + data: + - {_id: 1, y: [{b: 3}, {b: 1}]} + - {_id: 2, y: [{b: 0}, {b: 1}]} + - {_id: 3, y: [{b: 5, c: [{d: 2}, {d: 0}] }]} From 3188880666d6cfcba7349af068751d007d17dcc5 Mon Sep 17 00:00:00 2001 From: Thomas Bloor Date: Tue, 23 Jan 2018 18:37:22 +0000 Subject: [PATCH 3/4] PERL-787 Factor out featureCompatibilityVersion parsing in tests to helper sub --- t/crud_spec.t | 20 +++++++++++--------- t/lib/MongoDBTest.pm | 24 ++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/t/crud_spec.t b/t/crud_spec.t index 5981dbbc..703ce492 100644 --- a/t/crud_spec.t +++ b/t/crud_spec.t @@ -26,7 +26,14 @@ use version; use MongoDB; use lib "t/lib"; -use MongoDBTest qw/skip_unless_mongod build_client get_test_db server_version server_type get_capped/; +use MongoDBTest qw/ + skip_unless_mongod + build_client + get_test_db + server_version + server_type + get_feature_compat_version +/; skip_unless_mongod(); @@ -34,11 +41,9 @@ my $conn = build_client(); my $testdb = get_test_db($conn); my $server_version = server_version($conn); my $server_type = server_type($conn); +my $feat_compat_ver = get_feature_compat_version($conn); my $coll = $testdb->get_collection('test_collection'); -my $feature_comp = $conn->send_admin_command( - Tie::IxHash->new( getParameter => 1, featureCompatibilityVersion => 1 ) -); for my $dir ( map { path("t/data/CRUD/$_") } qw/read write/ ) { my $iterator = $dir->iterator( { recurse => 1 } ); @@ -52,11 +57,8 @@ for my $dir ( map { path("t/data/CRUD/$_") } qw/read write/ ) { my $name = $path->relative($dir)->basename(".json"); subtest $name => sub { - if ( $name =~ 'arrayFilter' ) { - my $ver = $feature_comp->output->{featureCompatibilityVersion}; - $ver = $ver->{version} if ref($ver) eq 'HASH'; - plan skip_all => "requires featureCompatibilityVersion 3.6 - got $ver" - if $ver < 3.6; + if ( $name =~ 'arrayFilter' && $feat_compat_ver < 3.6 ) { + plan skip_all => "arrayFilters requires featureCompatibilityVersion 3.6 - got $feat_compat_ver"; } if ( exists $plan->{minServerVersion} ) { my $min_version = $plan->{minServerVersion}; diff --git a/t/lib/MongoDBTest.pm b/t/lib/MongoDBTest.pm index 5816b598..475fc981 100644 --- a/t/lib/MongoDBTest.pm +++ b/t/lib/MongoDBTest.pm @@ -28,8 +28,16 @@ use boolean; use version; our @EXPORT_OK = qw( - build_client get_test_db server_version server_type clear_testdbs get_capped - skip_unless_mongod uri_escape get_unique_collection + build_client + get_test_db + server_version + server_type + clear_testdbs + get_capped + skip_unless_mongod + uri_escape + get_unique_collection + get_feature_compat_version ); my @testdbs; @@ -153,6 +161,18 @@ sub server_type { return $server_type; } +sub get_feature_compat_version { + my $conn = shift; + + my $feature_comp = $conn->send_admin_command( + Tie::IxHash->new( getParameter => 1, featureCompatibilityVersion => 1 ) + ); + + my $ver = $feature_comp->output->{featureCompatibilityVersion}; + $ver = $ver->{version} if ref($ver) eq 'HASH'; + return $ver; +} + # URI escaping adapted from HTTP::Tiny my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255; my $unsafe_char = qr/[^A-Za-z0-9\-\._~]/; From 68823b4d576baf80c4f5f29dc85ec3f8f899938f Mon Sep 17 00:00:00 2001 From: Thomas Bloor Date: Wed, 24 Jan 2018 13:28:58 +0000 Subject: [PATCH 4/4] PERL-787 Add error for using arrayFilter against pre 3.6 MongoDB or unacknowledged writes --- lib/MongoDB/Op/_Update.pm | 9 +++++++++ lib/MongoDB/_Link.pm | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/lib/MongoDB/Op/_Update.pm b/lib/MongoDB/Op/_Update.pm index 0338d7b7..8bd7f4df 100644 --- a/lib/MongoDB/Op/_Update.pm +++ b/lib/MongoDB/Op/_Update.pm @@ -100,6 +100,15 @@ sub execute { if !$self->write_concern->is_acknowledged; } + if ( defined $self->arrayFilters ) { + MongoDB::UsageError->throw( + "MongoDB host '" . $link->address . "' doesn't support arrayFilters" ) + if !$link->supports_arrayFilters; + MongoDB::UsageError->throw( + "Unacknowledged updates that specify arrayFilters are not allowed") + if !$self->write_concern->is_acknowledged; + } + my $orig_op = { q => ( ref( $self->filter ) eq 'ARRAY' diff --git a/lib/MongoDB/_Link.pm b/lib/MongoDB/_Link.pm index d8f9a7db..b79ef6b0 100644 --- a/lib/MongoDB/_Link.pm +++ b/lib/MongoDB/_Link.pm @@ -129,6 +129,12 @@ has supports_collation => ( isa => Bool, ); +has supports_arrayFilters => ( + is => 'rwp', + init_arg => undef, + isa => Bool, +); + my @connection_state_fields = qw( fh connected rcvbuf last_used fdset is_ssl ); @@ -235,6 +241,7 @@ sub set_metadata { $self->_set_does_write_commands( $self->accepts_wire_version(2) ); $self->_set_supports_collation( $self->accepts_wire_version(5) ); + $self->_set_supports_arrayFilters( $self->accepts_wire_version(6) ); return; }