Commit 5c266962 authored by Jeremy Mikola's avatar Jeremy Mikola

PHPLIB-68: Throw when accessing fields in unacknowledged write result

parent 42683dc5
......@@ -2,8 +2,8 @@
namespace MongoDB;
use MongoDB\BSON\ObjectId;
use MongoDB\Driver\WriteResult;
use MongoDB\Exception\BadMethodCallException;
/**
* Result class for a bulk write operation.
......@@ -12,6 +12,7 @@ class BulkWriteResult
{
private $writeResult;
private $insertedIds;
private $isAcknowledged;
/**
* Constructor.
......@@ -23,41 +24,53 @@ class BulkWriteResult
{
$this->writeResult = $writeResult;
$this->insertedIds = $insertedIds;
$this->isAcknowledged = $writeResult->isAcknowledged();
}
/**
* Return the number of documents that were deleted.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see BulkWriteResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getDeletedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getDeletedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return the number of documents that were inserted.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see BulkWriteResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getInsertedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getInsertedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return a map of the inserted documents' IDs.
*
* The index of each ID in the map corresponds to the document's position
* in bulk operation. If the document had an ID prior to insertion (i.e. the
* driver did not generate an ID), this will contain its "_id" field value.
* Any driver-generated ID will be an MongoDB\Driver\ObjectID instance.
* The index of each ID in the map corresponds to the document's position in
* the bulk operation. If the document had an ID prior to insertion (i.e.
* the driver did not generate an ID), this will contain its "_id" field
* value. Any driver-generated ID will be an MongoDB\Driver\ObjectID
* instance.
*
* @return mixed[]
*/
......@@ -69,43 +82,60 @@ class BulkWriteResult
/**
* Return the number of documents that were matched by the filter.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see BulkWriteResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getMatchedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getMatchedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return the number of documents that were modified.
*
* This value is undefined if the write was not acknowledged or if the write
* executed as a legacy operation instead of write command.
* This value is undefined (i.e. null) if the write executed as a legacy
* operation instead of command.
*
* This method should only be called if the write was acknowledged.
*
* @see BulkWriteResult::isAcknowledged()
* @return integer|null
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getModifiedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getModifiedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return the number of documents that were upserted.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see BulkWriteResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getUpsertedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getUpsertedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return a map of the upserted documents' IDs.
*
......@@ -114,13 +144,21 @@ class BulkWriteResult
* server did not need to generate an ID), this will contain its "_id". Any
* server-generated ID will be an MongoDB\Driver\ObjectID instance.
*
* This method should only be called if the write was acknowledged.
*
* @see BulkWriteResult::isAcknowledged()
* @return mixed[]
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getUpsertedIds()
{
if ($this->isAcknowledged) {
return $this->writeResult->getUpsertedIds();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return whether this update was acknowledged by the server.
*
......@@ -131,6 +169,6 @@ class BulkWriteResult
*/
public function isAcknowledged()
{
return $this->writeResult->isAcknowledged();
return $this->isAcknowledged;
}
}
......@@ -3,6 +3,7 @@
namespace MongoDB;
use MongoDB\Driver\WriteResult;
use MongoDB\Exception\BadMethodCallException;
/**
* Result class for a delete operation.
......@@ -10,6 +11,7 @@ use MongoDB\Driver\WriteResult;
class DeleteResult
{
private $writeResult;
private $isAcknowledged;
/**
* Constructor.
......@@ -19,21 +21,27 @@ class DeleteResult
public function __construct(WriteResult $writeResult)
{
$this->writeResult = $writeResult;
$this->isAcknowledged = $writeResult->isAcknowledged();
}
/**
* Return the number of documents that were deleted.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see UpdateResult::isAcknowledged()
* @see DeleteResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getDeletedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getDeletedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return whether this delete was acknowledged by the server.
*
......@@ -44,6 +52,6 @@ class DeleteResult
*/
public function isAcknowledged()
{
return $this->writeResult->isAcknowledged();
return $this->isAcknowledged;
}
}
......@@ -4,4 +4,11 @@ namespace MongoDB\Exception;
class BadMethodCallException extends \BadMethodCallException implements Exception
{
/**
* Thrown when accessing a result field on an unacknowledged write result.
*/
public static function unacknowledgedWriteResultAccess($method)
{
return new static(sprintf('%s should not be called for an unacknowledged write result', $method));
}
}
......@@ -3,14 +3,16 @@
namespace MongoDB;
use MongoDB\Driver\WriteResult;
use MongoDB\Exception\BadMethodCallException;
/**
* Result class for a multi-document write operation.
* Result class for a multi-document insert operation.
*/
class InsertManyResult
{
private $writeResult;
private $insertedIds;
private $isAcknowledged;
/**
* Constructor.
......@@ -22,28 +24,35 @@ class InsertManyResult
{
$this->writeResult = $writeResult;
$this->insertedIds = $insertedIds;
$this->isAcknowledged = $writeResult->isAcknowledged();
}
/**
* Return the number of documents that were inserted.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see InsertManyResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getInsertedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getInsertedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return a map of the inserted documents' IDs.
*
* The index of each ID in the map corresponds to the document's position
* in bulk operation. If the document had an ID prior to insertion (i.e. the
* driver did not generate an ID), this will contain its "_id" field value.
* Any driver-generated ID will be an MongoDB\Driver\ObjectID instance.
* The index of each ID in the map corresponds to the document's position in
* the bulk operation. If the document had an ID prior to insertion (i.e.
* the driver did not generate an ID), this will contain its "_id" field
* value. Any driver-generated ID will be an MongoDB\Driver\ObjectID
* instance.
*
* @return mixed[]
*/
......
......@@ -3,6 +3,7 @@
namespace MongoDB;
use MongoDB\Driver\WriteResult;
use MongoDB\Exception\BadMethodCallException;
/**
* Result class for a single-document insert operation.
......@@ -11,6 +12,7 @@ class InsertOneResult
{
private $writeResult;
private $insertedId;
private $isAcknowledged;
/**
* Constructor.
......@@ -22,21 +24,27 @@ class InsertOneResult
{
$this->writeResult = $writeResult;
$this->insertedId = $insertedId;
$this->isAcknowledged = $writeResult->isAcknowledged();
}
/**
* Return the number of documents that were inserted.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see InsertOneResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getInsertedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getInsertedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return the inserted document's ID.
*
......@@ -57,6 +65,10 @@ class InsertOneResult
* If the insert was not acknowledged, other fields from the WriteResult
* (e.g. insertedCount) will be undefined.
*
* If the insert was not acknowledged, other fields from the WriteResult
* (e.g. insertedCount) will be undefined and their getter methods should
* not be invoked.
*
* @return boolean
*/
public function isAcknowledged()
......
......@@ -3,6 +3,7 @@
namespace MongoDB;
use MongoDB\Driver\WriteResult;
use MongoDB\Exception\BadMethodCallException;
/**
* Result class for an update operation.
......@@ -10,6 +11,7 @@ use MongoDB\Driver\WriteResult;
class UpdateResult
{
private $writeResult;
private $isAcknowledged;
/**
* Constructor.
......@@ -19,72 +21,101 @@ class UpdateResult
public function __construct(WriteResult $writeResult)
{
$this->writeResult = $writeResult;
$this->isAcknowledged = $writeResult->isAcknowledged();
}
/**
* Return the number of documents that were matched by the filter.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see UpdateResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getMatchedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getMatchedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return the number of documents that were modified.
*
* This value is undefined if the write was not acknowledged or if the write
* executed as a legacy operation instead of write command.
* This value is undefined (i.e. null) if the write executed as a legacy
* operation instead of command.
*
* This method should only be called if the write was acknowledged.
*
* @see UpdateResult::isAcknowledged()
* @return integer
* @return integer|null
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getModifiedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getModifiedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return the number of documents that were upserted.
*
* This value is undefined if the write was not acknowledged.
* This method should only be called if the write was acknowledged.
*
* @see UpdateResult::isAcknowledged()
* @return integer
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getUpsertedCount()
{
if ($this->isAcknowledged) {
return $this->writeResult->getUpsertedCount();
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return the ID of the document inserted by an upsert operation.
*
* This value is undefined if an upsert did not take place.
* This value is undefined (i.e. null) if an upsert did not take place.
*
* This method should only be called if the write was acknowledged.
*
* @see UpdateResult::isAcknowledged()
* @return mixed|null
* @throws BadMethodCallException is the write result is unacknowledged
*/
public function getUpsertedId()
{
if ($this->isAcknowledged) {
foreach ($this->writeResult->getUpsertedIds() as $id) {
return $id;
}
return null;
}
throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__);
}
/**
* Return whether this update was acknowledged by the server.
*
* If the update was not acknowledged, other fields from the WriteResult
* (e.g. matchedCount) will be undefined.
* (e.g. matchedCount) will be undefined and their getter methods should not
* be invoked.
*
* @return boolean
*/
public function isAcknowledged()
{
return $this->writeResult->isAcknowledged();
return $this->isAcknowledged;
}
}
......@@ -2,7 +2,9 @@
namespace MongoDB\Tests\Collection;
use MongoDB\BulkWriteResult;
use MongoDB\Driver\BulkWrite as Bulk;
use MongoDB\Driver\WriteConcern;
use MongoDB\Operation\BulkWrite;
class BulkWriteFunctionalTest extends FunctionalTestCase
......@@ -135,6 +137,78 @@ class BulkWriteFunctionalTest extends FunctionalTestCase
$this->assertSameDocuments($expected, $this->collection->find());
}
public function testUnacknowledgedWriteConcern()
{
$ops = [['insertOne' => [['_id' => 1]]]];
$options = ['writeConcern' => new WriteConcern(0)];
$operation = new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), $ops, $options);
$result = $operation->execute($this->getPrimaryServer());
$this->assertFalse($result->isAcknowledged());
return $result;
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesDeletedCount(BulkWriteResult $result)
{
$result->getDeletedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesInsertCount(BulkWriteResult $result)
{
$result->getInsertedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesMatchedCount(BulkWriteResult $result)
{
$result->getMatchedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesModifiedCount(BulkWriteResult $result)
{
$result->getModifiedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesUpsertedCount(BulkWriteResult $result)
{
$result->getUpsertedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesUpsertedIds(BulkWriteResult $result)
{
$result->getUpsertedIds();
}
/**
* @expectedException MongoDB\Exception\InvalidArgumentException
* @expectedExceptionMessage Unknown operation type "foo" in $operations[0]
......
......@@ -2,7 +2,9 @@
namespace MongoDB\Tests\Collection;
use MongoDB\DeleteResult;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\WriteConcern;
use MongoDB\Operation\Delete;
class DeleteFunctionalTest extends FunctionalTestCase
......@@ -46,6 +48,29 @@ class DeleteFunctionalTest extends FunctionalTestCase
$this->assertSameDocuments($expected, $this->collection->find());
}
public function testUnacknowledgedWriteConcern()
{
$filter = ['_id' => 1];
$options = ['writeConcern' => new WriteConcern(0)];
$operation = new Delete($this->getDatabaseName(), $this->getCollectionName(), $filter, 0, $options);
$result = $operation->execute($this->getPrimaryServer());
$this->assertFalse($result->isAcknowledged());
return $result;
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesDeletedCount(DeleteResult $result)
{
$result->getDeletedCount();
}
/**
* Create data fixtures.
*
......
......@@ -2,6 +2,8 @@
namespace MongoDB\Tests\Collection;
use MongoDB\InsertManyResult;
use MongoDB\Driver\WriteConcern;
use MongoDB\Operation\InsertMany;
class InsertManyFunctionalTest extends FunctionalTestCase
......@@ -33,4 +35,35 @@ class InsertManyFunctionalTest extends FunctionalTestCase
$this->assertSameDocuments($expected, $this->collection->find());
}
public function testUnacknowledgedWriteConcern()
{
$documents = [['x' => 11]];
$options = ['writeConcern' => new WriteConcern(0)];
$operation = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), $documents, $options);
$result = $operation->execute($this->getPrimaryServer());
$this->assertFalse($result->isAcknowledged());
return $result;
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesInsertedCount(InsertManyResult $result)
{
$result->getInsertedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
*/
public function testUnacknowledgedWriteConcernAccessesInsertedId(InsertManyResult $result)
{
$this->assertInstanceOf('MongoDB\BSON\ObjectId', $result->getInsertedIds()[0]);
}
}
......@@ -2,6 +2,8 @@
namespace MongoDB\Tests\Collection;
use MongoDB\InsertOneResult;
use MongoDB\Driver\WriteConcern;
use MongoDB\Operation\InsertOne;
class InsertOneFunctionalTest extends FunctionalTestCase
......@@ -41,4 +43,35 @@ class InsertOneFunctionalTest extends FunctionalTestCase
$this->assertSameDocuments($expected, $this->collection->find());
}
public function testUnacknowledgedWriteConcern()
{
$document = ['x' => 11];
$options = ['writeConcern' => new WriteConcern(0)];
$operation = new InsertOne($this->getDatabaseName(), $this->getCollectionName(), $document, $options);
$result = $operation->execute($this->getPrimaryServer());
$this->assertFalse($result->isAcknowledged());
return $result;
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesInsertedCount(InsertOneResult $result)
{
$result->getInsertedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
*/
public function testUnacknowledgedWriteConcernAccessesInsertedId(InsertOneResult $result)
{
$this->assertInstanceOf('MongoDB\BSON\ObjectId', $result->getInsertedId());
}
}
......@@ -2,7 +2,9 @@
namespace MongoDB\Tests\Collection;
use MongoDB\UpdateResult;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\WriteConcern;
use MongoDB\Operation\Update;
class UpdateFunctionalTest extends FunctionalTestCase
......@@ -121,6 +123,59 @@ class UpdateFunctionalTest extends FunctionalTestCase
$this->assertSameDocuments($expected, $this->collection->find());
}
public function testUnacknowledgedWriteConcern()
{
$filter = ['_id' => 1];
$update = ['$set' => ['x' => 1]];
$options = ['writeConcern' => new WriteConcern(0)];
$operation = new Update($this->getDatabaseName(), $this->getCollectionName(), $filter, $update, $options);
$result = $operation->execute($this->getPrimaryServer());
$this->assertFalse($result->isAcknowledged());
return $result;
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesMatchedCount(UpdateResult $result)
{
$result->getMatchedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesModifiedCount(UpdateResult $result)
{
$result->getModifiedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesUpsertedCount(UpdateResult $result)
{
$result->getUpsertedCount();
}
/**
* @depends testUnacknowledgedWriteConcern
* @expectedException MongoDB\Exception\BadMethodCallException
* @expectedExceptionMessageRegExp /[\w:\\]+ should not be called for an unacknowledged write result/
*/
public function testUnacknowledgedWriteConcernAccessesUpsertedId(UpdateResult $result)
{
$result->getUpsertedId();
}
/**
* Create data fixtures.
*
......
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