Commit 2665bc30 authored by Jeremy Mikola's avatar Jeremy Mikola

Merge pull request #262

parents aef1ef7c 21b7d92a
...@@ -16,6 +16,7 @@ class Client ...@@ -16,6 +16,7 @@ class Client
'document' => 'MongoDB\Model\BSONDocument', 'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument', 'root' => 'MongoDB\Model\BSONDocument',
]; ];
private static $wireVersionForWritableCommandWriteConcern = 5;
private $manager; private $manager;
private $uri; private $uri;
...@@ -114,9 +115,14 @@ class Client ...@@ -114,9 +115,14 @@ class Client
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new DropDatabase($databaseName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new DropDatabase($databaseName, $options);
return $operation->execute($server); return $operation->execute($server);
} }
......
...@@ -39,6 +39,7 @@ class Collection ...@@ -39,6 +39,7 @@ class Collection
'root' => 'MongoDB\Model\BSONDocument', 'root' => 'MongoDB\Model\BSONDocument',
]; ];
private static $wireVersionForFindAndModifyWriteConcern = 4; private static $wireVersionForFindAndModifyWriteConcern = 4;
private static $wireVersionForWritableCommandWriteConcern = 5;
private $collectionName; private $collectionName;
private $databaseName; private $databaseName;
...@@ -180,9 +181,14 @@ class Collection ...@@ -180,9 +181,14 @@ class Collection
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new Aggregate($this->databaseName, $this->collectionName, $pipeline, $options);
$server = $this->manager->selectServer($options['readPreference']); $server = $this->manager->selectServer($options['readPreference']);
if ($hasOutStage && ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new Aggregate($this->databaseName, $this->collectionName, $pipeline, $options);
return $operation->execute($server); return $operation->execute($server);
} }
...@@ -234,6 +240,7 @@ class Collection ...@@ -234,6 +240,7 @@ class Collection
* Create a single index for the collection. * Create a single index for the collection.
* *
* @see Collection::createIndexes() * @see Collection::createIndexes()
* @see CreateIndexes::__construct() for supported command options
* @param array|object $key Document containing fields mapped to values, * @param array|object $key Document containing fields mapped to values,
* which denote order or an index type * which denote order or an index type
* @param array $options Index options * @param array $options Index options
...@@ -241,7 +248,10 @@ class Collection ...@@ -241,7 +248,10 @@ class Collection
*/ */
public function createIndex($key, array $options = []) public function createIndex($key, array $options = [])
{ {
return current($this->createIndexes([['key' => $key] + $options])); $indexOptions = array_diff_key($options, ['writeConcern' => 1]);
$commandOptions = array_intersect_key($options, ['writeConcern' => 1]);
return current($this->createIndexes([['key' => $key] + $indexOptions], $commandOptions));
} }
/** /**
...@@ -263,15 +273,22 @@ class Collection ...@@ -263,15 +273,22 @@ class Collection
* *
* @see http://docs.mongodb.org/manual/reference/command/createIndexes/ * @see http://docs.mongodb.org/manual/reference/command/createIndexes/
* @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/ * @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
* @see CreateIndexes::__construct() for supported command options
* @param array[] $indexes List of index specifications * @param array[] $indexes List of index specifications
* @param array $options Command options
* @return string[] The names of the created indexes * @return string[] The names of the created indexes
* @throws InvalidArgumentException if an index specification is invalid * @throws InvalidArgumentException if an index specification is invalid
*/ */
public function createIndexes(array $indexes) public function createIndexes(array $indexes, array $options = [])
{ {
$operation = new CreateIndexes($this->databaseName, $this->collectionName, $indexes);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new CreateIndexes($this->databaseName, $this->collectionName, $indexes, $options);
return $operation->execute($server); return $operation->execute($server);
} }
...@@ -355,9 +372,14 @@ class Collection ...@@ -355,9 +372,14 @@ class Collection
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new DropCollection($this->databaseName, $this->collectionName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new DropCollection($this->databaseName, $this->collectionName, $options);
return $operation->execute($server); return $operation->execute($server);
} }
...@@ -382,9 +404,14 @@ class Collection ...@@ -382,9 +404,14 @@ class Collection
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new DropIndexes($this->databaseName, $this->collectionName, $indexName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new DropIndexes($this->databaseName, $this->collectionName, $indexName, $options);
return $operation->execute($server); return $operation->execute($server);
} }
...@@ -401,9 +428,14 @@ class Collection ...@@ -401,9 +428,14 @@ class Collection
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new DropIndexes($this->databaseName, $this->collectionName, '*', $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new DropIndexes($this->databaseName, $this->collectionName, '*', $options);
return $operation->execute($server); return $operation->execute($server);
} }
......
...@@ -24,6 +24,7 @@ class Database ...@@ -24,6 +24,7 @@ class Database
'document' => 'MongoDB\Model\BSONDocument', 'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument', 'root' => 'MongoDB\Model\BSONDocument',
]; ];
private static $wireVersionForWritableCommandWriteConcern = 5;
private $databaseName; private $databaseName;
private $manager; private $manager;
...@@ -173,9 +174,14 @@ class Database ...@@ -173,9 +174,14 @@ class Database
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new CreateCollection($this->databaseName, $collectionName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new CreateCollection($this->databaseName, $collectionName, $options);
return $operation->execute($server); return $operation->execute($server);
} }
...@@ -192,9 +198,14 @@ class Database ...@@ -192,9 +198,14 @@ class Database
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new DropDatabase($this->databaseName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new DropDatabase($this->databaseName, $options);
return $operation->execute($server); return $operation->execute($server);
} }
...@@ -212,9 +223,14 @@ class Database ...@@ -212,9 +223,14 @@ class Database
$options['typeMap'] = $this->typeMap; $options['typeMap'] = $this->typeMap;
} }
$operation = new DropCollection($this->databaseName, $collectionName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
if ( ! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new DropCollection($this->databaseName, $collectionName, $options);
return $operation->execute($server); return $operation->execute($server);
} }
......
...@@ -13,4 +13,14 @@ class UnsupportedException extends RuntimeException implements Exception ...@@ -13,4 +13,14 @@ class UnsupportedException extends RuntimeException implements Exception
{ {
return new static('Collations are not supported by the server executing this operation'); return new static('Collations are not supported by the server executing this operation');
} }
/**
* Thrown when a command's writeConcern option is not supported by a server.
*
* @return self
*/
public static function writeConcernNotSupported()
{
return new static('Write concern is not supported by the server executing this command');
}
} }
...@@ -6,6 +6,7 @@ use MongoDB\Driver\Command; ...@@ -6,6 +6,7 @@ use MongoDB\Driver\Command;
use MongoDB\Driver\ReadConcern; use MongoDB\Driver\ReadConcern;
use MongoDB\Driver\ReadPreference; use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server; use MongoDB\Driver\Server;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException; use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException; use MongoDB\Exception\UnsupportedException;
...@@ -26,6 +27,7 @@ class Aggregate implements Executable ...@@ -26,6 +27,7 @@ class Aggregate implements Executable
private static $wireVersionForCursor = 2; private static $wireVersionForCursor = 2;
private static $wireVersionForDocumentLevelValidation = 4; private static $wireVersionForDocumentLevelValidation = 4;
private static $wireVersionForReadConcern = 4; private static $wireVersionForReadConcern = 4;
private static $wireVersionForWriteConcern = 5;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
...@@ -81,6 +83,12 @@ class Aggregate implements Executable ...@@ -81,6 +83,12 @@ class Aggregate implements Executable
* For servers >= 2.6, this option allows users to turn off cursors if * For servers >= 2.6, this option allows users to turn off cursors if
* necessary to aid in mongod/mongos upgrades. * necessary to aid in mongod/mongos upgrades.
* *
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern. This only
* applies when the $out stage is specified.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
* @param array $pipeline List of pipeline operations * @param array $pipeline List of pipeline operations
...@@ -148,6 +156,10 @@ class Aggregate implements Executable ...@@ -148,6 +156,10 @@ class Aggregate implements Executable
throw InvalidArgumentException::invalidType('"useCursor" option', $options['useCursor'], 'boolean'); throw InvalidArgumentException::invalidType('"useCursor" option', $options['useCursor'], 'boolean');
} }
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
if (isset($options['batchSize']) && ! $options['useCursor']) { if (isset($options['batchSize']) && ! $options['useCursor']) {
throw new InvalidArgumentException('"batchSize" option should not be used if "useCursor" is false'); throw new InvalidArgumentException('"batchSize" option should not be used if "useCursor" is false');
} }
...@@ -169,7 +181,7 @@ class Aggregate implements Executable ...@@ -169,7 +181,7 @@ class Aggregate implements Executable
* @param Server $server * @param Server $server
* @return Traversable * @return Traversable
* @throws UnexpectedValueException if the command response was malformed * @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if collation is used and unsupported * @throws UnsupportedException if collation or write concern is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
...@@ -177,6 +189,10 @@ class Aggregate implements Executable ...@@ -177,6 +189,10 @@ class Aggregate implements Executable
throw UnsupportedException::collationNotSupported(); throw UnsupportedException::collationNotSupported();
} }
if (isset($this->options['writeConcern']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$isCursorSupported = \MongoDB\server_supports_feature($server, self::$wireVersionForCursor); $isCursorSupported = \MongoDB\server_supports_feature($server, self::$wireVersionForCursor);
$readPreference = isset($this->options['readPreference']) ? $this->options['readPreference'] : null; $readPreference = isset($this->options['readPreference']) ? $this->options['readPreference'] : null;
...@@ -240,6 +256,10 @@ class Aggregate implements Executable ...@@ -240,6 +256,10 @@ class Aggregate implements Executable
$cmd['readConcern'] = \MongoDB\read_concern_as_document($this->options['readConcern']); $cmd['readConcern'] = \MongoDB\read_concern_as_document($this->options['readConcern']);
} }
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']);
}
if ($this->options['useCursor']) { if ($this->options['useCursor']) {
$cmd['cursor'] = isset($this->options["batchSize"]) $cmd['cursor'] = isset($this->options["batchSize"])
? ['batchSize' => $this->options["batchSize"]] ? ['batchSize' => $this->options["batchSize"]]
......
...@@ -4,6 +4,7 @@ namespace MongoDB\Operation; ...@@ -4,6 +4,7 @@ namespace MongoDB\Operation;
use MongoDB\Driver\Command; use MongoDB\Driver\Command;
use MongoDB\Driver\Server; use MongoDB\Driver\Server;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException; use MongoDB\Exception\UnsupportedException;
...@@ -20,6 +21,7 @@ class CreateCollection implements Executable ...@@ -20,6 +21,7 @@ class CreateCollection implements Executable
const NO_PADDING = 2; const NO_PADDING = 2;
private static $wireVersionForCollation = 5; private static $wireVersionForCollation = 5;
private static $wireVersionForWriteConcern = 5;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
...@@ -69,6 +71,11 @@ class CreateCollection implements Executable ...@@ -69,6 +71,11 @@ class CreateCollection implements Executable
* *
* * validator (document): Validation rules or expressions. * * validator (document): Validation rules or expressions.
* *
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @see http://source.wiredtiger.com/2.4.1/struct_w_t___s_e_s_s_i_o_n.html#a358ca4141d59c345f401c58501276bbb * @see http://source.wiredtiger.com/2.4.1/struct_w_t___s_e_s_s_i_o_n.html#a358ca4141d59c345f401c58501276bbb
* @see https://docs.mongodb.org/manual/core/document-validation/ * @see https://docs.mongodb.org/manual/core/document-validation/
* @param string $databaseName Database name * @param string $databaseName Database name
...@@ -130,6 +137,10 @@ class CreateCollection implements Executable ...@@ -130,6 +137,10 @@ class CreateCollection implements Executable
throw InvalidArgumentException::invalidType('"validator" option', $options['validator'], 'array or object'); throw InvalidArgumentException::invalidType('"validator" option', $options['validator'], 'array or object');
} }
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName; $this->collectionName = (string) $collectionName;
$this->options = $options; $this->options = $options;
...@@ -141,7 +152,7 @@ class CreateCollection implements Executable ...@@ -141,7 +152,7 @@ class CreateCollection implements Executable
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return array|object Command result document * @return array|object Command result document
* @throws UnsupportedException if collation is used and unsupported * @throws UnsupportedException if collation or write concern is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
...@@ -149,6 +160,10 @@ class CreateCollection implements Executable ...@@ -149,6 +160,10 @@ class CreateCollection implements Executable
throw UnsupportedException::collationNotSupported(); throw UnsupportedException::collationNotSupported();
} }
if (isset($this->options['writeConcern']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$cursor = $server->executeCommand($this->databaseName, $this->createCommand()); $cursor = $server->executeCommand($this->databaseName, $this->createCommand());
if (isset($this->options['typeMap'])) { if (isset($this->options['typeMap'])) {
...@@ -179,6 +194,10 @@ class CreateCollection implements Executable ...@@ -179,6 +194,10 @@ class CreateCollection implements Executable
} }
} }
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']);
}
return new Command($cmd); return new Command($cmd);
} }
} }
...@@ -22,21 +22,31 @@ class CreateIndexes implements Executable ...@@ -22,21 +22,31 @@ class CreateIndexes implements Executable
{ {
private static $wireVersionForCollation = 5; private static $wireVersionForCollation = 5;
private static $wireVersionForCommand = 2; private static $wireVersionForCommand = 2;
private static $wireVersionForWriteConcern = 5;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $indexes = []; private $indexes = [];
private $isCollationUsed = false; private $isCollationUsed = false;
private $options = [];
/** /**
* Constructs a createIndexes command. * Constructs a createIndexes command.
* *
* Supported options:
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
* @param array[] $indexes List of index specifications * @param array[] $indexes List of index specifications
* @param array $options Command options
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function __construct($databaseName, $collectionName, array $indexes) public function __construct($databaseName, $collectionName, array $indexes, array $options = [])
{ {
if (empty($indexes)) { if (empty($indexes)) {
throw new InvalidArgumentException('$indexes is empty'); throw new InvalidArgumentException('$indexes is empty');
...@@ -66,8 +76,13 @@ class CreateIndexes implements Executable ...@@ -66,8 +76,13 @@ class CreateIndexes implements Executable
$expectedIndex += 1; $expectedIndex += 1;
} }
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName; $this->collectionName = (string) $collectionName;
$this->options = $options;
} }
/** /**
...@@ -79,7 +94,7 @@ class CreateIndexes implements Executable ...@@ -79,7 +94,7 @@ class CreateIndexes implements Executable
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return string[] The names of the created indexes * @return string[] The names of the created indexes
* @throws UnsupportedException if collation is used and unsupported * @throws UnsupportedException if collation or write concern is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
...@@ -87,6 +102,10 @@ class CreateIndexes implements Executable ...@@ -87,6 +102,10 @@ class CreateIndexes implements Executable
throw UnsupportedException::collationNotSupported(); throw UnsupportedException::collationNotSupported();
} }
if (isset($this->options['writeConcern']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
if (\MongoDB\server_supports_feature($server, self::$wireVersionForCommand)) { if (\MongoDB\server_supports_feature($server, self::$wireVersionForCommand)) {
$this->executeCommand($server); $this->executeCommand($server);
} else { } else {
...@@ -104,12 +123,16 @@ class CreateIndexes implements Executable ...@@ -104,12 +123,16 @@ class CreateIndexes implements Executable
*/ */
private function executeCommand(Server $server) private function executeCommand(Server $server)
{ {
$command = new Command([ $cmd = [
'createIndexes' => $this->collectionName, 'createIndexes' => $this->collectionName,
'indexes' => $this->indexes, 'indexes' => $this->indexes,
]); ];
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']);
}
$server->executeCommand($this->databaseName, $command); $server->executeCommand($this->databaseName, new Command($cmd));
} }
/** /**
......
...@@ -91,6 +91,7 @@ class Distinct implements Executable ...@@ -91,6 +91,7 @@ class Distinct implements Executable
* @param Server $server * @param Server $server
* @return mixed[] * @return mixed[]
* @throws UnexpectedValueException if the command response was malformed * @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if collation is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
......
...@@ -4,6 +4,7 @@ namespace MongoDB\Operation; ...@@ -4,6 +4,7 @@ namespace MongoDB\Operation;
use MongoDB\Driver\Command; use MongoDB\Driver\Command;
use MongoDB\Driver\Server; use MongoDB\Driver\Server;
use MongoDB\Driver\WriteConcern;
use MongoDB\Driver\Exception\RuntimeException; use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
...@@ -18,6 +19,7 @@ use MongoDB\Exception\InvalidArgumentException; ...@@ -18,6 +19,7 @@ use MongoDB\Exception\InvalidArgumentException;
class DropCollection implements Executable class DropCollection implements Executable
{ {
private static $errorMessageNamespaceNotFound = 'ns not found'; private static $errorMessageNamespaceNotFound = 'ns not found';
private static $wireVersionForWriteConcern = 5;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
...@@ -31,6 +33,11 @@ class DropCollection implements Executable ...@@ -31,6 +33,11 @@ class DropCollection implements Executable
* * typeMap (array): Type map for BSON deserialization. This will be used * * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document. * for the returned command result document.
* *
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
* @param array $options Command options * @param array $options Command options
...@@ -41,6 +48,10 @@ class DropCollection implements Executable ...@@ -41,6 +48,10 @@ class DropCollection implements Executable
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
} }
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName; $this->collectionName = (string) $collectionName;
$this->options = $options; $this->options = $options;
...@@ -52,11 +63,16 @@ class DropCollection implements Executable ...@@ -52,11 +63,16 @@ class DropCollection implements Executable
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return array|object Command result document * @return array|object Command result document
* @throws UnsupportedException if writeConcern is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
if (isset($this->options['writeConcern']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
try { try {
$cursor = $server->executeCommand($this->databaseName, new Command(['drop' => $this->collectionName])); $cursor = $server->executeCommand($this->databaseName, $this->createCommand());
} catch (RuntimeException $e) { } catch (RuntimeException $e) {
/* The server may return an error if the collection does not exist. /* The server may return an error if the collection does not exist.
* Check for an error message (unfortunately, there isn't a code) * Check for an error message (unfortunately, there isn't a code)
...@@ -75,4 +91,20 @@ class DropCollection implements Executable ...@@ -75,4 +91,20 @@ class DropCollection implements Executable
return current($cursor->toArray()); return current($cursor->toArray());
} }
/**
* Create the drop command.
*
* @return Command
*/
private function createCommand()
{
$cmd = ['drop' => $this->collectionName];
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']);
}
return new Command($cmd);
}
} }
...@@ -4,6 +4,7 @@ namespace MongoDB\Operation; ...@@ -4,6 +4,7 @@ namespace MongoDB\Operation;
use MongoDB\Driver\Command; use MongoDB\Driver\Command;
use MongoDB\Driver\Server; use MongoDB\Driver\Server;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
/** /**
...@@ -16,6 +17,8 @@ use MongoDB\Exception\InvalidArgumentException; ...@@ -16,6 +17,8 @@ use MongoDB\Exception\InvalidArgumentException;
*/ */
class DropDatabase implements Executable class DropDatabase implements Executable
{ {
private static $wireVersionForWriteConcern = 5;
private $databaseName; private $databaseName;
private $options; private $options;
...@@ -27,6 +30,11 @@ class DropDatabase implements Executable ...@@ -27,6 +30,11 @@ class DropDatabase implements Executable
* * typeMap (array): Type map for BSON deserialization. This will be used * * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document. * for the returned command result document.
* *
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name * @param string $databaseName Database name
* @param array $options Command options * @param array $options Command options
*/ */
...@@ -36,6 +44,10 @@ class DropDatabase implements Executable ...@@ -36,6 +44,10 @@ class DropDatabase implements Executable
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
} }
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->options = $options; $this->options = $options;
} }
...@@ -46,10 +58,15 @@ class DropDatabase implements Executable ...@@ -46,10 +58,15 @@ class DropDatabase implements Executable
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return array|object Command result document * @return array|object Command result document
* @throws UnsupportedException if writeConcern is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$cursor = $server->executeCommand($this->databaseName, new Command(['dropDatabase' => 1])); if (isset($this->options['writeConcern']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$cursor = $server->executeCommand($this->databaseName, $this->createCommand());
if (isset($this->options['typeMap'])) { if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']); $cursor->setTypeMap($this->options['typeMap']);
...@@ -57,4 +74,20 @@ class DropDatabase implements Executable ...@@ -57,4 +74,20 @@ class DropDatabase implements Executable
return current($cursor->toArray()); return current($cursor->toArray());
} }
/**
* Create the dropDatabase command.
*
* @return Command
*/
private function createCommand()
{
$cmd = ['dropDatabase' => 1];
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']);
}
return new Command($cmd);
}
} }
...@@ -4,6 +4,7 @@ namespace MongoDB\Operation; ...@@ -4,6 +4,7 @@ namespace MongoDB\Operation;
use MongoDB\Driver\Command; use MongoDB\Driver\Command;
use MongoDB\Driver\Server; use MongoDB\Driver\Server;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
/** /**
...@@ -15,6 +16,8 @@ use MongoDB\Exception\InvalidArgumentException; ...@@ -15,6 +16,8 @@ use MongoDB\Exception\InvalidArgumentException;
*/ */
class DropIndexes implements Executable class DropIndexes implements Executable
{ {
private static $wireVersionForWriteConcern = 5;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $indexName; private $indexName;
...@@ -28,6 +31,11 @@ class DropIndexes implements Executable ...@@ -28,6 +31,11 @@ class DropIndexes implements Executable
* * typeMap (array): Type map for BSON deserialization. This will be used * * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document. * for the returned command result document.
* *
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
* @param string $indexName Index name (use "*" to drop all indexes) * @param string $indexName Index name (use "*" to drop all indexes)
...@@ -46,6 +54,10 @@ class DropIndexes implements Executable ...@@ -46,6 +54,10 @@ class DropIndexes implements Executable
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
} }
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName; $this->collectionName = (string) $collectionName;
$this->indexName = $indexName; $this->indexName = $indexName;
...@@ -58,15 +70,15 @@ class DropIndexes implements Executable ...@@ -58,15 +70,15 @@ class DropIndexes implements Executable
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return array|object Command result document * @return array|object Command result document
* @throws UnsupportedException if writeConcern is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$cmd = [ if (isset($this->options['writeConcern']) && ! \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) {
'dropIndexes' => $this->collectionName, throw UnsupportedException::writeConcernNotSupported();
'index' => $this->indexName, }
];
$cursor = $server->executeCommand($this->databaseName, new Command($cmd)); $cursor = $server->executeCommand($this->databaseName, $this->createCommand());
if (isset($this->options['typeMap'])) { if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']); $cursor->setTypeMap($this->options['typeMap']);
...@@ -74,4 +86,23 @@ class DropIndexes implements Executable ...@@ -74,4 +86,23 @@ class DropIndexes implements Executable
return current($cursor->toArray()); return current($cursor->toArray());
} }
/**
* Create the dropIndexes command.
*
* @return Command
*/
private function createCommand()
{
$cmd = [
'dropIndexes' => $this->collectionName,
'index' => $this->indexName,
];
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']);
}
return new Command($cmd);
}
} }
...@@ -184,6 +184,7 @@ class Find implements Executable ...@@ -184,6 +184,7 @@ class Find implements Executable
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return Cursor * @return Cursor
* @throws UnsupportedException if collation is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
......
...@@ -66,8 +66,9 @@ class FindAndModify implements Executable ...@@ -66,8 +66,9 @@ class FindAndModify implements Executable
* matches the query. This option is ignored for remove operations. The * matches the query. This option is ignored for remove operations. The
* default is false. * default is false.
* *
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern. This option * * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
* is only supported for server versions >= 3.2. *
* This is not supported for server versions < 3.2.
* *
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
...@@ -142,6 +143,7 @@ class FindAndModify implements Executable ...@@ -142,6 +143,7 @@ class FindAndModify implements Executable
* @param Server $server * @param Server $server
* @return object|null * @return object|null
* @throws UnexpectedValueException if the command response was malformed * @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if collation is used and unsupported
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
...@@ -205,6 +207,10 @@ class FindAndModify implements Executable ...@@ -205,6 +207,10 @@ class FindAndModify implements Executable
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation']; $cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
} }
/* In the future, we should throw an exception if the "writeConcern"
* option is specified and not supported by the server (see: SPEC-494).
* For BC in 1.x, we will silently omit it for incompatible servers.
*/
if (isset($this->options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) { if (isset($this->options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWriteConcern)) {
$cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']); $cmd['writeConcern'] = \MongoDB\write_concern_as_document($this->options['writeConcern']);
} }
......
...@@ -73,6 +73,10 @@ class AggregateTest extends TestCase ...@@ -73,6 +73,10 @@ class AggregateTest extends TestCase
$options[][] = ['useCursor' => $value]; $options[][] = ['useCursor' => $value];
} }
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options; return $options;
} }
......
...@@ -71,6 +71,10 @@ class CreateCollectionTest extends TestCase ...@@ -71,6 +71,10 @@ class CreateCollectionTest extends TestCase
$options[][] = ['validator' => $value]; $options[][] = ['validator' => $value];
} }
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options; return $options;
} }
} }
...@@ -8,27 +8,47 @@ class CreateIndexesTest extends TestCase ...@@ -8,27 +8,47 @@ class CreateIndexesTest extends TestCase
{ {
/** /**
* @expectedException MongoDB\Exception\InvalidArgumentException * @expectedException MongoDB\Exception\InvalidArgumentException
* @expectedExceptionMessage $indexes is empty * @expectedExceptionMessage $indexes is not a list (unexpected index: "1")
*/ */
public function testCreateIndexesRequiresAtLeastOneIndex() public function testConstructorIndexesArgumentMustBeAList()
{ {
new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), []); new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [1 => ['key' => ['x' => 1]]]);
} }
/** /**
* @expectedException MongoDB\Exception\InvalidArgumentException * @expectedException MongoDB\Exception\InvalidArgumentException
* @expectedExceptionMessage $indexes is not a list (unexpected index: "1") * @dataProvider provideInvalidConstructorOptions
*/ */
public function testConstructorIndexesArgumentMustBeAList() public function testConstructorOptionTypeChecks(array $options)
{ {
new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [1 => ['key' => ['x' => 1]]]); new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [['key' => ['x' => 1]]], $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options;
}
/**
* @expectedException MongoDB\Exception\InvalidArgumentException
* @expectedExceptionMessage $indexes is empty
*/
public function testConstructorRequiresAtLeastOneIndex()
{
new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), []);
} }
/** /**
* @expectedException MongoDB\Exception\InvalidArgumentException * @expectedException MongoDB\Exception\InvalidArgumentException
* @dataProvider provideInvalidIndexSpecificationTypes * @dataProvider provideInvalidIndexSpecificationTypes
*/ */
public function testCreateIndexesRequiresIndexSpecificationsToBeAnArray($index) public function testConstructorRequiresIndexSpecificationsToBeAnArray($index)
{ {
new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [$index]); new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [$index]);
} }
......
...@@ -23,6 +23,10 @@ class DropCollectionTest extends TestCase ...@@ -23,6 +23,10 @@ class DropCollectionTest extends TestCase
$options[][] = ['typeMap' => $value]; $options[][] = ['typeMap' => $value];
} }
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options; return $options;
} }
} }
...@@ -23,6 +23,10 @@ class DropDatabaseTest extends TestCase ...@@ -23,6 +23,10 @@ class DropDatabaseTest extends TestCase
$options[][] = ['typeMap' => $value]; $options[][] = ['typeMap' => $value];
} }
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options; return $options;
} }
} }
...@@ -31,6 +31,10 @@ class DropIndexesTest extends TestCase ...@@ -31,6 +31,10 @@ class DropIndexesTest extends TestCase
$options[][] = ['typeMap' => $value]; $options[][] = ['typeMap' => $value];
} }
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options; return $options;
} }
} }
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