diff --git a/src/Operation/Explain.php b/src/Operation/Explain.php
index defbbf7ef9f89eed5b93e5b332e63644b8c360ba..5ba76bd1c2ad8f714fe659b7e7cc9d8c74124899 100644
--- a/src/Operation/Explain.php
+++ b/src/Operation/Explain.php
@@ -80,16 +80,12 @@ class Explain implements Executable
throw UnsupportedException::explainNotSupported();
}
- if ($this->explainable instanceOf \MongoDB\Operation\Distinct) {
- if (! \MongoDB\server_supports_feature($server, self::$wireVersionForDistinct)) {
- throw UnsupportedException::explainNotSupported();
- }
+ if ($this->explainable instanceof \MongoDB\Operation\Distinct && ! \MongoDB\server_supports_feature($server, self::$wireVersionForDistinct)) {
+ throw UnsupportedException::explainNotSupported();
}
- if ($this->explainable instanceOf \MongoDB\Operation\FindAndModify) {
- if (! \MongoDB\server_supports_feature($server, self::$wireVersionForFindAndModify)) {
- throw UnsupportedException::explainNotSupported();
- }
+ if ($this->explainable instanceof \MongoDB\Operation\FindAndModify && ! \MongoDB\server_supports_feature($server, self::$wireVersionForFindAndModify)) {
+ throw UnsupportedException::explainNotSupported();
}
$cmd = ['explain' => $this->explainable->getCommandDocument()];
diff --git a/tests/Operation/ExplainFunctionalTest.php b/tests/Operation/ExplainFunctionalTest.php
index a593403717bf12486c12b6a4367c0995b0057da3..064765fa498bcc66c5f1f7fbd280f49fd956a61c 100644
--- a/tests/Operation/ExplainFunctionalTest.php
+++ b/tests/Operation/ExplainFunctionalTest.php
@@ -22,65 +22,10 @@ class ExplainFunctionalTest extends FunctionalTestCase
}
}
- public function testCountAllPlansExecution()
- {
- $insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
- ['x' => 0],
- ['x' => 1],
- ['x' => 2],
- ['y' => 3]
- ]);
- $insertMany->execute($this->getPrimaryServer());
-
- $operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testCountDefaultVerbosity()
- {
- $insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
- ['x' => 0],
- ['x' => 1],
- ['x' => 2],
- ['y' => 3]
- ]);
- $insertMany->execute($this->getPrimaryServer());
-
- $operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testCountExecutionStats()
- {
- $insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
- ['x' => 0],
- ['x' => 1],
- ['x' => 2],
- ['y' => 3]
- ]);
- $insertMany->execute($this->getPrimaryServer());
-
- $operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
-
- $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testCountQueryPlanner()
+ /**
+ * @dataProvider provideVerbosityInformation
+ */
+ public function testCount($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
{
$insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
['x' => 0],
@@ -91,62 +36,16 @@ class ExplainFunctionalTest extends FunctionalTestCase
$insertMany->execute($this->getPrimaryServer());
$operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => ['$gte' => 1]], []);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertFalse(array_key_exists('executionStats', $result));
- }
-
- public function testDistinctAllPlansExecution()
- {
- if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
- $this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
- }
-
- $operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
+ $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
$result = $explainOperation->execute($this->getPrimaryServer());
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
+ $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
}
- public function testDistinctDefaultVerbosity()
- {
- if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
- $this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
- }
-
- $operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testDistinctExecutionStats()
- {
- if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
- $this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
- }
-
- $operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testDistinctQueryPlanner()
+ /**
+ * @dataProvider provideVerbosityInformation
+ */
+ public function testDistinct($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
{
if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
$this->markTestSkipped('Distinct is not supported on servers with version < 3.2');
@@ -154,62 +53,16 @@ class ExplainFunctionalTest extends FunctionalTestCase
$operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
+ $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
$result = $explainOperation->execute($this->getPrimaryServer());
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertFalse(array_key_exists('executionStats', $result));
+ $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
}
- public function testFindAndModifyAllPlansExecution()
- {
- if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
- $this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
- }
-
- $operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testFindAndModifyDefaultVerbosity()
- {
- if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
- $this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
- }
-
- $operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testFindAndModifyExecutionStats()
- {
- if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
- $this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
- }
-
- $operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testFindAndModifyQueryPlanner()
+ /**
+ * @dataProvider provideVerbosityInformation
+ */
+ public function testFindAndModify($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
{
if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
$this->markTestSkipped('FindAndModify is not supported on servers with version < 3.2');
@@ -217,69 +70,31 @@ class ExplainFunctionalTest extends FunctionalTestCase
$operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true]);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
+ $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
$result = $explainOperation->execute($this->getPrimaryServer());
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertFalse(array_key_exists('executionStats', $result));
+ $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
}
- public function testFindAllPlansExecution()
- {
- $this->createFixtures(3);
-
- $operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testFindDefaultVerbosity()
- {
- $this->createFixtures(3);
-
- $operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testFindExecutionStats()
- {
- $this->createFixtures(3);
-
- $operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testFindQueryPlanner()
+ /**
+ * @dataProvider provideVerbosityInformation
+ */
+ public function testFind($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
{
$this->createFixtures(3);
$operation = new Find($this->getDatabaseName(), $this->getCollectionName(), [], ['readConcern' => $this->createDefaultReadConcern()]);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
+ $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
$result = $explainOperation->execute($this->getPrimaryServer());
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertFalse(array_key_exists('executionStats', $result));
+ $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
}
- public function testFindMaxAwait()
+ /**
+ * @dataProvider provideVerbosityInformation
+ */
+ public function testFindMaxAwait($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
{
if (version_compare($this->getServerVersion(), '3.2.0', '<')) {
$this->markTestSkipped('maxAwaitTimeMS option is not supported');
@@ -312,67 +127,49 @@ class ExplainFunctionalTest extends FunctionalTestCase
$operation = new Find($databaseName, $cappedCollectionName, [], ['cursorType' => Find::TAILABLE_AWAIT, 'maxAwaitTimeMS' => $maxAwaitTimeMS]);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
- }
-
- public function testFindOneAllPlansExecution()
- {
- $this->createFixtures(1);
-
- $operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_ALL_PLANS, 'typeMap' => ['root' => 'array']]);
+ $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
$result = $explainOperation->execute($this->getPrimaryServer());
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
+ $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
}
- public function testFindOneDefaultVerbosity()
+ /**
+ * @dataProvider provideVerbosityInformation
+ */
+ public function testFindOne($verbosity, $executionStatsExpected, $allPlansExecutionExpected)
{
$this->createFixtures(1);
$operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['typeMap' => ['root' => 'array']]);
+ $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => $verbosity, 'typeMap' => ['root' => 'array', 'document' => 'array']]);
$result = $explainOperation->execute($this->getPrimaryServer());
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertTrue(array_key_exists('allPlansExecution', $result['executionStats']));
+ $this->assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected);
}
- public function testFindOneExecutionStats()
+ public function provideVerbosityInformation()
{
- $this->createFixtures(1);
-
- $operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_EXEC_STATS, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertTrue(array_key_exists('executionStats', $result));
- $this->assertFalse(array_key_exists('allPlansExecution', $result['executionStats']));
+ return [
+ [Explain::VERBOSITY_ALL_PLANS, true, true],
+ [Explain::VERBOSITY_EXEC_STATS, true, false],
+ [Explain::VERBOSITY_QUERY, false, false]
+ ];
}
- public function testFindOneQueryPlanner()
+ private function assertExplainResult($result, $executionStatsExpected, $allPlansExecutionExpected)
{
- $this->createFixtures(1);
-
- $operation = new FindOne($this->getDatabaseName(), $this->getCollectionName(), []);
-
- $explainOperation = new Explain($this->getDatabaseName(), $operation, ['verbosity' => Explain::VERBOSITY_QUERY, 'typeMap' => ['root' => 'array']]);
- $result = $explainOperation->execute($this->getPrimaryServer());
-
- $this->assertTrue(array_key_exists('queryPlanner', $result));
- $this->assertFalse(array_key_exists('executionStats', $result));
+ $this->assertArrayHasKey('queryPlanner', $result);
+ if ($executionStatsExpected) {
+ $this->assertArrayHasKey('executionStats', $result);
+ if ($allPlansExecutionExpected) {
+ $this->assertArrayHasKey('allPlansExecution', $result['executionStats']);
+ } else {
+ $this->assertArrayNotHasKey('allPlansExecution', $result['executionStats']);
+ }
+ } else {
+ $this->assertArrayNotHasKey('executionStats', $result);
+ }
}
/**
diff --git a/tests/Operation/ExplainTest.php b/tests/Operation/ExplainTest.php
index 1372affc7f99bd3cb91888b8ab166564bf436b16..6711e887fd620ec5e041e3ab91ca53fb7538aabf 100644
--- a/tests/Operation/ExplainTest.php
+++ b/tests/Operation/ExplainTest.php
@@ -12,19 +12,9 @@ class ExplainTest extends TestCase
* @expectedException MongoDB\Exception\InvalidArgumentException
* @dataProvider provideInvalidConstructorOptions
*/
- public function testConstructorOptionTypeChecksForCount(array $options)
+ public function testConstructorOptionTypeChecks(array $options)
{
- $explainable = new Count($this->getDatabaseName(), $this->getCollectionName(),[]);
- new Explain($this->getDatabaseName(), $explainable, $options);
- }
-
- /**
- * @expectedException MongoDB\Exception\InvalidArgumentException
- * @dataProvider provideInvalidConstructorOptions
- */
- public function testConstructorOptionTypeChecksForDistinct(array $options)
- {
- $explainable = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', []);
+ $explainable = $this->createMock('MongoDB\Operation\Explainable');
new Explain($this->getDatabaseName(), $explainable, $options);
}