Skip to content

Commit aef1ef7

Browse files
committed
Merge pull request mongodb#269
2 parents 55e2a31 + c405cec commit aef1ef7

31 files changed

+414
-27
lines changed

.travis.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,15 @@ env:
1313
- MONGO_REPO_TYPE="precise/mongodb-enterprise/"
1414
- SOURCES_LOC="/etc/apt/sources.list.d/mongodb.list"
1515
matrix:
16-
- DRIVER_VERSION=stable SERVER_VERSION=2.6
17-
- DRIVER_VERSION=stable SERVER_VERSION=3.0
18-
- DRIVER_VERSION=stable SERVER_VERSION=3.2
16+
- DRIVER_VERSION=1.2.0alpha3 SERVER_VERSION=2.6
17+
- DRIVER_VERSION=1.2.0alpha3 SERVER_VERSION=3.0
18+
- DRIVER_VERSION=1.2.0alpha3 SERVER_VERSION=3.2
1919

2020
matrix:
2121
fast_finish: true
2222
include:
23-
- php: 5.6
24-
env: DRIVER_VERSION=1.1.0 SERVER_VERSION=3.2
2523
- php: 7.0
26-
env: DRIVER_VERSION=stable SERVER_VERSION=2.4
24+
env: DRIVER_VERSION=1.2.0alpha3 SERVER_VERSION=2.4
2725
- php: 7.0
2826
env: DRIVER_VERSION=devel SERVER_VERSION=3.2
2927
exclude:

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
],
1212
"require": {
1313
"php": ">=5.4",
14-
"ext-mongodb": "^1.1.0"
14+
"ext-mongodb": "^1.2.0"
1515
},
1616
"require-dev": {
1717
"phpunit/phpunit": "^4.8"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace MongoDB\Exception;
4+
5+
class UnsupportedException extends RuntimeException implements Exception
6+
{
7+
/**
8+
* Thrown when collations are not supported by a server.
9+
*
10+
* @return self
11+
*/
12+
public static function collationNotSupported()
13+
{
14+
return new static('Collations are not supported by the server executing this operation');
15+
}
16+
}

src/Operation/Aggregate.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use MongoDB\Driver\Server;
99
use MongoDB\Exception\InvalidArgumentException;
1010
use MongoDB\Exception\UnexpectedValueException;
11+
use MongoDB\Exception\UnsupportedException;
1112
use ArrayIterator;
1213
use stdClass;
1314
use Traversable;
@@ -21,6 +22,7 @@
2122
*/
2223
class Aggregate implements Executable
2324
{
25+
private static $wireVersionForCollation = 5;
2426
private static $wireVersionForCursor = 2;
2527
private static $wireVersionForDocumentLevelValidation = 4;
2628
private static $wireVersionForReadConcern = 4;
@@ -48,6 +50,11 @@ class Aggregate implements Executable
4850
* For servers < 3.2, this option is ignored as document level validation
4951
* is not available.
5052
*
53+
* * collation (document): Collation specification.
54+
*
55+
* This is not supported for server versions < 3.4 and will result in an
56+
* exception at execution time if used.
57+
*
5158
* * maxTimeMS (integer): The maximum amount of time to allow the query to
5259
* run.
5360
*
@@ -117,6 +124,10 @@ public function __construct($databaseName, $collectionName, array $pipeline, arr
117124
throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
118125
}
119126

127+
if (isset($options['collation']) && ! is_array($options['collation']) && ! is_object($options['collation'])) {
128+
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
129+
}
130+
120131
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
121132
throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
122133
}
@@ -158,9 +169,14 @@ public function __construct($databaseName, $collectionName, array $pipeline, arr
158169
* @param Server $server
159170
* @return Traversable
160171
* @throws UnexpectedValueException if the command response was malformed
172+
* @throws UnsupportedException if collation is used and unsupported
161173
*/
162174
public function execute(Server $server)
163175
{
176+
if (isset($this->options['collation']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForCollation)) {
177+
throw UnsupportedException::collationNotSupported();
178+
}
179+
164180
$isCursorSupported = \MongoDB\server_supports_feature($server, self::$wireVersionForCursor);
165181
$readPreference = isset($this->options['readPreference']) ? $this->options['readPreference'] : null;
166182

@@ -212,6 +228,10 @@ private function createCommand(Server $server, $isCursorSupported)
212228
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
213229
}
214230

231+
if (isset($this->options['collation'])) {
232+
$cmd['collation'] = (object) $this->options['collation'];
233+
}
234+
215235
if (isset($this->options['maxTimeMS'])) {
216236
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
217237
}

src/Operation/BulkWrite.php

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use MongoDB\Driver\Server;
88
use MongoDB\Driver\WriteConcern;
99
use MongoDB\Exception\InvalidArgumentException;
10+
use MongoDB\Exception\UnsupportedException;
1011

1112
/**
1213
* Operation for executing multiple write operations.
@@ -23,21 +24,23 @@ class BulkWrite implements Executable
2324
const UPDATE_MANY = 'updateMany';
2425
const UPDATE_ONE = 'updateOne';
2526

27+
private static $wireVersionForCollation = 5;
2628
private static $wireVersionForDocumentLevelValidation = 4;
2729

2830
private $databaseName;
2931
private $collectionName;
3032
private $operations;
3133
private $options;
34+
private $isCollationUsed = false;
3235

3336
/**
3437
* Constructs a bulk write operation.
3538
*
3639
* Example array structure for all supported operation types:
3740
*
3841
* [
39-
* [ 'deleteMany' => [ $filter ] ],
40-
* [ 'deleteOne' => [ $filter ] ],
42+
* [ 'deleteMany' => [ $filter, $options ] ],
43+
* [ 'deleteOne' => [ $filter, $options ] ],
4144
* [ 'insertOne' => [ $document ] ],
4245
* [ 'replaceOne' => [ $filter, $replacement, $options ] ],
4346
* [ 'updateMany' => [ $filter, $update, $options ] ],
@@ -48,8 +51,20 @@ class BulkWrite implements Executable
4851
* writeConcern option is specified for the top-level bulk write operation
4952
* instead of each individual operation.
5053
*
54+
* Supported options for deleteMany and deleteOne operations:
55+
*
56+
* * collation (document): Collation specification.
57+
*
58+
* This is not supported for server versions < 3.4 and will result in an
59+
* exception at execution time if used.
60+
*
5161
* Supported options for replaceOne, updateMany, and updateOne operations:
5262
*
63+
* * collation (document): Collation specification.
64+
*
65+
* This is not supported for server versions < 3.4 and will result in an
66+
* exception at execution time if used.
67+
*
5368
* * upsert (boolean): When true, a new document is created if no document
5469
* matches the query. The default is false.
5570
*
@@ -108,7 +123,25 @@ public function __construct($databaseName, $collectionName, array $operations, a
108123

109124
case self::DELETE_MANY:
110125
case self::DELETE_ONE:
111-
$operations[$i][$type][1] = ['limit' => ($type === self::DELETE_ONE ? 1 : 0)];
126+
if ( ! isset($args[1])) {
127+
$args[1] = [];
128+
}
129+
130+
if ( ! is_array($args[1])) {
131+
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][1]', $i, $type), $args[1], 'array');
132+
}
133+
134+
$args[1]['limit'] = ($type === self::DELETE_ONE ? 1 : 0);
135+
136+
if (isset($args[1]['collation'])) {
137+
$this->isCollationUsed = true;
138+
139+
if ( ! is_array($args[1]['collation']) && ! is_object($args[1]['collation'])) {
140+
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][1]["collation"]', $i, $type), $args[1]['collation'], 'array or object');
141+
}
142+
}
143+
144+
$operations[$i][$type][1] = $args[1];
112145

113146
break;
114147

@@ -136,6 +169,14 @@ public function __construct($databaseName, $collectionName, array $operations, a
136169
$args[2]['multi'] = false;
137170
$args[2] += ['upsert' => false];
138171

172+
if (isset($args[2]['collation'])) {
173+
$this->isCollationUsed = true;
174+
175+
if ( ! is_array($args[2]['collation']) && ! is_object($args[2]['collation'])) {
176+
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["collation"]', $i, $type), $args[2]['collation'], 'array or object');
177+
}
178+
}
179+
139180
if ( ! is_bool($args[2]['upsert'])) {
140181
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["upsert"]', $i, $type), $args[2]['upsert'], 'boolean');
141182
}
@@ -169,6 +210,14 @@ public function __construct($databaseName, $collectionName, array $operations, a
169210
$args[2]['multi'] = ($type === self::UPDATE_MANY);
170211
$args[2] += ['upsert' => false];
171212

213+
if (isset($args[2]['collation'])) {
214+
$this->isCollationUsed = true;
215+
216+
if ( ! is_array($args[2]['collation']) && ! is_object($args[2]['collation'])) {
217+
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["collation"]', $i, $type), $args[2]['collation'], 'array or object');
218+
}
219+
}
220+
172221
if ( ! is_bool($args[2]['upsert'])) {
173222
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["upsert"]', $i, $type), $args[2]['upsert'], 'boolean');
174223
}
@@ -210,9 +259,14 @@ public function __construct($databaseName, $collectionName, array $operations, a
210259
* @see Executable::execute()
211260
* @param Server $server
212261
* @return BulkWriteResult
262+
* @throws UnsupportedException if collation is used and unsupported
213263
*/
214264
public function execute(Server $server)
215265
{
266+
if ($this->isCollationUsed && ! \MongoDB\server_supports_feature($server, self::$wireVersionForCollation)) {
267+
throw UnsupportedException::collationNotSupported();
268+
}
269+
216270
$options = ['ordered' => $this->options['ordered']];
217271

218272
if (isset($this->options['bypassDocumentValidation']) && \MongoDB\server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)) {

src/Operation/Count.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use MongoDB\Driver\Server;
99
use MongoDB\Exception\InvalidArgumentException;
1010
use MongoDB\Exception\UnexpectedValueException;
11+
use MongoDB\Exception\UnsupportedException;
1112

1213
/**
1314
* Operation for the count command.
@@ -18,6 +19,7 @@
1819
*/
1920
class Count implements Executable
2021
{
22+
private static $wireVersionForCollation = 5;
2123
private static $wireVersionForReadConcern = 4;
2224

2325
private $databaseName;
@@ -30,6 +32,11 @@ class Count implements Executable
3032
*
3133
* Supported options:
3234
*
35+
* * collation (document): Collation specification.
36+
*
37+
* This is not supported for server versions < 3.4 and will result in an
38+
* exception at execution time if used.
39+
*
3340
* * hint (string|document): The index to use. If a document, it will be
3441
* interpretted as an index specification and a name will be generated.
3542
*
@@ -60,6 +67,10 @@ public function __construct($databaseName, $collectionName, $filter = [], array
6067
throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object');
6168
}
6269

70+
if (isset($options['collation']) && ! is_array($options['collation']) && ! is_object($options['collation'])) {
71+
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
72+
}
73+
6374
if (isset($options['hint'])) {
6475
if (is_array($options['hint']) || is_object($options['hint'])) {
6576
$options['hint'] = \MongoDB\generate_index_name($options['hint']);
@@ -103,9 +114,14 @@ public function __construct($databaseName, $collectionName, $filter = [], array
103114
* @param Server $server
104115
* @return integer
105116
* @throws UnexpectedValueException if the command response was malformed
117+
* @throws UnsupportedException if collation is used and unsupported
106118
*/
107119
public function execute(Server $server)
108120
{
121+
if (isset($this->options['collation']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForCollation)) {
122+
throw UnsupportedException::collationNotSupported();
123+
}
124+
109125
$readPreference = isset($this->options['readPreference']) ? $this->options['readPreference'] : null;
110126

111127
$cursor = $server->executeCommand($this->databaseName, $this->createCommand($server), $readPreference);
@@ -133,6 +149,10 @@ private function createCommand(Server $server)
133149
$cmd['query'] = (object) $this->filter;
134150
}
135151

152+
if (isset($this->options['collation'])) {
153+
$cmd['collation'] = (object) $this->options['collation'];
154+
}
155+
136156
foreach (['hint', 'limit', 'maxTimeMS', 'skip'] as $option) {
137157
if (isset($this->options[$option])) {
138158
$cmd[$option] = $this->options[$option];

src/Operation/CreateCollection.php

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use MongoDB\Driver\Command;
66
use MongoDB\Driver\Server;
77
use MongoDB\Exception\InvalidArgumentException;
8+
use MongoDB\Exception\UnsupportedException;
89

910
/**
1011
* Operation for the create command.
@@ -18,6 +19,8 @@ class CreateCollection implements Executable
1819
const USE_POWER_OF_2_SIZES = 1;
1920
const NO_PADDING = 2;
2021

22+
private static $wireVersionForCollation = 5;
23+
2124
private $databaseName;
2225
private $collectionName;
2326
private $options = [];
@@ -34,6 +37,11 @@ class CreateCollection implements Executable
3437
* * capped (boolean): Specify true to create a capped collection. If set,
3538
* the size option must also be specified. The default is false.
3639
*
40+
* * collation (document): Collation specification.
41+
*
42+
* This is not supported for server versions < 3.4 and will result in an
43+
* exception at execution time if used.
44+
*
3745
* * flags (integer): Options for the MMAPv1 storage engine only. Must be a
3846
* bitwise combination CreateCollection::USE_POWER_OF_2_SIZES and
3947
* CreateCollection::NO_PADDING. The default is
@@ -78,6 +86,10 @@ public function __construct($databaseName, $collectionName, array $options = [])
7886
throw InvalidArgumentException::invalidType('"capped" option', $options['capped'], 'boolean');
7987
}
8088

89+
if (isset($options['collation']) && ! is_array($options['collation']) && ! is_object($options['collation'])) {
90+
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
91+
}
92+
8193
if (isset($options['flags']) && ! is_integer($options['flags'])) {
8294
throw InvalidArgumentException::invalidType('"flags" option', $options['flags'], 'integer');
8395
}
@@ -129,9 +141,14 @@ public function __construct($databaseName, $collectionName, array $options = [])
129141
* @see Executable::execute()
130142
* @param Server $server
131143
* @return array|object Command result document
144+
* @throws UnsupportedException if collation is used and unsupported
132145
*/
133146
public function execute(Server $server)
134147
{
148+
if (isset($this->options['collation']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForCollation)) {
149+
throw UnsupportedException::collationNotSupported();
150+
}
151+
135152
$cursor = $server->executeCommand($this->databaseName, $this->createCommand());
136153

137154
if (isset($this->options['typeMap'])) {
@@ -156,16 +173,10 @@ private function createCommand()
156173
}
157174
}
158175

159-
if (isset($this->options['indexOptionDefaults'])) {
160-
$cmd['indexOptionDefaults'] = (object) $this->options['indexOptionDefaults'];
161-
}
162-
163-
if (isset($this->options['storageEngine'])) {
164-
$cmd['storageEngine'] = (object) $this->options['storageEngine'];
165-
}
166-
167-
if (isset($this->options['validator'])) {
168-
$cmd['validator'] = (object) $this->options['validator'];
176+
foreach (['collation', 'indexOptionDefaults', 'storageEngine', 'validator'] as $option) {
177+
if (isset($this->options[$option])) {
178+
$cmd[$option] = (object) $this->options[$option];
179+
}
169180
}
170181

171182
return new Command($cmd);

0 commit comments

Comments
 (0)