diff --git a/data/crud/test_files.txt b/data/crud/test_files.txt index e7ee0e2b28..5859a138eb 100644 --- a/data/crud/test_files.txt +++ b/data/crud/test_files.txt @@ -36,6 +36,54 @@ v1/write/updateOne.json v2/aggregate-merge.json v2/aggregate-out-readConcern.json v2/bulkWrite-arrayFilters.json +v2/bulkWrite-delete-hint-clientError.json +v2/bulkWrite-delete-hint.json +v2/bulkWrite-delete-hint-serverError.json +v2/bulkWrite-update-hint-clientError.json +v2/bulkWrite-update-hint.json +v2/bulkWrite-update-hint-serverError.json v2/db-aggregate.json +v2/deleteMany-hint-clientError.json +v2/deleteMany-hint.json +v2/deleteMany-hint-serverError.json +v2/deleteOne-hint-clientError.json +v2/deleteOne-hint.json +v2/deleteOne-hint-serverError.json +v2/findOneAndDelete-hint-clientError.json +v2/findOneAndDelete-hint.json +v2/findOneAndDelete-hint-serverError.json +v2/findOneAndReplace-hint-clientError.json +v2/findOneAndReplace-hint.json +v2/findOneAndReplace-hint-serverError.json +v2/findOneAndUpdate-hint-clientError.json +v2/findOneAndUpdate-hint.json +v2/findOneAndUpdate-hint-serverError.json +v2/replaceOne-hint.json +v2/unacknowledged-bulkWrite-delete-hint-clientError.json +v2/unacknowledged-bulkWrite-delete-hint.json +v2/unacknowledged-bulkWrite-update-hint-clientError.json +v2/unacknowledged-bulkWrite-update-hint.json +v2/unacknowledged-deleteMany-hint-clientError.json +v2/unacknowledged-deleteMany-hint.json +v2/unacknowledged-deleteOne-hint-clientError.json +v2/unacknowledged-deleteOne-hint.json +v2/unacknowledged-findOneAndDelete-hint-clientError.json +v2/unacknowledged-findOneAndDelete-hint.json +v2/unacknowledged-findOneAndReplace-hint-clientError.json +v2/unacknowledged-findOneAndReplace-hint.json +v2/unacknowledged-findOneAndUpdate-hint-clientError.json +v2/unacknowledged-findOneAndUpdate-hint.json +v2/unacknowledged-replaceOne-hint-clientError.json +v2/unacknowledged-replaceOne-hint.json +v2/unacknowledged-updateMany-hint-clientError.json +v2/unacknowledged-updateMany-hint.json +v2/unacknowledged-updateOne-hint-clientError.json +v2/unacknowledged-updateOne-hint.json +v2/updateMany-hint-clientError.json +v2/updateMany-hint.json +v2/updateMany-hint-serverError.json +v2/updateOne-hint-clientError.json +v2/updateOne-hint.json +v2/updateOne-hint-serverError.json v2/find-allowdiskuse.json -v2/updateWithPipelines.json +v2/updateWithPipelines.json \ No newline at end of file diff --git a/data/crud/v2/bulkWrite-arrayFilters.json b/data/crud/v2/bulkWrite-arrayFilters.json index be26a337a5..2d3ce96de1 100644 --- a/data/crud/v2/bulkWrite-arrayFilters.json +++ b/data/crud/v2/bulkWrite-arrayFilters.json @@ -32,7 +32,7 @@ "database_name": "crud-tests", "tests": [ { - "description": "BulkWrite with arrayFilters", + "description": "BulkWrite updateOne with arrayFilters", "operations": [ { "name": "bulkWrite", @@ -53,7 +53,86 @@ } ] } - }, + } + ], + "options": { + "ordered": true + } + }, + "result": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": {}, + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test", + "updates": [ + { + "q": {}, + "u": { + "$set": { + "y.$[i].b": 2 + } + }, + "arrayFilters": [ + { + "i.b": 3 + } + ] + } + ], + "ordered": true + }, + "command_name": "update", + "database_name": "crud-tests" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "y": [ + { + "b": 2 + }, + { + "b": 1 + } + ] + }, + { + "_id": 2, + "y": [ + { + "b": 0 + }, + { + "b": 1 + } + ] + } + ] + } + } + }, + { + "description": "BulkWrite updateMany with arrayFilters", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ { "name": "updateMany", "arguments": { @@ -79,8 +158,8 @@ "deletedCount": 0, "insertedCount": 0, "insertedIds": {}, - "matchedCount": 3, - "modifiedCount": 3, + "matchedCount": 2, + "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} } @@ -92,19 +171,6 @@ "command": { "update": "test", "updates": [ - { - "q": {}, - "u": { - "$set": { - "y.$[i].b": 2 - } - }, - "arrayFilters": [ - { - "i.b": 3 - } - ] - }, { "q": {}, "u": { @@ -134,7 +200,7 @@ "_id": 1, "y": [ { - "b": 2 + "b": 3 }, { "b": 2 diff --git a/data/crud/v2/bulkWrite-delete-hint-clientError.json b/data/crud/v2/bulkWrite-delete-hint-clientError.json new file mode 100644 index 0000000000..cfeac904ca --- /dev/null +++ b/data/crud/v2/bulkWrite-delete-hint-clientError.json @@ -0,0 +1,150 @@ +{ + "runOn": [ + { + "maxServerVersion": "3.3.99" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "BulkWrite_delete_hint", + "tests": [ + { + "description": "BulkWrite deleteOne with hints unsupported (client-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 2 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite deleteMany with hints unsupported (client-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_" + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/bulkWrite-delete-hint-serverError.json b/data/crud/v2/bulkWrite-delete-hint-serverError.json new file mode 100644 index 0000000000..c68973b0f6 --- /dev/null +++ b/data/crud/v2/bulkWrite-delete-hint-serverError.json @@ -0,0 +1,209 @@ +{ + "runOn": [ + { + "minServerVersion": "3.4.0", + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "BulkWrite_delete_hint", + "tests": [ + { + "description": "BulkWrite deleteOne with hints unsupported (server-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 2 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "BulkWrite_delete_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": "_id_", + "limit": 1 + }, + { + "q": { + "_id": 2 + }, + "hint": { + "_id": 1 + }, + "limit": 1 + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite deleteMany with hints unsupported (server-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_" + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "BulkWrite_delete_hint", + "deletes": [ + { + "q": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_", + "limit": 0 + }, + { + "q": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + }, + "limit": 0 + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/bulkWrite-delete-hint.json b/data/crud/v2/bulkWrite-delete-hint.json new file mode 100644 index 0000000000..ece3238fc3 --- /dev/null +++ b/data/crud/v2/bulkWrite-delete-hint.json @@ -0,0 +1,204 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "BulkWrite_delete_hint", + "tests": [ + { + "description": "BulkWrite deleteOne with hints", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 2 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "result": { + "deletedCount": 2, + "insertedCount": 0, + "insertedIds": {}, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "BulkWrite_delete_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": "_id_", + "limit": 1 + }, + { + "q": { + "_id": 2 + }, + "hint": { + "_id": 1 + }, + "limit": 1 + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite deleteMany with hints", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_" + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "result": { + "deletedCount": 3, + "insertedCount": 0, + "insertedIds": {}, + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "BulkWrite_delete_hint", + "deletes": [ + { + "q": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_", + "limit": 0 + }, + { + "q": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + }, + "limit": 0 + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 3, + "x": 33 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/bulkWrite-update-hint-clientError.json b/data/crud/v2/bulkWrite-update-hint-clientError.json new file mode 100644 index 0000000000..fa919ec515 --- /dev/null +++ b/data/crud/v2/bulkWrite-update-hint-clientError.json @@ -0,0 +1,235 @@ +{ + "runOn": [ + { + "maxServerVersion": "3.3.99" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "test_bulkwrite_update_hint", + "tests": [ + { + "description": "BulkWrite updateOne with update hints unsupported (client-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite updateMany with update hints unsupported (client-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite replaceOne with update hints unsupported (client-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 333 + }, + "hint": "_id_" + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/bulkWrite-update-hint-serverError.json b/data/crud/v2/bulkWrite-update-hint-serverError.json new file mode 100644 index 0000000000..e8b96fffeb --- /dev/null +++ b/data/crud/v2/bulkWrite-update-hint-serverError.json @@ -0,0 +1,343 @@ +{ + "runOn": [ + { + "minServerVersion": "3.4.0", + "maxServerVersion": "4.1.9" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "test_bulkwrite_update_hint", + "tests": [ + { + "description": "BulkWrite updateOne with update hints unsupported (server-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_bulkwrite_update_hint", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite updateMany with update hints unsupported (server-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_bulkwrite_update_hint", + "updates": [ + { + "q": { + "_id": { + "$lt": 3 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": "_id_" + }, + { + "q": { + "_id": { + "$lt": 3 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite replaceOne with update hints unsupported (server-side error)", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 333 + }, + "hint": "_id_" + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_bulkwrite_update_hint", + "updates": [ + { + "q": { + "_id": 3 + }, + "u": { + "x": 333 + }, + "hint": "_id_" + }, + { + "q": { + "_id": 4 + }, + "u": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/bulkWrite-update-hint.json b/data/crud/v2/bulkWrite-update-hint.json new file mode 100644 index 0000000000..15e169f76c --- /dev/null +++ b/data/crud/v2/bulkWrite-update-hint.json @@ -0,0 +1,366 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "test_bulkwrite_update_hint", + "tests": [ + { + "description": "BulkWrite updateOne with update hints", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "result": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": {}, + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_bulkwrite_update_hint", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 13 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite updateMany with update hints", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "result": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": {}, + "matchedCount": 4, + "modifiedCount": 4, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_bulkwrite_update_hint", + "updates": [ + { + "q": { + "_id": { + "$lt": 3 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": "_id_" + }, + { + "q": { + "_id": { + "$lt": 3 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 13 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "BulkWrite replaceOne with update hints", + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 333 + }, + "hint": "_id_" + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "result": { + "deletedCount": 0, + "insertedCount": 0, + "insertedIds": {}, + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0, + "upsertedIds": {} + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_bulkwrite_update_hint", + "updates": [ + { + "q": { + "_id": 3 + }, + "u": { + "x": 333 + }, + "hint": "_id_" + }, + { + "q": { + "_id": 4 + }, + "u": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 333 + }, + { + "_id": 4, + "x": 444 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/bulkWrite-update-hint.yml b/data/crud/v2/bulkWrite-update-hint.yml new file mode 100644 index 0000000000..0d60a56b6f --- /dev/null +++ b/data/crud/v2/bulkWrite-update-hint.yml @@ -0,0 +1,164 @@ +runOn: + - { minServerVersion: "4.2.0" } + +data: + - {_id: 1, x: 11} + - {_id: 2, x: 22} + - {_id: 3, x: 33} + - {_id: 4, x: 44} + +collection_name: &collection_name 'test_bulkwrite_update_hint' + +tests: + - + description: "BulkWrite updateOne with update hints" + operations: + - + name: "bulkWrite" + arguments: + requests: + - + name: "updateOne" + arguments: + filter: &updateOne_filter { _id: 1 } + update: &updateOne_update { $inc: { x: 1 } } + hint: &hint_string "_id_" + - + name: "updateOne" + arguments: + filter: *updateOne_filter + update: *updateOne_update + hint: &hint_doc { _id: 1 } + options: { ordered: true } + result: + deletedCount: 0 + insertedCount: 0 + insertedIds: {} + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + upsertedIds: {} + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *updateOne_filter + u: *updateOne_update + hint: *hint_string + - + q: *updateOne_filter + u: *updateOne_update + hint: *hint_doc + ordered: true + outcome: + collection: + data: + - {_id: 1, x: 13 } + - {_id: 2, x: 22 } + - {_id: 3, x: 33 } + - {_id: 4, x: 44 } + - + description: "BulkWrite updateMany with update hints" + operations: + - + name: "bulkWrite" + arguments: + requests: + - + name: "updateMany" + arguments: + filter: &updateMany_filter { _id: { $lt: 3 } } + update: &updateMany_update { $inc: { x: 1 } } + hint: *hint_string + - + name: "updateMany" + arguments: + filter: *updateMany_filter + update: *updateMany_update + hint: *hint_doc + options: { ordered: true } + result: + deletedCount: 0 + insertedCount: 0 + insertedIds: {} + matchedCount: 4 + modifiedCount: 4 + upsertedCount: 0 + upsertedIds: {} + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *updateMany_filter + u: *updateMany_update + multi: true + hint: *hint_string + - + q: *updateMany_filter + u: *updateMany_update + multi: true + hint: *hint_doc + ordered: true + outcome: + collection: + data: + - {_id: 1, x: 13 } + - {_id: 2, x: 24 } + - {_id: 3, x: 33 } + - {_id: 4, x: 44 } + - + description: "BulkWrite replaceOne with update hints" + operations: + - + name: "bulkWrite" + arguments: + requests: + - + name: "replaceOne" + arguments: + filter: { _id: 3 } + replacement: { x: 333 } + hint: *hint_string + - + name: "replaceOne" + arguments: + filter: { _id: 4 } + replacement: { x: 444 } + hint: *hint_doc + options: { ordered: true } + result: + deletedCount: 0 + insertedCount: 0 + insertedIds: {} + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + upsertedIds: {} + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: { _id: 3 } + u: { x: 333 } + hint: *hint_string + - + q: { _id: 4 } + u: { x: 444 } + hint: *hint_doc + ordered: true + outcome: + collection: + data: + - {_id: 1, x: 11 } + - {_id: 2, x: 22 } + - {_id: 3, x: 333 } + - {_id: 4, x: 444 } diff --git a/data/crud/v2/deleteMany-hint-clientError.json b/data/crud/v2/deleteMany-hint-clientError.json new file mode 100644 index 0000000000..3a0d02566b --- /dev/null +++ b/data/crud/v2/deleteMany-hint-clientError.json @@ -0,0 +1,100 @@ +{ + "runOn": [ + { + "maxServerVersion": "3.3.99" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "DeleteMany_hint", + "tests": [ + { + "description": "DeleteMany with hint string unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + }, + { + "description": "DeleteMany with hint document unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/deleteMany-hint-serverError.json b/data/crud/v2/deleteMany-hint-serverError.json new file mode 100644 index 0000000000..5829e86df8 --- /dev/null +++ b/data/crud/v2/deleteMany-hint-serverError.json @@ -0,0 +1,141 @@ +{ + "runOn": [ + { + "minServerVersion": "3.4.0", + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "DeleteMany_hint", + "tests": [ + { + "description": "DeleteMany with hint string unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteMany_hint", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_", + "limit": 0 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + }, + { + "description": "DeleteMany with hint document unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteMany_hint", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + }, + "limit": 0 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/deleteMany-hint.json b/data/crud/v2/deleteMany-hint.json new file mode 100644 index 0000000000..51ee386066 --- /dev/null +++ b/data/crud/v2/deleteMany-hint.json @@ -0,0 +1,128 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "DeleteMany_hint", + "tests": [ + { + "description": "DeleteMany with hint string", + "operations": [ + { + "object": "collection", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "result": { + "deletedCount": 2 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteMany_hint", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_", + "limit": 0 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + } + ] + } + } + }, + { + "description": "DeleteMany with hint document", + "operations": [ + { + "object": "collection", + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "result": { + "deletedCount": 2 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteMany_hint", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + }, + "limit": 0 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/deleteOne-hint-clientError.json b/data/crud/v2/deleteOne-hint-clientError.json new file mode 100644 index 0000000000..97f8ec4924 --- /dev/null +++ b/data/crud/v2/deleteOne-hint-clientError.json @@ -0,0 +1,84 @@ +{ + "runOn": [ + { + "maxServerVersion": "3.3.99" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "DeleteOne_hint", + "tests": [ + { + "description": "DeleteOne with hint string unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "DeleteOne with hint document unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/deleteOne-hint-serverError.json b/data/crud/v2/deleteOne-hint-serverError.json new file mode 100644 index 0000000000..3cf9400a88 --- /dev/null +++ b/data/crud/v2/deleteOne-hint-serverError.json @@ -0,0 +1,121 @@ +{ + "runOn": [ + { + "minServerVersion": "3.4.0", + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "DeleteOne_hint", + "tests": [ + { + "description": "DeleteOne with hint string unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteOne_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": "_id_", + "limit": 1 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "DeleteOne with hint document unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteOne_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": { + "_id": 1 + }, + "limit": 1 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/deleteOne-hint.json b/data/crud/v2/deleteOne-hint.json new file mode 100644 index 0000000000..ec8e7715a2 --- /dev/null +++ b/data/crud/v2/deleteOne-hint.json @@ -0,0 +1,116 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "DeleteOne_hint", + "tests": [ + { + "description": "DeleteOne with hint string", + "operations": [ + { + "object": "collection", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + }, + "result": { + "deletedCount": 1 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteOne_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": "_id_", + "limit": 1 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "deleteOne with hint document", + "operations": [ + { + "object": "collection", + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": { + "_id": 1 + } + }, + "result": { + "deletedCount": 1 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteOne_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": { + "_id": 1 + }, + "limit": 1 + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/replaceOne-hint.json b/data/crud/v2/replaceOne-hint.json new file mode 100644 index 0000000000..de4aa4d02f --- /dev/null +++ b/data/crud/v2/replaceOne-hint.json @@ -0,0 +1,146 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "test_replaceone_hint", + "tests": [ + { + "description": "ReplaceOne with hint string", + "operations": [ + { + "object": "collection", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_replaceone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 111 + } + ] + } + } + }, + { + "description": "ReplaceOne with hint document", + "operations": [ + { + "object": "collection", + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_replaceone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 111 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/replaceOne-hint.yml b/data/crud/v2/replaceOne-hint.yml new file mode 100644 index 0000000000..8b418d1202 --- /dev/null +++ b/data/crud/v2/replaceOne-hint.yml @@ -0,0 +1,61 @@ +runOn: + - { minServerVersion: "4.2.0" } + +data: + - {_id: 1, x: 11} + - {_id: 2, x: 22} + +collection_name: &collection_name 'test_replaceone_hint' + +tests: + - + description: "ReplaceOne with hint string" + operations: + - + object: collection + name: replaceOne + arguments: + filter: &filter { _id: { $gt: 1 } } + replacement: &replacement {x: 111} + hint: "_id_" + result: &result + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *filter + u: *replacement + hint: "_id_" + outcome: &outcome + collection: + data: + - {_id: 1, x: 11 } + - {_id: 2, x: 111 } + - + description: "ReplaceOne with hint document" + operations: + - + object: collection + name: replaceOne + arguments: + filter: *filter + replacement: *replacement + hint: { _id: 1 } + result: *result + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *filter + u: *replacement + hint: { _id: 1 } + outcome: *outcome diff --git a/data/crud/v2/unacknowledged-bulkWrite-delete-hint-clientError.json b/data/crud/v2/unacknowledged-bulkWrite-delete-hint-clientError.json new file mode 100644 index 0000000000..a92c5dfb88 --- /dev/null +++ b/data/crud/v2/unacknowledged-bulkWrite-delete-hint-clientError.json @@ -0,0 +1,160 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "BulkWrite_delete_hint", + "tests": [ + { + "description": "Unacknowledged bulkWrite deleteOne with hints fails with client-side error on server < 4.4", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 2 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "Unacknowledged bulkWrite deleteMany with hints fails with client-side error on server < 4.4", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_" + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-bulkWrite-delete-hint.json b/data/crud/v2/unacknowledged-bulkWrite-delete-hint.json new file mode 100644 index 0000000000..b2147a27f9 --- /dev/null +++ b/data/crud/v2/unacknowledged-bulkWrite-delete-hint.json @@ -0,0 +1,174 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "BulkWrite_delete_hint", + "tests": [ + { + "description": "Unacknowledged bulkWrite deleteOne with hints succeeds on server >= 4.4", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 2 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "BulkWrite_delete_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": "_id_", + "limit": 1 + }, + { + "q": { + "_id": 2 + }, + "hint": { + "_id": 1 + }, + "limit": 1 + } + ], + "ordered": true + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged bulkWrite deleteMany with hints succeeds on server >= 4.4", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_" + } + }, + { + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "BulkWrite_delete_hint", + "deletes": [ + { + "q": { + "_id": { + "$lt": 3 + } + }, + "hint": "_id_", + "limit": 0 + }, + { + "q": { + "_id": { + "$gte": 4 + } + }, + "hint": { + "_id": 1 + }, + "limit": 0 + } + ], + "ordered": true + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-bulkWrite-update-hint-clientError.json b/data/crud/v2/unacknowledged-bulkWrite-update-hint-clientError.json new file mode 100644 index 0000000000..93c46f82ea --- /dev/null +++ b/data/crud/v2/unacknowledged-bulkWrite-update-hint-clientError.json @@ -0,0 +1,250 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.1.9" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "Bulkwrite_update_hint", + "tests": [ + { + "description": "Unacknowledged bulkWrite updateOne with hints fails with client-side error on server < 4.2", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "Unacknowledged bulkWrite updateMany with hints fails with client-side error on server < 4.2", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + }, + { + "description": "Unacknowledged bulkWrite replaceOne with hints unsupported (client-side error)", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 333 + }, + "hint": "_id_" + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-bulkWrite-update-hint.json b/data/crud/v2/unacknowledged-bulkWrite-update-hint.json new file mode 100644 index 0000000000..eaba364e95 --- /dev/null +++ b/data/crud/v2/unacknowledged-bulkWrite-update-hint.json @@ -0,0 +1,291 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ], + "collection_name": "BulkWrite_update_hint", + "tests": [ + { + "description": "Unacknowledged bulkWrite updateOne with update hint succeeds on server >= 4.2", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "BulkWrite_update_hint", + "updates": [ + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + { + "q": { + "_id": 1 + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged bulkWrite updateMany with update hint succeeds on server >= 4.2", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + }, + { + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$lt": 3 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "BulkWrite_update_hint", + "updates": [ + { + "q": { + "_id": { + "$lt": 3 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": "_id_" + }, + { + "q": { + "_id": { + "$lt": 3 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged bulkWrite replaceOne with update hints", + "operations": [ + { + "name": "bulkWrite", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "arguments": { + "requests": [ + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 3 + }, + "replacement": { + "x": 333 + }, + "hint": "_id_" + } + }, + { + "name": "replaceOne", + "arguments": { + "filter": { + "_id": 4 + }, + "replacement": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + } + ], + "options": { + "ordered": true + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "BulkWrite_update_hint", + "updates": [ + { + "q": { + "_id": 3 + }, + "u": { + "x": 333 + }, + "hint": "_id_" + }, + { + "q": { + "_id": 4 + }, + "u": { + "x": 444 + }, + "hint": { + "_id": 1 + } + } + ], + "ordered": true + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-deleteMany-hint-clientError.json b/data/crud/v2/unacknowledged-deleteMany-hint-clientError.json new file mode 100644 index 0000000000..903340bf01 --- /dev/null +++ b/data/crud/v2/unacknowledged-deleteMany-hint-clientError.json @@ -0,0 +1,110 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "DeleteMany_hint", + "tests": [ + { + "description": "Unacknowledged deleteMany with hint string fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + }, + { + "description": "Unacknowledged deleteMany with hint document fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-deleteMany-hint.json b/data/crud/v2/unacknowledged-deleteMany-hint.json new file mode 100644 index 0000000000..485fd61985 --- /dev/null +++ b/data/crud/v2/unacknowledged-deleteMany-hint.json @@ -0,0 +1,114 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "DeleteMany_hint", + "tests": [ + { + "description": "Unacknowledged deleteMany with hint string succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteMany_hint", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_", + "limit": 0 + } + ] + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged deleteMany with hint document succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteMany_hint", + "deletes": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "hint": { + "_id": 1 + }, + "limit": 0 + } + ] + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-deleteOne-hint-clientError.json b/data/crud/v2/unacknowledged-deleteOne-hint-clientError.json new file mode 100644 index 0000000000..11e0b883cb --- /dev/null +++ b/data/crud/v2/unacknowledged-deleteOne-hint-clientError.json @@ -0,0 +1,94 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "DeleteOne_hint", + "tests": [ + { + "description": "Unacknowledged deleteOne with hint string fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "Unacknowledged deleteOne with hint document fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-deleteOne-hint.json b/data/crud/v2/unacknowledged-deleteOne-hint.json new file mode 100644 index 0000000000..bd9443d4f7 --- /dev/null +++ b/data/crud/v2/unacknowledged-deleteOne-hint.json @@ -0,0 +1,102 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "DeleteOne_hint", + "tests": [ + { + "description": "Unacknowledged deleteOne with hint string succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteOne_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": "_id_", + "limit": 1 + } + ] + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged deleteOne with hint document succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "deleteOne", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "delete": "DeleteOne_hint", + "deletes": [ + { + "q": { + "_id": 1 + }, + "hint": { + "_id": 1 + }, + "limit": 1 + } + ] + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-findOneAndDelete-hint-clientError.json b/data/crud/v2/unacknowledged-findOneAndDelete-hint-clientError.json new file mode 100644 index 0000000000..1c4423d3c3 --- /dev/null +++ b/data/crud/v2/unacknowledged-findOneAndDelete-hint-clientError.json @@ -0,0 +1,94 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "findOneAndDelete_hint", + "tests": [ + { + "description": "Unacknowledged findOneAndDelete with hint string fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "Unacknowledged findOneAndDelete with hint document fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-findOneAndDelete-hint.json b/data/crud/v2/unacknowledged-findOneAndDelete-hint.json new file mode 100644 index 0000000000..9dce1ae9d8 --- /dev/null +++ b/data/crud/v2/unacknowledged-findOneAndDelete-hint.json @@ -0,0 +1,94 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "findOneAndDelete_hint", + "tests": [ + { + "description": "Unacknowledged findOneAndDelete with hint string succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "findOneAndDelete_hint", + "query": { + "_id": 1 + }, + "hint": "_id_", + "remove": true + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged findOneAndDelete with hint document succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndDelete", + "arguments": { + "filter": { + "_id": 1 + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "findOneAndDelete_hint", + "query": { + "_id": 1 + }, + "hint": { + "_id": 1 + }, + "remove": true + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-findOneAndReplace-hint-clientError.json b/data/crud/v2/unacknowledged-findOneAndReplace-hint-clientError.json new file mode 100644 index 0000000000..0379e7946e --- /dev/null +++ b/data/crud/v2/unacknowledged-findOneAndReplace-hint-clientError.json @@ -0,0 +1,100 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "FindOneAndReplace_hint", + "tests": [ + { + "description": "Unacknowledged findOneAndReplace with hint string fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "x": 33 + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "Unacknowledged findOneAndReplace with hint document fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "x": 33 + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-findOneAndReplace-hint.json b/data/crud/v2/unacknowledged-findOneAndReplace-hint.json new file mode 100644 index 0000000000..7c3e55e046 --- /dev/null +++ b/data/crud/v2/unacknowledged-findOneAndReplace-hint.json @@ -0,0 +1,101 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "FindOneAndReplace_hint", + "tests": [ + { + "description": "Unacknowledged findOneAndReplace with hint string succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "x": 33 + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "FindOneAndReplace_hint", + "query": { + "_id": 1 + }, + "update": { + "x": 33 + }, + "hint": "_id_" + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged findOneAndReplace with hint document succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndReplace", + "arguments": { + "filter": { + "_id": 1 + }, + "replacement": { + "x": 33 + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "FindOneAndReplace_hint", + "query": { + "_id": 1 + }, + "update": { + "x": 33 + } + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-findOneAndUpdate-hint-clientError.json b/data/crud/v2/unacknowledged-findOneAndUpdate-hint-clientError.json new file mode 100644 index 0000000000..14e1fb6da4 --- /dev/null +++ b/data/crud/v2/unacknowledged-findOneAndUpdate-hint-clientError.json @@ -0,0 +1,104 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.3.3" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "FindOneAndUpdate_hint", + "tests": [ + { + "description": "Unacknowledged findOneAndUpdate with hint string fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "Unacknowledged findOneAndUpdate with hint document fails with client-side error on server < 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-findOneAndUpdate-hint.json b/data/crud/v2/unacknowledged-findOneAndUpdate-hint.json new file mode 100644 index 0000000000..383ca6ad6d --- /dev/null +++ b/data/crud/v2/unacknowledged-findOneAndUpdate-hint.json @@ -0,0 +1,112 @@ +{ + "runOn": [ + { + "minServerVersion": "4.3.4" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "FindOneAndUpdate_hint", + "tests": [ + { + "description": "Unacknowledged findOneAndUpdate with hint string succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "FindOneAndUpdate_hint", + "query": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged findOneAndUpdate with hint document succeeds on server >= 4.4", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "findAndModify": "FindOneAndUpdate_hint", + "query": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-replaceOne-hint-clientError.json b/data/crud/v2/unacknowledged-replaceOne-hint-clientError.json new file mode 100644 index 0000000000..f442953f2d --- /dev/null +++ b/data/crud/v2/unacknowledged-replaceOne-hint-clientError.json @@ -0,0 +1,104 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.1.9" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "ReplaceOne_hint", + "tests": [ + { + "description": "Unacknowledged ReplaceOne with hint string fails with client-side error on server < 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "Unacknowledged ReplaceOne with hint document fails with client-side error on server < 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-replaceOne-hint.json b/data/crud/v2/unacknowledged-replaceOne-hint.json new file mode 100644 index 0000000000..1d896bfb57 --- /dev/null +++ b/data/crud/v2/unacknowledged-replaceOne-hint.json @@ -0,0 +1,120 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "Replaceone_hint", + "tests": [ + { + "description": "Unacknowledged replaceOne with hint string succeeds on server >= 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "Replaceone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged replaceOne with hint document succeeds on server >= 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "replaceOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "replacement": { + "x": 111 + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "Replaceone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 111 + }, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-updateMany-hint-clientError.json b/data/crud/v2/unacknowledged-updateMany-hint-clientError.json new file mode 100644 index 0000000000..9425d542eb --- /dev/null +++ b/data/crud/v2/unacknowledged-updateMany-hint-clientError.json @@ -0,0 +1,120 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.1.9" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "Updatemany_hint", + "tests": [ + { + "description": "Unacknowledged updateMany with hint string fails with client-side error on server < 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + }, + { + "description": "Unacknowledged updateMany with hint document fails with client-side error on server < 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-updateMany-hint.json b/data/crud/v2/unacknowledged-updateMany-hint.json new file mode 100644 index 0000000000..d601a1b709 --- /dev/null +++ b/data/crud/v2/unacknowledged-updateMany-hint.json @@ -0,0 +1,134 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "UpdateMany_hint", + "tests": [ + { + "description": "Unacknowledged updateMany with hint string succeeds on server >= 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "UpdateMany_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged updateMany with hint document succeeds on server >= 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "UpdateMany_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/unacknowledged-updateOne-hint-clientError.json b/data/crud/v2/unacknowledged-updateOne-hint-clientError.json new file mode 100644 index 0000000000..bce3add675 --- /dev/null +++ b/data/crud/v2/unacknowledged-updateOne-hint-clientError.json @@ -0,0 +1,108 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.1.9" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "Updateone_hint", + "tests": [ + { + "description": "Unacknowledged updateOne with hint string fails with client-side error on server < 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "Unacknowledged updateOne with hint document fails with client-side error on server < 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": {}, + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/unacknowledged-updateOne-hint.json b/data/crud/v2/unacknowledged-updateOne-hint.json new file mode 100644 index 0000000000..ca2f57f621 --- /dev/null +++ b/data/crud/v2/unacknowledged-updateOne-hint.json @@ -0,0 +1,128 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "updateone_hint", + "tests": [ + { + "description": "Unacknowledged updateOne with hint string succeeds on server >= 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "updateone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": {} + }, + { + "description": "Unacknowledged updateOne with hint document succeeds on server >= 4.2", + "operations": [ + { + "object": "collection", + "collectionOptions": { + "writeConcern": { + "w": 0 + } + }, + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "updateone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": {} + } + ] +} diff --git a/data/crud/v2/updateMany-hint-clientError.json b/data/crud/v2/updateMany-hint-clientError.json new file mode 100644 index 0000000000..44ebddc53d --- /dev/null +++ b/data/crud/v2/updateMany-hint-clientError.json @@ -0,0 +1,110 @@ +{ + "runOn": [ + { + "maxServerVersion": "3.3.99" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "test_updatemany_hint", + "tests": [ + { + "description": "UpdateMany with hint string unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + }, + { + "description": "UpdateMany with hint document unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/updateMany-hint-serverError.json b/data/crud/v2/updateMany-hint-serverError.json new file mode 100644 index 0000000000..86f21246e9 --- /dev/null +++ b/data/crud/v2/updateMany-hint-serverError.json @@ -0,0 +1,161 @@ +{ + "runOn": [ + { + "minServerVersion": "3.4.0", + "maxServerVersion": "4.1.9" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "test_updatemany_hint", + "tests": [ + { + "description": "UpdateMany with hint string unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updatemany_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + }, + { + "description": "UpdateMany with hint document unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updatemany_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/updateMany-hint.json b/data/crud/v2/updateMany-hint.json new file mode 100644 index 0000000000..489348917f --- /dev/null +++ b/data/crud/v2/updateMany-hint.json @@ -0,0 +1,168 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ], + "collection_name": "test_updatemany_hint", + "tests": [ + { + "description": "UpdateMany with hint string", + "operations": [ + { + "object": "collection", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "result": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updatemany_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 34 + } + ] + } + } + }, + { + "description": "UpdateMany with hint document", + "operations": [ + { + "object": "collection", + "name": "updateMany", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "result": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updatemany_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "multi": true, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + }, + { + "_id": 3, + "x": 34 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/updateMany-hint.yml b/data/crud/v2/updateMany-hint.yml new file mode 100644 index 0000000000..57067f0778 --- /dev/null +++ b/data/crud/v2/updateMany-hint.yml @@ -0,0 +1,65 @@ +runOn: + - { minServerVersion: "4.2.0" } + +data: + - {_id: 1, x: 11} + - {_id: 2, x: 22} + - {_id: 3, x: 33} + +collection_name: &collection_name 'test_updatemany_hint' + +tests: + - + description: "UpdateMany with hint string" + operations: + - + object: collection + name: updateMany + arguments: + filter: &filter { _id: { $gt: 1 } } + update: &update { $inc: { x: 1 } } + hint: "_id_" + result: &result + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *filter + u: *update + multi: true + hint: "_id_" + outcome: &outcome + collection: + data: + - { _id: 1, x: 11 } + - { _id: 2, x: 23 } + - { _id: 3, x: 34 } + - + description: "UpdateMany with hint document" + operations: + - + object: collection + name: updateMany + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + result: *result + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *filter + u: *update + multi: true + hint: { _id: 1 } + outcome: *outcome diff --git a/data/crud/v2/updateOne-hint-clientError.json b/data/crud/v2/updateOne-hint-clientError.json new file mode 100644 index 0000000000..82bfe368c7 --- /dev/null +++ b/data/crud/v2/updateOne-hint-clientError.json @@ -0,0 +1,98 @@ +{ + "runOn": [ + { + "maxServerVersion": "3.3.99" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "test_updateone_hint", + "tests": [ + { + "description": "UpdateOne with hint string unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "UpdateOne with hint document unsupported (client-side error)", + "operations": [ + { + "object": "collection", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/updateOne-hint-serverError.json b/data/crud/v2/updateOne-hint-serverError.json new file mode 100644 index 0000000000..8e8037eb8c --- /dev/null +++ b/data/crud/v2/updateOne-hint-serverError.json @@ -0,0 +1,147 @@ +{ + "runOn": [ + { + "minServerVersion": "3.4.0", + "maxServerVersion": "4.1.9" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "test_updateone_hint", + "tests": [ + { + "description": "UpdateOne with hint string unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updateone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + }, + { + "description": "UpdateOne with hint document unsupported (server-side error)", + "operations": [ + { + "object": "collection", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "error": true + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updateone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/updateOne-hint.json b/data/crud/v2/updateOne-hint.json new file mode 100644 index 0000000000..43f76da498 --- /dev/null +++ b/data/crud/v2/updateOne-hint.json @@ -0,0 +1,154 @@ +{ + "runOn": [ + { + "minServerVersion": "4.2.0" + } + ], + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ], + "collection_name": "test_updateone_hint", + "tests": [ + { + "description": "UpdateOne with hint string", + "operations": [ + { + "object": "collection", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updateone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": "_id_" + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + } + ] + } + } + }, + { + "description": "UpdateOne with hint document", + "operations": [ + { + "object": "collection", + "name": "updateOne", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "update": "test_updateone_hint", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "hint": { + "_id": 1 + } + } + ] + } + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 23 + } + ] + } + } + } + ] +} diff --git a/data/crud/v2/updateOne-hint.yml b/data/crud/v2/updateOne-hint.yml new file mode 100644 index 0000000000..cb86da9475 --- /dev/null +++ b/data/crud/v2/updateOne-hint.yml @@ -0,0 +1,61 @@ +runOn: + - { minServerVersion: "4.2.0" } + +data: + - {_id: 1, x: 11} + - {_id: 2, x: 22} + +collection_name: &collection_name 'test_updateone_hint' + +tests: + - + description: "UpdateOne with hint string" + operations: + - + object: collection + name: updateOne + arguments: + filter: &filter { _id: { $gt: 1 } } + update: &update { $inc: { x: 1 } } + hint: "_id_" + result: &result + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *filter + u: *update + hint: "_id_" + outcome: &outcome + collection: + data: + - {_id: 1, x: 11 } + - {_id: 2, x: 23 } + - + description: "UpdateOne with hint document" + operations: + - + object: collection + name: updateOne + arguments: + filter: *filter + update: *update + hint: { _id: 1 } + result: *result + expectations: + - + command_started_event: + command: + update: *collection_name + updates: + - + q: *filter + u: *update + hint: { _id: 1 } + outcome: *outcome diff --git a/src/mongocxx/bulk_write.cpp b/src/mongocxx/bulk_write.cpp index f098b841a1..c569c54605 100644 --- a/src/mongocxx/bulk_write.cpp +++ b/src/mongocxx/bulk_write.cpp @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include - #include #include #include +#include #include +#include #include #include #include @@ -28,8 +28,6 @@ #include #include -#include - namespace mongocxx { MONGOCXX_INLINE_NAMESPACE_BEGIN @@ -61,6 +59,9 @@ bulk_write& bulk_write::append(const model::write& operation) { if (operation.get_update_one().collation()) { options_builder.append(kvp("collation", *operation.get_update_one().collation())); } + if (operation.get_update_one().hint()) { + options_builder.append(kvp("hint", *operation.get_update_one().hint())); + } if (operation.get_update_one().upsert()) { options_builder.append(kvp("upsert", *operation.get_update_one().upsert())); } @@ -86,6 +87,9 @@ bulk_write& bulk_write::append(const model::write& operation) { if (operation.get_update_many().collation()) { options_builder.append(kvp("collation", *operation.get_update_many().collation())); } + if (operation.get_update_many().hint()) { + options_builder.append(kvp("hint", *operation.get_update_many().hint())); + } if (operation.get_update_many().upsert()) { options_builder.append(kvp("upsert", *operation.get_update_many().upsert())); } @@ -110,6 +114,9 @@ bulk_write& bulk_write::append(const model::write& operation) { if (operation.get_delete_one().collation()) { options_builder.append(kvp("collation", *operation.get_delete_one().collation())); } + if (operation.get_delete_one().hint()) { + options_builder.append(kvp("hint", *operation.get_delete_one().hint())); + } scoped_bson_t options(options_builder.extract()); bson_error_t error; @@ -127,6 +134,9 @@ bulk_write& bulk_write::append(const model::write& operation) { if (operation.get_delete_many().collation()) { options_builder.append(kvp("collation", *operation.get_delete_many().collation())); } + if (operation.get_delete_many().hint()) { + options_builder.append(kvp("hint", *operation.get_delete_many().hint())); + } scoped_bson_t options(options_builder.extract()); bson_error_t error; @@ -145,6 +155,9 @@ bulk_write& bulk_write::append(const model::write& operation) { if (operation.get_replace_one().collation()) { options_builder.append(kvp("collation", *operation.get_replace_one().collation())); } + if (operation.get_replace_one().hint()) { + options_builder.append(kvp("hint", *operation.get_replace_one().hint())); + } if (operation.get_replace_one().upsert()) { options_builder.append(kvp("upsert", *operation.get_replace_one().upsert())); } diff --git a/src/mongocxx/collection.cpp b/src/mongocxx/collection.cpp index 57d05db3ff..ecfed8a207 100644 --- a/src/mongocxx/collection.cpp +++ b/src/mongocxx/collection.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -29,13 +28,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -45,24 +42,20 @@ #include #include #include -#include #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -584,6 +577,9 @@ stdx::optional collection::_replace_one(const client_sessio if (options.collation()) { replace_op.collation(*options.collation()); } + if (options.hint()) { + replace_op.hint(*options.hint()); + } if (options.upsert()) { replace_op.upsert(*options.upsert()); } @@ -623,6 +619,9 @@ stdx::optional collection::_update_many(const client_session* se if (options.collation()) { update_op.collation(*options.collation()); } + if (options.hint()) { + update_op.hint(*options.hint()); + } if (options.upsert()) { update_op.upsert(*options.upsert()); } @@ -700,6 +699,9 @@ stdx::optional collection::_update_one(const client_session* ses if (options.collation()) { update_op.collation(*options.collation()); } + if (options.hint()) { + update_op.hint(*options.hint()); + } if (options.upsert()) { update_op.upsert(*options.upsert()); } @@ -772,6 +774,9 @@ stdx::optional collection::_delete_many( if (options.collation()) { delete_op.collation(*options.collation()); } + if (options.hint()) { + delete_op.hint(*options.hint()); + } bulk_op.append(delete_op); auto result = bulk_op.execute(); @@ -806,6 +811,9 @@ stdx::optional collection::_delete_one( if (options.collation()) { delete_op.collation(*options.collation()); } + if (options.hint()) { + delete_op.hint(*options.hint()); + } bulk_op.append(delete_op); auto result = bulk_op.execute(); @@ -943,7 +951,7 @@ stdx::optional collection::_find_one_and_delete( MONGOC_FIND_AND_MODIFY_REMOVE, false, stdx::nullopt, - stdx::nullopt, + options.hint(), options); } diff --git a/src/mongocxx/collection.hpp b/src/mongocxx/collection.hpp index c0321e469e..2f94674faf 100644 --- a/src/mongocxx/collection.hpp +++ b/src/mongocxx/collection.hpp @@ -15,10 +15,6 @@ #pragma once #include -#include -#include -#include - #include #include #include @@ -30,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -59,8 +56,7 @@ #include #include #include - -#include +#include namespace mongocxx { MONGOCXX_INLINE_NAMESPACE_BEGIN diff --git a/src/mongocxx/model/delete_many.cpp b/src/mongocxx/model/delete_many.cpp index a4a48d82c8..eb3d3ab0a2 100644 --- a/src/mongocxx/model/delete_many.cpp +++ b/src/mongocxx/model/delete_many.cpp @@ -31,6 +31,15 @@ delete_many& delete_many::collation(bsoncxx::document::view_or_value collation) return *this; } +delete_many& delete_many::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + +const stdx::optional& delete_many::hint() const { + return _hint; +} + const stdx::optional& delete_many::collation() const { return _collation; } diff --git a/src/mongocxx/model/delete_many.hpp b/src/mongocxx/model/delete_many.hpp index 19ccc5068d..d9e1b7c6ba 100644 --- a/src/mongocxx/model/delete_many.hpp +++ b/src/mongocxx/model/delete_many.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -70,10 +71,32 @@ class MONGOCXX_API delete_many { /// const stdx::optional& collation() const; + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + delete_many& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + private: bsoncxx::document::view_or_value _filter; stdx::optional _collation; + stdx::optional _hint; }; } // namespace model diff --git a/src/mongocxx/model/delete_one.cpp b/src/mongocxx/model/delete_one.cpp index 98af866ee1..fa037f0272 100644 --- a/src/mongocxx/model/delete_one.cpp +++ b/src/mongocxx/model/delete_one.cpp @@ -35,6 +35,15 @@ const stdx::optional& delete_one::collation() return _collation; } +delete_one& delete_one::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + +const stdx::optional& delete_one::hint() const { + return _hint; +} + } // namespace model MONGOCXX_INLINE_NAMESPACE_END } // namespace mongocxx diff --git a/src/mongocxx/model/delete_one.hpp b/src/mongocxx/model/delete_one.hpp index 49fb2e24fe..340001d941 100644 --- a/src/mongocxx/model/delete_one.hpp +++ b/src/mongocxx/model/delete_one.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -66,10 +67,33 @@ class MONGOCXX_API delete_one { /// const stdx::optional& collation() const; + /// + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + delete_one& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + private: bsoncxx::document::view_or_value _filter; stdx::optional _collation; + stdx::optional _hint; }; } // namespace model diff --git a/src/mongocxx/model/replace_one.cpp b/src/mongocxx/model/replace_one.cpp index 85dd8fd502..596f7a453f 100644 --- a/src/mongocxx/model/replace_one.cpp +++ b/src/mongocxx/model/replace_one.cpp @@ -51,6 +51,14 @@ const stdx::optional& replace_one::upsert() const { return _upsert; } +replace_one& replace_one::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + +const stdx::optional& replace_one::hint() const { + return _hint; +} } // namespace model MONGOCXX_INLINE_NAMESPACE_END } // namespace mongocxx diff --git a/src/mongocxx/model/replace_one.hpp b/src/mongocxx/model/replace_one.hpp index 6981d7a482..5ed2cdb2f3 100644 --- a/src/mongocxx/model/replace_one.hpp +++ b/src/mongocxx/model/replace_one.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -98,12 +99,35 @@ class MONGOCXX_API replace_one { /// const stdx::optional& upsert() const; + /// + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + replace_one& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + private: bsoncxx::document::view_or_value _filter; bsoncxx::document::view_or_value _replacement; stdx::optional _collation; stdx::optional _upsert; + stdx::optional _hint; }; } // namespace model diff --git a/src/mongocxx/model/update_many.cpp b/src/mongocxx/model/update_many.cpp index a05b5248aa..ed916e0bc6 100644 --- a/src/mongocxx/model/update_many.cpp +++ b/src/mongocxx/model/update_many.cpp @@ -49,6 +49,15 @@ const stdx::optional& update_many::collation() return _collation; } +update_many& update_many::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + +const stdx::optional& update_many::hint() const { + return _hint; +} + update_many& update_many::upsert(bool upsert) { _upsert = upsert; return *this; diff --git a/src/mongocxx/model/update_many.hpp b/src/mongocxx/model/update_many.hpp index b35e9a5939..32cab496c6 100644 --- a/src/mongocxx/model/update_many.hpp +++ b/src/mongocxx/model/update_many.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,27 @@ class MONGOCXX_API update_many { /// const stdx::optional& collation() const; + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + update_many& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + /// /// Sets the upsert option. /// @@ -170,6 +192,7 @@ class MONGOCXX_API update_many { stdx::optional _collation; stdx::optional _array_filters; stdx::optional _upsert; + stdx::optional _hint; }; } // namespace model diff --git a/src/mongocxx/model/update_one.cpp b/src/mongocxx/model/update_one.cpp index d0637584df..42a67a6625 100644 --- a/src/mongocxx/model/update_one.cpp +++ b/src/mongocxx/model/update_one.cpp @@ -49,6 +49,15 @@ const stdx::optional& update_one::collation() return _collation; } +update_one& update_one::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + +const stdx::optional& update_one::hint() const { + return _hint; +} + update_one& update_one::upsert(bool upsert) { _upsert = upsert; return *this; diff --git a/src/mongocxx/model/update_one.hpp b/src/mongocxx/model/update_one.hpp index 4dfdb4f3cd..a1c2cfb072 100644 --- a/src/mongocxx/model/update_one.hpp +++ b/src/mongocxx/model/update_one.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,28 @@ class MONGOCXX_API update_one { /// const stdx::optional& collation() const; + /// + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + update_one& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + /// /// Sets the upsert option. /// @@ -170,6 +193,7 @@ class MONGOCXX_API update_one { stdx::optional _collation; stdx::optional _array_filters; stdx::optional _upsert; + stdx::optional _hint; }; } // namespace model diff --git a/src/mongocxx/options/delete.cpp b/src/mongocxx/options/delete.cpp index 3f4421358c..03438ed50d 100644 --- a/src/mongocxx/options/delete.cpp +++ b/src/mongocxx/options/delete.cpp @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include - #include +#include +#include namespace mongocxx { MONGOCXX_INLINE_NAMESPACE_BEGIN @@ -30,6 +30,11 @@ delete_options& delete_options::write_concern(class write_concern wc) { return *this; } +delete_options& delete_options::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + const stdx::optional& delete_options::collation() const { return _collation; } @@ -38,6 +43,10 @@ const stdx::optional& delete_options::write_concern() const return _write_concern; } +const stdx::optional& delete_options::hint() const { + return _hint; +} + } // namespace options MONGOCXX_INLINE_NAMESPACE_END } // namespace mongocxx diff --git a/src/mongocxx/options/delete.hpp b/src/mongocxx/options/delete.hpp index 06ca3a1464..715f8d42b6 100644 --- a/src/mongocxx/options/delete.hpp +++ b/src/mongocxx/options/delete.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -80,9 +81,32 @@ class MONGOCXX_API delete_options { /// const stdx::optional& write_concern() const; + /// + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + delete_options& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + private: stdx::optional _collation; stdx::optional _write_concern; + stdx::optional _hint; }; } // namespace options diff --git a/src/mongocxx/options/find_one_and_delete.cpp b/src/mongocxx/options/find_one_and_delete.cpp index 73cf95ac2c..a93019ebf3 100644 --- a/src/mongocxx/options/find_one_and_delete.cpp +++ b/src/mongocxx/options/find_one_and_delete.cpp @@ -45,6 +45,15 @@ find_one_and_delete& find_one_and_delete::write_concern(mongocxx::write_concern return *this; } +find_one_and_delete& find_one_and_delete::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + +const stdx::optional& find_one_and_delete::hint() const { + return _hint; +} + const stdx::optional& find_one_and_delete::collation() const { return _collation; } diff --git a/src/mongocxx/options/find_one_and_delete.hpp b/src/mongocxx/options/find_one_and_delete.hpp index 564845d644..94e22fa43a 100644 --- a/src/mongocxx/options/find_one_and_delete.hpp +++ b/src/mongocxx/options/find_one_and_delete.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -153,12 +154,35 @@ class MONGOCXX_API find_one_and_delete { /// const stdx::optional& write_concern() const; + /// + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + find_one_and_delete& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + private: stdx::optional _collation; stdx::optional _max_time; stdx::optional _projection; stdx::optional _ordering; stdx::optional _write_concern; + stdx::optional _hint; }; } // namespace options diff --git a/src/mongocxx/options/replace.cpp b/src/mongocxx/options/replace.cpp index 70c5533857..11cedb7e13 100644 --- a/src/mongocxx/options/replace.cpp +++ b/src/mongocxx/options/replace.cpp @@ -27,6 +27,11 @@ replace& replace::bypass_document_validation(bool bypass_document_validation) { return *this; } +replace& replace::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + replace& replace::collation(bsoncxx::document::view_or_value collation) { _collation = std::move(collation); return *this; @@ -42,6 +47,10 @@ replace& replace::write_concern(class write_concern wc) { return *this; } +const stdx::optional& replace::hint() const { + return _hint; +} + const stdx::optional& replace::bypass_document_validation() const { return _bypass_document_validation; } diff --git a/src/mongocxx/options/replace.hpp b/src/mongocxx/options/replace.hpp index 3ef0f23f87..7f6e284214 100644 --- a/src/mongocxx/options/replace.hpp +++ b/src/mongocxx/options/replace.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -130,11 +131,34 @@ class MONGOCXX_API replace { /// const stdx::optional& write_concern() const; + /// + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + replace& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + private: stdx::optional _bypass_document_validation; stdx::optional _collation; stdx::optional _upsert; stdx::optional _write_concern; + stdx::optional _hint; }; } // namespace options diff --git a/src/mongocxx/options/update.cpp b/src/mongocxx/options/update.cpp index 977122d2f1..cca8da43c8 100644 --- a/src/mongocxx/options/update.cpp +++ b/src/mongocxx/options/update.cpp @@ -32,6 +32,11 @@ update& update::collation(bsoncxx::document::view_or_value collation) { return *this; } +update& update::hint(class hint index_hint) { + _hint = std::move(index_hint); + return *this; +} + update& update::upsert(bool upsert) { _upsert = upsert; return *this; @@ -50,6 +55,10 @@ const stdx::optional& update::collation() cons return _collation; } +const stdx::optional& update::hint() const { + return _hint; +} + const stdx::optional& update::upsert() const { return _upsert; } diff --git a/src/mongocxx/options/update.hpp b/src/mongocxx/options/update.hpp index 06c3bb56f6..7e39bdcc7b 100644 --- a/src/mongocxx/options/update.hpp +++ b/src/mongocxx/options/update.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,28 @@ class MONGOCXX_API update { /// const stdx::optional& collation() const; + /// + /// Sets the index to use for this operation. + /// + /// @note if the server already has a cached shape for this query, it may + /// ignore a hint. + /// + /// @param index_hint + /// Object representing the index to use. + /// + /// @return + /// A reference to the object on which this member function is being called. This facilitates + /// method chaining. + /// + update& hint(class hint index_hint); + + /// + /// Gets the current hint. + /// + /// @return The current hint, if one is set. + /// + const stdx::optional& hint() const; + /// /// Sets the upsert option. /// @@ -160,6 +183,7 @@ class MONGOCXX_API update { stdx::optional _upsert; stdx::optional _write_concern; stdx::optional _array_filters; + stdx::optional _hint; }; } // namespace options diff --git a/src/mongocxx/test/collection_mocked.cpp b/src/mongocxx/test/collection_mocked.cpp index 673ab6543f..2f108683c4 100644 --- a/src/mongocxx/test/collection_mocked.cpp +++ b/src/mongocxx/test/collection_mocked.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -468,6 +466,7 @@ TEST_CASE("Collection", "[collection]") { auto expected_order_setting = false; auto expect_set_bypass_document_validation_called = false; auto expected_bypass_document_validation = false; + mongocxx::stdx::optional expected_hint{}; auto modification_doc = make_document(kvp("cool", "wow"), kvp("foo", "bar")); @@ -598,6 +597,12 @@ TEST_CASE("Collection", "[collection]") { } } + if (expected_hint) { + REQUIRE(options_view["hint"].get_utf8() == expected_hint->get_utf8()); + } else { + REQUIRE(!options_view["hint"]); + } + return true; }); @@ -617,6 +622,12 @@ TEST_CASE("Collection", "[collection]") { options.upsert(upsert_option); } + SECTION("With hint") { + hint index_hint("a_1"); + expected_hint = index_hint.to_value(); + options.hint(index_hint); + } + SECTION("With bypass_document_validation") { expect_set_bypass_document_validation_called = true; expected_bypass_document_validation = true; @@ -711,6 +722,12 @@ TEST_CASE("Collection", "[collection]") { } } + if (expected_hint) { + REQUIRE(options_view["hint"].get_utf8() == expected_hint->get_utf8()); + } else { + REQUIRE(!options_view["hint"]); + } + return true; }); @@ -730,6 +747,12 @@ TEST_CASE("Collection", "[collection]") { options.upsert(upsert_option); } + SECTION("With hint") { + hint index_hint("a_1"); + expected_hint = index_hint.to_value(); + options.hint(index_hint); + } + mongo_coll.update_many(filter_doc.view(), modification_doc.view(), options); REQUIRE(bulk_operation_execute_called); perform_checks(); @@ -782,6 +805,12 @@ TEST_CASE("Collection", "[collection]") { } } + if (expected_hint) { + REQUIRE(options_view["hint"].get_utf8() == expected_hint->get_utf8()); + } else { + REQUIRE(!options_view["hint"]); + } + return true; }); @@ -801,6 +830,12 @@ TEST_CASE("Collection", "[collection]") { options.upsert(upsert_option); } + SECTION("With hint") { + hint index_hint("a_1"); + expected_hint = index_hint.to_value(); + options.hint(index_hint); + } + mongo_coll.replace_one(filter_doc.view(), modification_doc.view(), options); REQUIRE(bulk_operation_execute_called); perform_checks(); @@ -826,14 +861,29 @@ TEST_CASE("Collection", "[collection]") { SECTION("Delete One", "[collection::delete_one]") { expected_order_setting = true; - bulk_operation_remove_one_with_opts->interpose( - [&](mongoc_bulk_operation_t*, const bson_t* doc, const bson_t*, bson_error_t*) { - bulk_operation_op_called = true; - REQUIRE(bson_get_data(doc) == filter_doc.view().data()); - return true; - }); + bulk_operation_remove_one_with_opts->interpose([&]( + mongoc_bulk_operation_t*, const bson_t* doc, const bson_t* options, bson_error_t*) { + bulk_operation_op_called = true; + REQUIRE(bson_get_data(doc) == filter_doc.view().data()); - mongo_coll.delete_one(filter_doc.view()); + bsoncxx::document::view options_view{bson_get_data(options), options->len}; + if (expected_hint) { + CAPTURE(to_json(options_view)); + REQUIRE(options_view["hint"].get_utf8() == expected_hint->get_utf8()); + } else { + REQUIRE(!options_view["hint"]); + } + return true; + }); + + options::delete_options options; + SECTION("With hint") { + hint index_hint("a_1"); + expected_hint = index_hint.to_value(); + options.hint(index_hint); + } + + mongo_coll.delete_one(filter_doc.view(), options); REQUIRE(bulk_operation_execute_called); perform_checks(); } @@ -854,14 +904,29 @@ TEST_CASE("Collection", "[collection]") { SECTION("Delete Many", "[collection::delete_many]") { expected_order_setting = true; - bulk_operation_remove_many_with_opts->interpose( - [&](mongoc_bulk_operation_t*, const bson_t* doc, const bson_t*, bson_error_t*) { - bulk_operation_op_called = true; - REQUIRE(bson_get_data(doc) == filter_doc.view().data()); - return true; - }); + bulk_operation_remove_many_with_opts->interpose([&]( + mongoc_bulk_operation_t*, const bson_t* doc, const bson_t* options, bson_error_t*) { + bulk_operation_op_called = true; + REQUIRE(bson_get_data(doc) == filter_doc.view().data()); + + bsoncxx::document::view options_view{bson_get_data(options), options->len}; + if (expected_hint) { + CAPTURE(to_json(options_view)); + REQUIRE(options_view["hint"].get_utf8() == expected_hint->get_utf8()); + } else { + REQUIRE(!options_view["hint"]); + } + return true; + }); + + options::delete_options options; + SECTION("With hint") { + hint index_hint("a_1"); + expected_hint = index_hint.to_value(); + options.hint(index_hint); + } - mongo_coll.delete_many(filter_doc.view()); + mongo_coll.delete_many(filter_doc.view(), options); REQUIRE(bulk_operation_execute_called); perform_checks(); } diff --git a/src/mongocxx/test/spec/crud.cpp b/src/mongocxx/test/spec/crud.cpp index 7789e6368e..887624b649 100644 --- a/src/mongocxx/test/spec/crud.cpp +++ b/src/mongocxx/test/spec/crud.cpp @@ -59,107 +59,114 @@ void run_crud_tests_in_file(std::string test_path) { } for (auto&& test : test_spec_view["tests"].get_array().value) { - INFO("Test description: " << test["description"].get_utf8().value); - - if (is_unsupported(test["description"].get_utf8().value)) { - continue; - } - - if (should_skip_spec_test(client, test.get_document())) { - continue; - } + auto description = test["description"].get_utf8().value; + SECTION(to_string(description)) { + if (is_unsupported(test["description"].get_utf8().value)) { + continue; + } - auto get_value_or_default = [&](std::string key, std::string default_str) { - if (test_spec_view[key]) { - return to_string(test_spec_view[key].get_utf8().value); + if (should_skip_spec_test(client, test.get_document())) { + continue; } - return default_str; - }; - auto database_name = get_value_or_default("database_name", "crud_test"); - auto collection_name = get_value_or_default("collection_name", "test"); + auto get_value_or_default = [&](std::string key, std::string default_str) { + if (test_spec_view[key]) { + return to_string(test_spec_view[key].get_utf8().value); + } + return default_str; + }; - auto database = client[database_name]; - auto collection = database[collection_name]; + auto database_name = get_value_or_default("database_name", "crud_test"); + auto collection_name = get_value_or_default("collection_name", "test"); - if (test_spec_view["data"]) { - initialize_collection(&collection, test_spec_view["data"].get_array().value); - } + auto database = client[database_name]; + auto collection = database[collection_name]; - operation_runner op_runner{&database, &collection}; + if (test_spec_view["data"]) { + initialize_collection(&collection, test_spec_view["data"].get_array().value); + } - std::string outcome_collection_name = "test"; - if (test["outcome"] && test["outcome"]["collection"]["name"]) { - outcome_collection_name = - to_string(test["outcome"]["collection"]["name"].get_utf8().value); - auto outcome_collection = database[outcome_collection_name]; - initialize_collection(&outcome_collection, array::view{}); - } + operation_runner op_runner{&database, &collection}; - configure_fail_point(client, test.get_document().value); - - apm_checker.clear(); - auto perform_op = [&database, &op_runner, &test, &outcome_collection_name]( - document::view operation) { - optional actual_outcome_value; - INFO("Operation: " << bsoncxx::to_json(operation)); - try { - actual_outcome_value = op_runner.run(operation); - } catch (const mongocxx::operation_exception& e) { - REQUIRE([&operation, &test, &e]() { - if (operation["error"]) { /* v2 tests expect tests[i].operation.error */ - return operation["error"].get_bool().value; - } else if (test["outcome"] && test["outcome"]["error"]) { - /* v1 tests expect tests[i].outcome.error (but some tests may - have "outcome" without a nested "error") */ - return test["outcome"]["error"].get_bool().value; - } else { - WARN("Caught operation exception: " << e.what()); - return false; - } - }()); - return; /* do not check results if error is expected */ - } catch (const std::exception& e) { - WARN("Caught exception: " << e.what()); - } catch (...) { - WARN("Caught unknown exception"); + std::string outcome_collection_name = collection_name; + if (test["outcome"] && test["outcome"]["collection"]["name"]) { + outcome_collection_name = + to_string(test["outcome"]["collection"]["name"].get_utf8().value); + auto outcome_collection = database[outcome_collection_name]; + initialize_collection(&outcome_collection, array::view{}); } - if (test["outcome"]) { - if (test["outcome"]["collection"]) { - auto outcome_collection = database[outcome_collection_name]; - test_util::check_outcome_collection( - &outcome_collection, test["outcome"]["collection"].get_document().value); - } + configure_fail_point(client, test.get_document().value); + + apm_checker.clear(); + auto perform_op = + [&database, &op_runner, &test, &outcome_collection_name](document::view operation) { + optional actual_outcome_value; + INFO("Operation: " << bsoncxx::to_json(operation)); + try { + actual_outcome_value = op_runner.run(operation); + } catch (const mongocxx::operation_exception& e) { + REQUIRE([&operation, &test, &e]() { + if (operation["error"]) { /* v2 tests expect tests[i].operation.error */ + return operation["error"].get_bool().value; + } else if (test["outcome"] && test["outcome"]["error"]) { + /* v1 tests expect tests[i].outcome.error (but some tests may + have "outcome" without a nested "error") */ + return test["outcome"]["error"].get_bool().value; + } else { + WARN("Caught operation exception: " << e.what()); + return false; + } + }()); + return; /* do not check results if error is expected */ + } catch (const std::exception& e) { + WARN("Caught exception: " << e.what()); + } catch (...) { + WARN("Caught unknown exception"); + } + + if (test["outcome"]) { + if (test["outcome"]["collection"]) { + auto outcome_collection = database[outcome_collection_name]; + test_util::check_outcome_collection( + &outcome_collection, + test["outcome"]["collection"].get_document().value); + } + + if (test["outcome"]["result"]) { + // wrap the result, since it might not be a document. + bsoncxx::document::view actual_outcome = actual_outcome_value->view(); + auto actual_result_wrapped = + make_document(kvp("result", actual_outcome["result"].get_value())); + auto expected_result_wrapped = + make_document(kvp("result", test["outcome"]["result"].get_value())); + REQUIRE_BSON_MATCHES(actual_result_wrapped, expected_result_wrapped); + } + } + }; - if (test["outcome"]["result"]) { - // wrap the result, since it might not be a document. - bsoncxx::document::view actual_outcome = actual_outcome_value->view(); - auto actual_result_wrapped = - make_document(kvp("result", actual_outcome["result"].get_value())); - auto expected_result_wrapped = - make_document(kvp("result", test["outcome"]["result"].get_value())); - REQUIRE_BSON_MATCHES(actual_result_wrapped, expected_result_wrapped); + if (test["operations"]) { + /* v2 tests expect a tests[i].operations array */ + for (auto&& operation : test["operations"].get_array().value) { + perform_op(operation.get_document().value); } + } else if (test["operation"]) { + /* v1 tests expect a single document, tests[i].operation */ + perform_op(test["operation"].get_document().value); } - }; - if (test["operations"]) { - /* v2 tests expect a tests[i].operations array */ - for (auto&& operation : test["operations"].get_array().value) { - perform_op(operation.get_document().value); + if (test["expectations"]) { + /* some tests use empty documents, instead of arrays */ + if (test["expectations"].type() == type::k_array) + apm_checker.compare(test["expectations"].get_array().value, true); + else + REQUIRE(test["expectations"].get_document().view().empty()); } - } else if (test["operation"]) { - /* v1 tests expect a single document, tests[i].operation */ - perform_op(test["operation"].get_document().value); - } - - if (test["expectations"]) { - apm_checker.compare(test["expectations"].get_array().value, true); - } - if (test["failPoint"]) { - disable_fail_point(client, test["failPoint"]["configureFailPoint"].get_utf8().value); + if (test["failPoint"]) { + disable_fail_point(client, + test["failPoint"]["configureFailPoint"].get_utf8().value); + } } } } diff --git a/src/mongocxx/test/spec/operation.cpp b/src/mongocxx/test/spec/operation.cpp index 740bcfc12f..eb6e56a9a1 100644 --- a/src/mongocxx/test/spec/operation.cpp +++ b/src/mongocxx/test/spec/operation.cpp @@ -14,16 +14,11 @@ #include -#include #include -#include -#include -#include #include #include #include -#include #include #include #include @@ -32,10 +27,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -47,16 +38,13 @@ #include #include #include -#include #include #include #include #include #include -#include #include -#include namespace mongocxx { MONGOCXX_INLINE_NAMESPACE_BEGIN @@ -330,6 +318,13 @@ document::value operation_runner::_run_delete_many(document::view operation) { options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + auto result = builder::basic::document{}; std::int32_t deleted_count = 0; @@ -360,6 +355,13 @@ document::value operation_runner::_run_delete_one(document::view operation) { options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + auto result = builder::basic::document{}; std::int32_t deleted_count = 0; @@ -390,6 +392,20 @@ document::value operation_runner::_run_find_one_and_delete(document::view operat options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + if (arguments["projection"]) { options.projection(arguments["projection"].get_document().value); } @@ -445,6 +461,13 @@ document::value operation_runner::_run_find_one_and_replace(document::view opera options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + if (arguments["projection"]) { options.projection(arguments["projection"].get_document().value); } @@ -498,6 +521,13 @@ document::value operation_runner::_run_find_one_and_update(document::view operat options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + if (arguments["projection"]) { options.projection(arguments["projection"].get_document().value); } @@ -647,6 +677,13 @@ document::value operation_runner::_run_replace_one(document::view operation) { options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + if (arguments["upsert"]) { options.upsert(arguments["upsert"].get_bool().value); } @@ -708,6 +745,13 @@ document::value operation_runner::_run_update_many(document::view operation) { options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } + if (arguments["upsert"]) { options.upsert(arguments["upsert"].get_bool().value); } @@ -793,6 +837,12 @@ document::value operation_runner::_run_update_one(document::view operation) { options.collation(arguments["collation"].get_document().value); } + if (arguments["hint"]) { + if (arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + options.hint(hint{arguments["hint"].get_utf8().value}); + else + options.hint(hint{arguments["hint"].get_document().value}); + } if (arguments["upsert"]) { options.upsert(arguments["upsert"].get_bool().value); } @@ -946,6 +996,13 @@ document::value operation_runner::_run_bulk_write(document::view operation) { if (operation_name.compare("updateOne") == 0) { auto update_one = _build_update_model(request_arguments); + if (request_arguments["hint"]) { + if (request_arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + update_one.hint(hint{request_arguments["hint"].get_utf8().value}); + else + update_one.hint(hint{request_arguments["hint"].get_document().value}); + } + if (request_arguments["collation"]) { update_one.collation(request_arguments["collation"].get_document().value); } @@ -962,6 +1019,13 @@ document::value operation_runner::_run_bulk_write(document::view operation) { } else if (operation_name.compare("updateMany") == 0) { auto update_many = _build_update_model(request_arguments); + if (request_arguments["hint"]) { + if (request_arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + update_many.hint(hint{request_arguments["hint"].get_utf8().value}); + else + update_many.hint(hint{request_arguments["hint"].get_document().value}); + } + if (request_arguments["collation"]) { update_many.collation(request_arguments["collation"].get_document().value); } @@ -979,6 +1043,13 @@ document::value operation_runner::_run_bulk_write(document::view operation) { document::view filter = request_arguments["filter"].get_document().value; document::view replacement = request_arguments["replacement"].get_document().value; model::replace_one replace_one(filter, replacement); + if (request_arguments["hint"]) { + if (request_arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + replace_one.hint(hint{request_arguments["hint"].get_utf8().value}); + else + replace_one.hint(hint{request_arguments["hint"].get_document().value}); + } + if (request_arguments["collation"]) { replace_one.collation(request_arguments["collation"].get_document().value); } @@ -995,6 +1066,13 @@ document::value operation_runner::_run_bulk_write(document::view operation) { } else if (operation_name.compare("deleteOne") == 0) { document::view filter = request_arguments["filter"].get_document().value; model::delete_one delete_one(filter); + if (request_arguments["hint"]) { + if (request_arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + delete_one.hint(hint{request_arguments["hint"].get_utf8().value}); + else + delete_one.hint(hint{request_arguments["hint"].get_document().value}); + } + if (request_arguments["collation"]) { delete_one.collation(request_arguments["collation"].get_document().value); } @@ -1003,6 +1081,13 @@ document::value operation_runner::_run_bulk_write(document::view operation) { } else if (operation_name.compare("deleteMany") == 0) { document::view filter = request_arguments["filter"].get_document().value; model::delete_many delete_many(filter); + if (request_arguments["hint"]) { + if (request_arguments["hint"].type() == bsoncxx::v_noabi::type::k_utf8) + delete_many.hint(hint{request_arguments["hint"].get_utf8().value}); + else + delete_many.hint(hint{request_arguments["hint"].get_document().value}); + } + if (request_arguments["collation"]) { delete_many.collation(request_arguments["collation"].get_document().value); } diff --git a/src/mongocxx/test_util/client_helpers.cpp b/src/mongocxx/test_util/client_helpers.cpp index 0347264dd2..b7d4611bce 100644 --- a/src/mongocxx/test_util/client_helpers.cpp +++ b/src/mongocxx/test_util/client_helpers.cpp @@ -389,42 +389,26 @@ std::string tolowercase(stdx::string_view view) { } void check_outcome_collection(mongocxx::collection* coll, bsoncxx::document::view expected) { - std::vector actual_data; - std::vector expected_data; - read_concern rc; rc.acknowledge_level(read_concern::level::k_local); auto old_rc = coll->read_concern(); coll->read_concern(rc); options::find options{}; - builder::basic::document sort{}; - sort.append(builder::basic::kvp("_id", 1)); - options.sort(sort.extract()); - - std::vector expected_docs{}; - for (auto&& ele : expected["data"].get_array().value) { - expected_docs.push_back(ele.get_document().value); - } - - auto it = expected_docs.begin(); - - for (auto&& doc : coll->find({}, options)) { - if (it == expected_docs.end()) { - FAIL("found more documents than expected."); - } - - auto next_expected = *it; - it++; - - REQUIRE_BSON_MATCHES(doc, next_expected); - } - + options.sort(make_document(kvp("_id", 1))); + + using namespace std; + cursor actual = coll->find({}, options); + auto expected_data = expected["data"].get_array().value; + REQUIRE(equal(begin(expected_data), + end(expected_data), + begin(actual), + [&](const bsoncxx::array::element& ele, const document::view& doc) { + REQUIRE_BSON_MATCHES(doc, ele.get_document().value); + return true; + })); + REQUIRE(begin(actual) == end(actual)); coll->read_concern(old_rc); - - if (it != expected_docs.end()) { - FAIL("Had more expected documents than we found."); - } } bool server_has_sessions(const client& conn) {