Skip to content

Commit bcb9510

Browse files
committed
PHPLIB-438: Unify handling for write stages in aggregation pipelines
1 parent f4dec93 commit bcb9510

11 files changed

+38
-35
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ source:
3939
source:
4040
file: apiargs-MongoDBCollection-common-option.yaml
4141
ref: readPreference
42-
post: |
43-
This option will be ignored when using the :ref:`$out <agg-out>` stage.
4442
---
4543
source:
4644
file: apiargs-common-option.yaml
@@ -72,7 +70,8 @@ source:
7270
file: apiargs-MongoDBCollection-common-option.yaml
7371
ref: writeConcern
7472
post: |
75-
This only applies when the :ref:`$out <agg-out>` stage is specified.
73+
This only applies when a :ref:`$out <agg-out>` or :ref:`$merge <agg-merge>`
74+
stage is specified.
7675
7776
This is not supported for server versions prior to 3.4 and will result in an
7877
exception at execution time if used.

docs/includes/apiargs-MongoDBDatabase-method-aggregate-option.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ source:
3333
source:
3434
file: apiargs-MongoDBDatabase-common-option.yaml
3535
ref: readPreference
36-
post: |
37-
This option will be ignored when using the :ref:`$out <agg-out>` stage.
3836
---
3937
source:
4038
file: apiargs-common-option.yaml
@@ -48,7 +46,8 @@ source:
4846
file: apiargs-MongoDBDatabase-common-option.yaml
4947
ref: writeConcern
5048
post: |
51-
This only applies when the :ref:`$out <agg-out>` stage is specified.
49+
This only applies when a :ref:`$out <agg-out>` or :ref:`$merge <agg-merge>`
50+
stage is specified.
5251
5352
This is not supported for server versions prior to 3.4 and will result in an
5453
exception at execution time if used.

docs/includes/apiargs-aggregate-option.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ source:
2424
file: apiargs-MongoDBCollection-common-option.yaml
2525
ref: bypassDocumentValidation
2626
post: |
27-
This only applies when using the :ref:`$out <agg-out>` stage.
27+
This only applies when using the :ref:`$out <agg-out>` and
28+
:ref:`$out <agg-merge>` stages.
2829
2930
Document validation requires MongoDB 3.2 or later: if you are using an earlier
3031
version of MongoDB, this option will be ignored.

src/Collection.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class Collection
6969
private static $wireVersionForFindAndModifyWriteConcern = 4;
7070
private static $wireVersionForReadConcern = 4;
7171
private static $wireVersionForWritableCommandWriteConcern = 5;
72-
private static $wireVersionForReadConcernWithOutStage = 8;
72+
private static $wireVersionForReadConcernWithWriteStage = 8;
7373

7474
private $collectionName;
7575
private $databaseName;
@@ -190,13 +190,13 @@ public function __toString()
190190
*/
191191
public function aggregate(array $pipeline, array $options = [])
192192
{
193-
$hasOutStage = \MongoDB\is_last_pipeline_operator_out($pipeline);
193+
$hasWriteStage = \MongoDB\is_last_pipeline_operator_write($pipeline);
194194

195195
if ( ! isset($options['readPreference'])) {
196196
$options['readPreference'] = $this->readPreference;
197197
}
198198

199-
if ($hasOutStage) {
199+
if ($hasWriteStage) {
200200
$options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
201201
}
202202

@@ -210,7 +210,7 @@ public function aggregate(array $pipeline, array $options = [])
210210
if ( ! isset($options['readConcern']) &&
211211
\MongoDB\server_supports_feature($server, self::$wireVersionForReadConcern) &&
212212
! \MongoDB\is_in_transaction($options) &&
213-
( ! $hasOutStage || \MongoDB\server_supports_feature($server, self::$wireVersionForReadConcernWithOutStage))
213+
( ! $hasWriteStage || \MongoDB\server_supports_feature($server, self::$wireVersionForReadConcernWithWriteStage))
214214
) {
215215
$options['readConcern'] = $this->readConcern;
216216
}
@@ -219,7 +219,7 @@ public function aggregate(array $pipeline, array $options = [])
219219
$options['typeMap'] = $this->typeMap;
220220
}
221221

222-
if ($hasOutStage &&
222+
if ($hasWriteStage &&
223223
! isset($options['writeConcern']) &&
224224
\MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) &&
225225
! \MongoDB\is_in_transaction($options)) {

src/Database.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Database
4848
];
4949
private static $wireVersionForReadConcern = 4;
5050
private static $wireVersionForWritableCommandWriteConcern = 5;
51-
private static $wireVersionForReadConcernWithOutStage = 8;
51+
private static $wireVersionForReadConcernWithWriteStage = 8;
5252

5353
private $databaseName;
5454
private $manager;
@@ -175,13 +175,13 @@ public function __toString()
175175
*/
176176
public function aggregate(array $pipeline, array $options = [])
177177
{
178-
$hasOutStage = \MongoDB\is_last_pipeline_operator_out($pipeline);
178+
$hasWriteStage = \MongoDB\is_last_pipeline_operator_write($pipeline);
179179

180180
if ( ! isset($options['readPreference'])) {
181181
$options['readPreference'] = $this->readPreference;
182182
}
183183

184-
if ($hasOutStage) {
184+
if ($hasWriteStage) {
185185
$options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
186186
}
187187

@@ -195,7 +195,7 @@ public function aggregate(array $pipeline, array $options = [])
195195
if ( ! isset($options['readConcern']) &&
196196
\MongoDB\server_supports_feature($server, self::$wireVersionForReadConcern) &&
197197
! \MongoDB\is_in_transaction($options) &&
198-
( ! $hasOutStage || \MongoDB\server_supports_feature($server, self::$wireVersionForReadConcernWithOutStage))
198+
( ! $hasWriteStage || \MongoDB\server_supports_feature($server, self::$wireVersionForReadConcernWithWriteStage))
199199
) {
200200
$options['readConcern'] = $this->readConcern;
201201
}
@@ -204,7 +204,7 @@ public function aggregate(array $pipeline, array $options = [])
204204
$options['typeMap'] = $this->typeMap;
205205
}
206206

207-
if ($hasOutStage &&
207+
if ($hasWriteStage &&
208208
! isset($options['writeConcern']) &&
209209
\MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) &&
210210
! \MongoDB\is_in_transaction($options)) {

src/Operation/Aggregate.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,12 @@ public function execute(Server $server)
264264

265265

266266
$hasExplain = ! empty($this->options['explain']);
267-
$hasOutStage = \MongoDB\is_last_pipeline_operator_out($this->pipeline);
267+
$hasWriteStage = \MongoDB\is_last_pipeline_operator_write($this->pipeline);
268268

269-
$command = $this->createCommand($server, $hasOutStage);
270-
$options = $this->createOptions($hasOutStage, $hasExplain);
269+
$command = $this->createCommand($server, $hasWriteStage);
270+
$options = $this->createOptions($hasWriteStage, $hasExplain);
271271

272-
$cursor = ($hasOutStage && ! $hasExplain)
272+
$cursor = ($hasWriteStage && ! $hasExplain)
273273
? $server->executeReadWriteCommand($this->databaseName, $command, $options)
274274
: $server->executeReadCommand($this->databaseName, $command, $options);
275275

@@ -353,27 +353,27 @@ private function createCommand(Server $server, $hasOutStage)
353353
*
354354
* @see http://php.net/manual/en/mongodb-driver-server.executereadcommand.php
355355
* @see http://php.net/manual/en/mongodb-driver-server.executereadwritecommand.php
356-
* @param boolean $hasOutStage
356+
* @param boolean $hasWriteStage
357357
* @param boolean $hasExplain
358358
* @return array
359359
*/
360-
private function createOptions($hasOutStage, $hasExplain)
360+
private function createOptions($hasWriteStage, $hasExplain)
361361
{
362362
$options = [];
363363

364364
if (isset($this->options['readConcern'])) {
365365
$options['readConcern'] = $this->options['readConcern'];
366366
}
367367

368-
if ( ! $hasOutStage && isset($this->options['readPreference'])) {
368+
if (!$hasWriteStage && isset($this->options['readPreference'])) {
369369
$options['readPreference'] = $this->options['readPreference'];
370370
}
371371

372372
if (isset($this->options['session'])) {
373373
$options['session'] = $this->options['session'];
374374
}
375375

376-
if ($hasOutStage && ! $hasExplain && isset($this->options['writeConcern'])) {
376+
if ($hasWriteStage && ! $hasExplain && isset($this->options['writeConcern'])) {
377377
$options['writeConcern'] = $this->options['writeConcern'];
378378
}
379379

src/functions.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ function is_in_transaction(array $options)
127127
}
128128

129129
/**
130-
* Return whether the aggregation pipeline ends with an $out operator.
130+
* Return whether the aggregation pipeline ends with an $out or $merge operator.
131131
*
132132
* This is used for determining whether the aggregation pipeline must be
133133
* executed against a primary server.
@@ -136,7 +136,7 @@ function is_in_transaction(array $options)
136136
* @param array $pipeline List of pipeline operations
137137
* @return boolean
138138
*/
139-
function is_last_pipeline_operator_out(array $pipeline)
139+
function is_last_pipeline_operator_write(array $pipeline)
140140
{
141141
$lastOp = end($pipeline);
142142

@@ -146,7 +146,7 @@ function is_last_pipeline_operator_out(array $pipeline)
146146

147147
$lastOp = (array) $lastOp;
148148

149-
return key($lastOp) === '$out';
149+
return in_array(key($lastOp), ['$out', '$merge'], true);
150150
}
151151

152152
/**

tests/Collection/CrudSpecFunctionalTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ private function executeAssertResult(array $operation, $expectedResult, $actualR
292292
* the result here; however, assertEquivalentCollections() will
293293
* assert the output collection's contents later.
294294
*/
295-
if ( ! \MongoDB\is_last_pipeline_operator_out($operation['arguments']['pipeline'])) {
295+
if ( ! \MongoDB\is_last_pipeline_operator_write($operation['arguments']['pipeline'])) {
296296
$this->assertSameDocuments($expectedResult, $actualResult);
297297
}
298298
break;

tests/SpecTests/Context.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ public static function fromCrud(stdClass $test, $databaseName, $collectionName)
6363
$o->outcomeCollectionName = $test->outcome->collection->name;
6464
}
6565

66+
$o->defaultWriteOptions = [
67+
'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
68+
];
69+
70+
$o->outcomeFindOptions = [
71+
'readConcern' => new ReadConcern('local'),
72+
'readPreference' => new ReadPreference('primary'),
73+
];
74+
6675
$o->client = new Client(FunctionalTestCase::getUri(), $clientOptions);
6776

6877
return $o;

tests/SpecTests/CrudSpecTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ class CrudSpecTest extends FunctionalTestCase
1414
/* These should all pass before the driver can be considered compatible with
1515
* MongoDB 4.2. */
1616
private static $incompleteTests = [
17-
'aggregate-merge: Aggregate with $merge' => 'PHPLIB-438',
18-
'aggregate-merge: Aggregate with $merge and batch size of 0' => 'PHPLIB-438',
19-
'aggregate-merge: Aggregate with $merge and majority readConcern' => 'PHPLIB-438',
20-
'aggregate-merge: Aggregate with $merge and local readConcern' => 'PHPLIB-438',
21-
'aggregate-merge: Aggregate with $merge and available readConcern' => 'PHPLIB-438',
2217
'bulkWrite-arrayFilters: BulkWrite with arrayFilters' => 'Fails due to command assertions',
2318
'updateWithPipelines: UpdateOne using pipelines' => 'PHPLIB-418',
2419
'updateWithPipelines: UpdateMany using pipelines' => 'PHPLIB-418',

tests/SpecTests/Operation.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ private function getResultAssertionTypeForCollection()
416416
* the CRUD specification and is not implemented in the library
417417
* since we have no concept of lazy cursors. Rely on examining
418418
* the output collection rather than the operation result. */
419-
if (\MongoDB\is_last_pipeline_operator_out($this->arguments['pipeline'])) {
419+
if (\MongoDB\is_last_pipeline_operator_write($this->arguments['pipeline'])) {
420420
return ResultExpectation::ASSERT_NOTHING;
421421
}
422422

0 commit comments

Comments
 (0)