Skip to content

Commit 4e345a1

Browse files
committed
Merge pull request #732
* phplib-539: PHPLIB-539: Rework client-side error logic for unacknowledged findAndModify Rework client-side error logic for hints in updates PHPLIB-539: support hint in findAndDelete operations PHPLIB-539: Sync CRUD spec tests PHPLIB-539: Allow hinting for delete Allow customizing the driver repository for travis-ci
2 parents 7b084d3 + ee91ccf commit 4e345a1

File tree

48 files changed

+5367
-10
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+5367
-10
lines changed

.travis/install-extension.sh

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ tpecl () {
1616
fi
1717
}
1818

19-
if [ "x${DRIVER_BRANCH}" != "x" ]; then
20-
echo "Compiling driver branch ${DRIVER_BRANCH}"
19+
if [ "x${DRIVER_BRANCH}" != "x" ] || [ "x${DRIVER_REPO}" != "x" ]; then
20+
CLONE_REPO=${DRIVER_REPO:-https://github.com/mongodb/mongo-php-driver}
21+
CHECKOUT_BRANCH=${DRIVER_BRANCH:-master}
22+
23+
echo "Compiling driver branch ${CHECKOUT_BRANCH} from repository ${CLONE_REPO}"
2124

2225
mkdir -p /tmp/compile
23-
git clone https://github.com/mongodb/mongo-php-driver /tmp/compile/mongo-php-driver
26+
git clone ${CLONE_REPO} /tmp/compile/mongo-php-driver
2427
cd /tmp/compile/mongo-php-driver
2528

26-
git checkout ${DRIVER_BRANCH}
29+
git checkout ${CHECKOUT_BRANCH}
2730
git submodule update --init
2831
phpize
2932
./configure --enable-mongodb-developer-flags

docs/includes/apiargs-MongoDBCollection-method-deleteMany-option.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ source:
22
file: apiargs-MongoDBCollection-common-option.yaml
33
ref: collation
44
---
5+
source:
6+
file: apiargs-common-option.yaml
7+
ref: hint
8+
post: |
9+
This option is available in MongoDB 4.4+ and will result in an exception at
10+
execution time if specified for an older server version.
11+
12+
.. versionadded:: 1.7
13+
---
514
source:
615
file: apiargs-common-option.yaml
716
ref: session

docs/includes/apiargs-MongoDBCollection-method-deleteOne-option.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ source:
22
file: apiargs-MongoDBCollection-common-option.yaml
33
ref: collation
44
---
5+
source:
6+
file: apiargs-common-option.yaml
7+
ref: hint
8+
post: |
9+
This option is available in MongoDB 4.4+ and will result in an exception at
10+
execution time if specified for an older server version.
11+
12+
.. versionadded:: 1.7
13+
---
514
source:
615
file: apiargs-common-option.yaml
716
ref: session

src/Operation/Delete.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use MongoDB\Exception\UnsupportedException;
2828
use function is_array;
2929
use function is_object;
30+
use function is_string;
3031
use function MongoDB\server_supports_feature;
3132

3233
/**
@@ -43,6 +44,9 @@ class Delete implements Executable, Explainable
4344
/** @var integer */
4445
private static $wireVersionForCollation = 5;
4546

47+
/** @var int */
48+
private static $wireVersionForHintServerSideError = 5;
49+
4650
/** @var string */
4751
private $databaseName;
4852

@@ -68,6 +72,13 @@ class Delete implements Executable, Explainable
6872
* This is not supported for server versions < 3.4 and will result in an
6973
* exception at execution time if used.
7074
*
75+
* * hint (string|document): The index to use. Specify either the index
76+
* name as a string or the index key pattern as a document. If specified,
77+
* then the query system will only consider plans using the hinted index.
78+
*
79+
* This is not supported for server versions < 4.4 and will result in an
80+
* exception at execution time if used.
81+
*
7182
* * session (MongoDB\Driver\Session): Client session.
7283
*
7384
* Sessions are not supported for server versions < 3.6.
@@ -97,6 +108,10 @@ public function __construct($databaseName, $collectionName, $filter, $limit, arr
97108
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
98109
}
99110

111+
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) {
112+
throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], ['string', 'array', 'object']);
113+
}
114+
100115
if (isset($options['session']) && ! $options['session'] instanceof Session) {
101116
throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
102117
}
@@ -130,6 +145,13 @@ public function execute(Server $server)
130145
throw UnsupportedException::collationNotSupported();
131146
}
132147

148+
/* Server versions >= 3.4.0 raise errors for unknown update
149+
* options. For previous versions, the CRUD spec requires a client-side
150+
* error. */
151+
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHintServerSideError)) {
152+
throw UnsupportedException::hintNotSupported();
153+
}
154+
133155
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
134156
if ($inTransaction && isset($this->options['writeConcern'])) {
135157
throw UnsupportedException::writeConcernNotSupportedInTransaction();
@@ -170,6 +192,10 @@ private function createDeleteOptions()
170192
$deleteOptions['collation'] = (object) $this->options['collation'];
171193
}
172194

195+
if (isset($this->options['hint'])) {
196+
$deleteOptions['hint'] = $this->options['hint'];
197+
}
198+
173199
return $deleteOptions;
174200
}
175201

src/Operation/DeleteMany.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ class DeleteMany implements Executable, Explainable
4545
* This is not supported for server versions < 3.4 and will result in an
4646
* exception at execution time if used.
4747
*
48+
* * hint (string|document): The index to use. Specify either the index
49+
* name as a string or the index key pattern as a document. If specified,
50+
* then the query system will only consider plans using the hinted index.
51+
*
52+
* This is not supported for server versions < 4.4 and will result in an
53+
* exception at execution time if used.
54+
*
4855
* * session (MongoDB\Driver\Session): Client session.
4956
*
5057
* Sessions are not supported for server versions < 3.6.

src/Operation/DeleteOne.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ class DeleteOne implements Executable, Explainable
4545
* This is not supported for server versions < 3.4 and will result in an
4646
* exception at execution time if used.
4747
*
48+
* * hint (string|document): The index to use. Specify either the index
49+
* name as a string or the index key pattern as a document. If specified,
50+
* then the query system will only consider plans using the hinted index.
51+
*
52+
* This is not supported for server versions < 4.4 and will result in an
53+
* exception at execution time if used.
54+
*
4855
* * session (MongoDB\Driver\Session): Client session.
4956
*
5057
* Sessions are not supported for server versions < 3.6.

src/Operation/FindAndModify.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ class FindAndModify implements Executable, Explainable
5555
/** @var integer */
5656
private static $wireVersionForDocumentLevelValidation = 4;
5757

58+
/** @var integer */
59+
private static $wireVersionForHint = 9;
60+
5861
/** @var integer */
5962
private static $wireVersionForHintServerSideError = 8;
6063

@@ -99,8 +102,7 @@ class FindAndModify implements Executable, Explainable
99102
* name as a string or the index key pattern as a document. If specified,
100103
* then the query system will only consider plans using the hinted index.
101104
*
102-
* This is only supported for update and replace operations (i.e. remove
103-
* option is false) on server versions >= 4.4. Using this option in
105+
* This is only supported on server versions >= 4.4. Using this option in
104106
* other contexts will result in an exception at execution time.
105107
*
106108
* * maxTimeMS (integer): The maximum amount of time to allow the query to
@@ -246,7 +248,7 @@ public function execute(Server $server)
246248
* options (SERVER-40005), but the CRUD spec requires client-side errors
247249
* for server versions < 4.2. For later versions, we'll rely on the
248250
* server to either utilize the option or report its own error. */
249-
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHintServerSideError)) {
251+
if (isset($this->options['hint']) && ! $this->isHintSupported($server)) {
250252
throw UnsupportedException::hintNotSupported();
251253
}
252254

@@ -339,4 +341,20 @@ private function createOptions()
339341

340342
return $options;
341343
}
344+
345+
private function isAcknowledgedWriteConcern() : bool
346+
{
347+
if (! isset($this->options['writeConcern'])) {
348+
return true;
349+
}
350+
351+
return $this->options['writeConcern']->getW() > 1 || $this->options['writeConcern']->getJournal();
352+
}
353+
354+
private function isHintSupported(Server $server) : bool
355+
{
356+
$requiredWireVersion = $this->isAcknowledgedWriteConcern() ? self::$wireVersionForHintServerSideError : self::$wireVersionForHint;
357+
358+
return server_supports_feature($server, $requiredWireVersion);
359+
}
342360
}

src/Operation/FindOneAndDelete.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ class FindOneAndDelete implements Executable, Explainable
4646
* This is not supported for server versions < 3.4 and will result in an
4747
* exception at execution time if used.
4848
*
49+
* * hint (string|document): The index to use. Specify either the index
50+
* name as a string or the index key pattern as a document. If specified,
51+
* then the query system will only consider plans using the hinted index.
52+
*
53+
* This is not supported for server versions < 4.4 and will result in an
54+
* exception at execution time if used.
55+
*
4956
* * maxTimeMS (integer): The maximum amount of time to allow the query to
5057
* run.
5158
*

src/Operation/Update.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Update implements Executable, Explainable
5454
private static $wireVersionForDocumentLevelValidation = 4;
5555

5656
/** @var integer */
57-
private static $wireVersionForHint = 8;
57+
private static $wireVersionForHintServerSideError = 5;
5858

5959
/** @var string */
6060
private $databaseName;
@@ -202,7 +202,10 @@ public function execute(Server $server)
202202
throw UnsupportedException::collationNotSupported();
203203
}
204204

205-
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHint)) {
205+
/* Server versions >= 3.4.0 raise errors for unknown update
206+
* options. For previous versions, the CRUD spec requires a client-side
207+
* error. */
208+
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHintServerSideError)) {
206209
throw UnsupportedException::hintNotSupported();
207210
}
208211

tests/SpecTests/CrudSpecTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function testCrud(stdClass $test, array $runOn = null, array $data, $data
7373
}
7474

7575
if (isset($test->expectations)) {
76-
$commandExpectations = CommandExpectations::fromCrud($test->expectations);
76+
$commandExpectations = CommandExpectations::fromCrud((array) $test->expectations);
7777
$commandExpectations->startMonitoring();
7878
}
7979

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
{
2+
"runOn": [
3+
{
4+
"maxServerVersion": "3.3.99"
5+
}
6+
],
7+
"data": [
8+
{
9+
"_id": 1,
10+
"x": 11
11+
},
12+
{
13+
"_id": 2,
14+
"x": 22
15+
},
16+
{
17+
"_id": 3,
18+
"x": 33
19+
},
20+
{
21+
"_id": 4,
22+
"x": 44
23+
}
24+
],
25+
"collection_name": "BulkWrite_delete_hint",
26+
"tests": [
27+
{
28+
"description": "BulkWrite deleteOne with hints unsupported (client-side error)",
29+
"operations": [
30+
{
31+
"name": "bulkWrite",
32+
"arguments": {
33+
"requests": [
34+
{
35+
"name": "deleteOne",
36+
"arguments": {
37+
"filter": {
38+
"_id": 1
39+
},
40+
"hint": "_id_"
41+
}
42+
},
43+
{
44+
"name": "deleteOne",
45+
"arguments": {
46+
"filter": {
47+
"_id": 2
48+
},
49+
"hint": {
50+
"_id": 1
51+
}
52+
}
53+
}
54+
],
55+
"options": {
56+
"ordered": true
57+
}
58+
},
59+
"error": true
60+
}
61+
],
62+
"expectations": [],
63+
"outcome": {
64+
"collection": {
65+
"data": [
66+
{
67+
"_id": 1,
68+
"x": 11
69+
},
70+
{
71+
"_id": 2,
72+
"x": 22
73+
},
74+
{
75+
"_id": 3,
76+
"x": 33
77+
},
78+
{
79+
"_id": 4,
80+
"x": 44
81+
}
82+
]
83+
}
84+
}
85+
},
86+
{
87+
"description": "BulkWrite deleteMany with hints unsupported (client-side error)",
88+
"operations": [
89+
{
90+
"name": "bulkWrite",
91+
"arguments": {
92+
"requests": [
93+
{
94+
"name": "deleteMany",
95+
"arguments": {
96+
"filter": {
97+
"_id": {
98+
"$lt": 3
99+
}
100+
},
101+
"hint": "_id_"
102+
}
103+
},
104+
{
105+
"name": "deleteMany",
106+
"arguments": {
107+
"filter": {
108+
"_id": {
109+
"$gte": 4
110+
}
111+
},
112+
"hint": {
113+
"_id": 1
114+
}
115+
}
116+
}
117+
],
118+
"options": {
119+
"ordered": true
120+
}
121+
},
122+
"error": true
123+
}
124+
],
125+
"expectations": [],
126+
"outcome": {
127+
"collection": {
128+
"data": [
129+
{
130+
"_id": 1,
131+
"x": 11
132+
},
133+
{
134+
"_id": 2,
135+
"x": 22
136+
},
137+
{
138+
"_id": 3,
139+
"x": 33
140+
},
141+
{
142+
"_id": 4,
143+
"x": 44
144+
}
145+
]
146+
}
147+
}
148+
}
149+
]
150+
}

0 commit comments

Comments
 (0)