PHPLIB-522: Loosen index equality checks for GridFS

parent 051f3451
...@@ -17,14 +17,18 @@ ...@@ -17,14 +17,18 @@
namespace MongoDB\GridFS; namespace MongoDB\GridFS;
use ArrayIterator;
use MongoDB\Collection; use MongoDB\Collection;
use MongoDB\Driver\Cursor; use MongoDB\Driver\Cursor;
use MongoDB\Driver\Manager; use MongoDB\Driver\Manager;
use MongoDB\Driver\ReadPreference; use MongoDB\Driver\ReadPreference;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
use MongoDB\UpdateResult; use MongoDB\UpdateResult;
use MultipleIterator;
use stdClass; use stdClass;
use function abs; use function abs;
use function count;
use function is_numeric;
use function sprintf; use function sprintf;
/** /**
...@@ -289,13 +293,15 @@ class CollectionWrapper ...@@ -289,13 +293,15 @@ class CollectionWrapper
*/ */
private function ensureChunksIndex() private function ensureChunksIndex()
{ {
$expectedIndex = ['files_id' => 1, 'n' => 1];
foreach ($this->chunksCollection->listIndexes() as $index) { foreach ($this->chunksCollection->listIndexes() as $index) {
if ($index->isUnique() && $index->getKey() === ['files_id' => 1, 'n' => 1]) { if ($index->isUnique() && $this->indexKeysMatch($expectedIndex, $index->getKey())) {
return; return;
} }
} }
$this->chunksCollection->createIndex(['files_id' => 1, 'n' => 1], ['unique' => true]); $this->chunksCollection->createIndex($expectedIndex, ['unique' => true]);
} }
/** /**
...@@ -303,13 +309,15 @@ class CollectionWrapper ...@@ -303,13 +309,15 @@ class CollectionWrapper
*/ */
private function ensureFilesIndex() private function ensureFilesIndex()
{ {
$expectedIndex = ['filename' => 1, 'uploadDate' => 1];
foreach ($this->filesCollection->listIndexes() as $index) { foreach ($this->filesCollection->listIndexes() as $index) {
if ($index->getKey() === ['filename' => 1, 'uploadDate' => 1]) { if ($this->indexKeysMatch($expectedIndex, $index->getKey())) {
return; return;
} }
} }
$this->filesCollection->createIndex(['filename' => 1, 'uploadDate' => 1]); $this->filesCollection->createIndex($expectedIndex);
} }
/** /**
...@@ -334,6 +342,36 @@ class CollectionWrapper ...@@ -334,6 +342,36 @@ class CollectionWrapper
$this->ensureChunksIndex(); $this->ensureChunksIndex();
} }
private function indexKeysMatch(array $expectedKeys, array $actualKeys) : bool
{
if (count($expectedKeys) !== count($actualKeys)) {
return false;
}
$iterator = new MultipleIterator(MultipleIterator::MIT_NEED_ANY);
$iterator->attachIterator(new ArrayIterator($expectedKeys));
$iterator->attachIterator(new ArrayIterator($actualKeys));
foreach ($iterator as $key => $value) {
list($expectedKey, $actualKey) = $key;
list($expectedValue, $actualValue) = $value;
if ($expectedKey !== $actualKey) {
return false;
}
/* Since we don't expect special indexes (e.g. text), we mark any
* index with a non-numeric definition as unequal. All others are
* compared against their int value to avoid differences due to
* some drivers using float values in the key specification. */
if (! is_numeric($actualValue) || (int) $expectedValue !== (int) $actualValue) {
return false;
}
}
return true;
}
/** /**
* Returns whether the files collection is empty. * Returns whether the files collection is empty.
* *
......
...@@ -697,6 +697,17 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -697,6 +697,17 @@ class BucketFunctionalTest extends FunctionalTestCase
}); });
} }
public function testExistingIndexIsReused()
{
$this->filesCollection->createIndex(['filename' => 1.0, 'uploadDate' => 1], ['name' => 'test']);
$this->chunksCollection->createIndex(['files_id' => 1.0, 'n' => 1], ['name' => 'test', 'unique' => true]);
$this->bucket->uploadFromStream('filename', $this->createStream('foo'));
$this->assertIndexNotExists($this->filesCollection->getCollectionName(), 'filename_1_uploadDate_1');
$this->assertIndexNotExists($this->chunksCollection->getCollectionName(), 'files_id_1_n_1');
}
/** /**
* Asserts that a collection with the given name does not exist on the * Asserts that a collection with the given name does not exist on the
* server. * server.
...@@ -757,6 +768,29 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -757,6 +768,29 @@ class BucketFunctionalTest extends FunctionalTestCase
} }
} }
/**
* Asserts that an index with the given name does not exist for the collection.
*
* @param string $collectionName
* @param string $indexName
*/
private function assertIndexNotExists($collectionName, $indexName)
{
$operation = new ListIndexes($this->getDatabaseName(), $collectionName);
$indexes = $operation->execute($this->getPrimaryServer());
$foundIndex = false;
foreach ($indexes as $index) {
if ($index->getName() === $indexName) {
$foundIndex = true;
break;
}
}
$this->assertFalse($foundIndex, sprintf('Index %s exists', $indexName));
}
/** /**
* Return a list of invalid stream values. * Return a list of invalid stream values.
* *
......
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