Commit 546f9282 authored by Jeremy Mikola's avatar Jeremy Mikola

Merge pull request #711

parents 23e32ddc 01df4415
...@@ -10,6 +10,15 @@ source: ...@@ -10,6 +10,15 @@ source:
file: apiargs-MongoDBCollection-common-option.yaml file: apiargs-MongoDBCollection-common-option.yaml
ref: collation ref: collation
--- ---
source:
file: apiargs-common-option.yaml
ref: hint
post: |
This option is available in MongoDB 4.4+ and will result in an exception at
execution time if specified for an older server version.
.. versionadded:: 1.7
---
source: source:
file: apiargs-common-option.yaml file: apiargs-common-option.yaml
ref: maxTimeMS ref: maxTimeMS
......
...@@ -16,6 +16,15 @@ source: ...@@ -16,6 +16,15 @@ source:
file: apiargs-MongoDBCollection-common-option.yaml file: apiargs-MongoDBCollection-common-option.yaml
ref: collation ref: collation
--- ---
source:
file: apiargs-common-option.yaml
ref: hint
post: |
This option is available in MongoDB 4.4+ and will result in an exception at
execution time if specified for an older server version.
.. versionadded:: 1.7
---
source: source:
file: apiargs-common-option.yaml file: apiargs-common-option.yaml
ref: maxTimeMS ref: maxTimeMS
......
...@@ -30,6 +30,7 @@ use function is_array; ...@@ -30,6 +30,7 @@ use function is_array;
use function is_bool; use function is_bool;
use function is_integer; use function is_integer;
use function is_object; use function is_object;
use function is_string;
use function MongoDB\create_field_path_type_map; use function MongoDB\create_field_path_type_map;
use function MongoDB\is_pipeline; use function MongoDB\is_pipeline;
use function MongoDB\server_supports_feature; use function MongoDB\server_supports_feature;
...@@ -54,6 +55,9 @@ class FindAndModify implements Executable, Explainable ...@@ -54,6 +55,9 @@ class FindAndModify implements Executable, Explainable
/** @var integer */ /** @var integer */
private static $wireVersionForDocumentLevelValidation = 4; private static $wireVersionForDocumentLevelValidation = 4;
/** @var integer */
private static $wireVersionForHintServerSideError = 8;
/** @var integer */ /** @var integer */
private static $wireVersionForWriteConcern = 4; private static $wireVersionForWriteConcern = 4;
...@@ -91,6 +95,14 @@ class FindAndModify implements Executable, Explainable ...@@ -91,6 +95,14 @@ class FindAndModify implements Executable, Explainable
* * fields (document): Limits the fields to return for the matching * * fields (document): Limits the fields to return for the matching
* document. * document.
* *
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
* then the query system will only consider plans using the hinted index.
*
* This is only supported for update and replace operations (i.e. remove
* option is false) on server versions >= 4.4. Using this option in
* other contexts will result in an exception at execution time.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to * * maxTimeMS (integer): The maximum amount of time to allow the query to
* run. * run.
* *
...@@ -153,6 +165,10 @@ class FindAndModify implements Executable, Explainable ...@@ -153,6 +165,10 @@ class FindAndModify implements Executable, Explainable
throw InvalidArgumentException::invalidType('"fields" option', $options['fields'], 'array or object'); throw InvalidArgumentException::invalidType('"fields" option', $options['fields'], 'array or object');
} }
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) {
throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], ['string', 'array', 'object']);
}
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
} }
...@@ -226,6 +242,14 @@ class FindAndModify implements Executable, Explainable ...@@ -226,6 +242,14 @@ class FindAndModify implements Executable, Explainable
throw UnsupportedException::collationNotSupported(); throw UnsupportedException::collationNotSupported();
} }
/* Server versions >= 4.1.10 raise errors for unknown findAndModify
* options (SERVER-40005), but the CRUD spec requires client-side errors
* for server versions < 4.2. For later versions, we'll rely on the
* server to either utilize the option or report its own error. */
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHintServerSideError)) {
throw UnsupportedException::hintNotSupported();
}
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) { if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported(); throw UnsupportedException::writeConcernNotSupported();
} }
...@@ -280,12 +304,10 @@ class FindAndModify implements Executable, Explainable ...@@ -280,12 +304,10 @@ class FindAndModify implements Executable, Explainable
: (object) $this->options['update']; : (object) $this->options['update'];
} }
if (isset($this->options['arrayFilters'])) { foreach (['arrayFilters', 'hint', 'maxTimeMS'] as $option) {
$cmd['arrayFilters'] = $this->options['arrayFilters']; if (isset($this->options[$option])) {
} $cmd[$option] = $this->options[$option];
}
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
} }
if (! empty($this->options['bypassDocumentValidation']) && if (! empty($this->options['bypassDocumentValidation']) &&
......
...@@ -57,6 +57,13 @@ class FindOneAndReplace implements Executable, Explainable ...@@ -57,6 +57,13 @@ class FindOneAndReplace implements Executable, Explainable
* This is not supported for server versions < 3.4 and will result in an * This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used. * exception at execution time if used.
* *
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
* then the query system will only consider plans using the hinted index.
*
* This is not supported for server versions < 4.4 and will result in an
* exception at execution time if used.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to * * maxTimeMS (integer): The maximum amount of time to allow the query to
* run. * run.
* *
......
...@@ -61,6 +61,13 @@ class FindOneAndUpdate implements Executable, Explainable ...@@ -61,6 +61,13 @@ class FindOneAndUpdate implements Executable, Explainable
* This is not supported for server versions < 3.4 and will result in an * This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used. * exception at execution time if used.
* *
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
* then the query system will only consider plans using the hinted index.
*
* This is not supported for server versions < 4.4 and will result in an
* exception at execution time if used.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to * * maxTimeMS (integer): The maximum amount of time to allow the query to
* run. * run.
* *
......
{
"runOn": [
{
"maxServerVersion": "4.0.99"
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"collection_name": "findOneAndReplace_hint",
"tests": [
{
"description": "FindOneAndReplace with hint string unsupported (client-side error)",
"operations": [
{
"object": "collection",
"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": "FindOneAndReplace with hint document unsupported (client-side error)",
"operations": [
{
"object": "collection",
"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
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.2.0",
"maxServerVersion": "4.3.0"
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"collection_name": "findOneAndReplace_hint",
"tests": [
{
"description": "FindOneAndReplace with hint string unsupported (server-side error)",
"operations": [
{
"object": "collection",
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"x": 33
},
"hint": "_id_"
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndReplace_hint",
"query": {
"_id": 1
},
"update": {
"x": 33
},
"hint": "_id_"
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndReplace with hint document unsupported (server-side error)",
"operations": [
{
"object": "collection",
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"x": 33
},
"hint": {
"_id": 1
}
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndReplace_hint",
"query": {
"_id": 1
},
"update": {
"x": 33
},
"hint": {
"_id": 1
}
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.3.1"
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"collection_name": "findOneAndReplace_hint",
"tests": [
{
"description": "FindOneAndReplace with hint string",
"operations": [
{
"object": "collection",
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"x": 33
},
"hint": "_id_"
},
"result": {
"_id": 1,
"x": 11
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndReplace_hint",
"query": {
"_id": 1
},
"update": {
"x": 33
},
"hint": "_id_"
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 33
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndReplace with hint document",
"operations": [
{
"object": "collection",
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"x": 33
},
"hint": {
"_id": 1
}
},
"result": {
"_id": 1,
"x": 11
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndReplace_hint",
"query": {
"_id": 1
},
"update": {
"x": 33
},
"hint": {
"_id": 1
}
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 33
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"maxServerVersion": "4.0.99"
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"collection_name": "findOneAndUpdate_hint",
"tests": [
{
"description": "FindOneAndUpdate with hint string unsupported (client-side error)",
"operations": [
{
"object": "collection",
"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": "FindOneAndUpdate with hint document unsupported (client-side error)",
"operations": [
{
"object": "collection",
"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
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.2.0",
"maxServerVersion": "4.3.0"
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"collection_name": "findOneAndUpdate_hint",
"tests": [
{
"description": "FindOneAndUpdate with hint string unsupported (server-side error)",
"operations": [
{
"object": "collection",
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": "_id_"
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndUpdate_hint",
"query": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": "_id_"
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndUpdate with hint document unsupported (server-side error)",
"operations": [
{
"object": "collection",
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": {
"_id": 1
}
},
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndUpdate_hint",
"query": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": {
"_id": 1
}
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.3.1"
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"collection_name": "findOneAndUpdate_hint",
"tests": [
{
"description": "FindOneAndUpdate with hint string",
"operations": [
{
"object": "collection",
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": "_id_"
},
"result": {
"_id": 1,
"x": 11
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndUpdate_hint",
"query": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": "_id_"
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndUpdate with hint document",
"operations": [
{
"object": "collection",
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": {
"_id": 1
}
},
"result": {
"_id": 1,
"x": 11
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"findAndModify": "findOneAndUpdate_hint",
"query": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"hint": {
"_id": 1
}
}
}
}
],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment