Commit be6ba1e4 authored by Jeremy Mikola's avatar Jeremy Mikola

PHPLIB-285: Do not convert count's hint document to a string

parent 780fb6c3
...@@ -6,8 +6,13 @@ arg_name: option ...@@ -6,8 +6,13 @@ arg_name: option
name: hint name: hint
type: string|array|object type: string|array|object
description: | description: |
The index to use. If you specify a document, it is interpreted as an index The index to use. Specify either the index name as a string or the index key
specification from which a name will be derived. pattern as a document. If specified, then the query system will only consider
plans using the hinted index.
.. versionchanged:: 1.2
If a document is provided, it is passed to the command as-is. Previously,
the library would convert the key pattern to an index name.
interface: phpmethod interface: phpmethod
operation: ~ operation: ~
optional: true optional: true
......
...@@ -53,8 +53,9 @@ class Count implements Executable ...@@ -53,8 +53,9 @@ class Count implements Executable
* This is not supported for server versions < 3.4 and will result in an * This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used. * exception at execution time if used.
* *
* * hint (string|document): The index to use. If a document, it will be * * hint (string|document): The index to use. Specify either the index
* interpretted as an index specification and a name will be generated. * name as a string or the index key pattern as a document. If specified,
* then the query system will only consider plans using the hinted index.
* *
* * limit (integer): The maximum number of documents to count. * * limit (integer): The maximum number of documents to count.
* *
...@@ -87,14 +88,8 @@ class Count implements Executable ...@@ -87,14 +88,8 @@ class Count implements Executable
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object'); throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
} }
if (isset($options['hint'])) { if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) {
if (is_array($options['hint']) || is_object($options['hint'])) { throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object');
$options['hint'] = \MongoDB\generate_index_name($options['hint']);
}
if ( ! is_string($options['hint'])) {
throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object');
}
} }
if (isset($options['limit']) && ! is_integer($options['limit'])) { if (isset($options['limit']) && ! is_integer($options['limit'])) {
...@@ -177,7 +172,11 @@ class Count implements Executable ...@@ -177,7 +172,11 @@ class Count implements Executable
$cmd['collation'] = (object) $this->options['collation']; $cmd['collation'] = (object) $this->options['collation'];
} }
foreach (['hint', 'limit', 'maxTimeMS', 'skip'] as $option) { if (isset($this->options['hint'])) {
$cmd['hint'] = is_array($this->options['hint']) ? (object) $this->options['hint'] : $this->options['hint'];
}
foreach (['limit', 'maxTimeMS', 'skip'] as $option) {
if (isset($this->options[$option])) { if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option]; $cmd[$option] = $this->options[$option];
} }
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
namespace MongoDB\Tests\Operation; namespace MongoDB\Tests\Operation;
use MongoDB\Operation\Count; use MongoDB\Operation\Count;
use MongoDB\Operation\CreateIndexes;
use MongoDB\Operation\InsertMany;
use MongoDB\Tests\CommandObserver; use MongoDB\Tests\CommandObserver;
use stdClass; use stdClass;
...@@ -26,4 +28,49 @@ class CountFunctionalTest extends FunctionalTestCase ...@@ -26,4 +28,49 @@ class CountFunctionalTest extends FunctionalTestCase
} }
); );
} }
public function testHintOption()
{
if (version_compare($this->getServerVersion(), '2.6.0', '<')) {
$this->markTestSkipped('count command does not support "hint" option');
}
$insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
['x' => 1],
['x' => 2],
['y' => 3],
]);
$insertMany->execute($this->getPrimaryServer());
$createIndexes = new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [
['key' => ['x' => 1], 'sparse' => true, 'name' => 'sparse_x'],
['key' => ['y' => 1]],
]);
$createIndexes->execute($this->getPrimaryServer());
$hintsUsingSparseIndex = [
['x' => 1],
'sparse_x',
];
/* Per SERVER-22041, the count command in server versions before 3.3.2
* may ignore the hint option if its query predicate is empty. */
$filter = ['_id' => ['$exists' => true]];
foreach ($hintsUsingSparseIndex as $hint) {
$operation = new Count($this->getDatabaseName(), $this->getCollectionName(), $filter, ['hint' => $hint]);
$this->assertEquals(2, $operation->execute($this->getPrimaryServer()));
}
$hintsNotUsingSparseIndex = [
['_id' => 1],
['y' => 1],
'y_1',
];
foreach ($hintsNotUsingSparseIndex as $hint) {
$operation = new Count($this->getDatabaseName(), $this->getCollectionName(), $filter, ['hint' => $hint]);
$this->assertEquals(3, $operation->execute($this->getPrimaryServer()));
}
}
} }
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