Skip to content
This repository was archived by the owner on Feb 1, 2022. It is now read-only.

Commit 49d6485

Browse files
committed
PHP-1464: GridFS should not drop dupes when creating index
Additionally, we'll check for an exception after creating the index so that we can return early (instead of attempting to insert the first chunk and inevitably moving to cleanup).
1 parent c0fa5e3 commit 49d6485

2 files changed

Lines changed: 160 additions & 2 deletions

File tree

gridfs/gridfs.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ void php_mongo_ensure_gridfs_index(zval *return_value, zval *this_ptr TSRMLS_DC)
152152
{
153153
zval *index, *options;
154154

155-
/* ensure index on chunks.n */
155+
/* ensure unique index on chunks collection's "files_id" and "n" fields */
156156
MAKE_STD_ZVAL(index);
157157
array_init(index);
158158
add_assoc_long(index, "files_id", 1);
@@ -161,7 +161,6 @@ void php_mongo_ensure_gridfs_index(zval *return_value, zval *this_ptr TSRMLS_DC)
161161
MAKE_STD_ZVAL(options);
162162
array_init(options);
163163
add_assoc_bool(options, "unique", 1);
164-
add_assoc_bool(options, "dropDups", 1);
165164

166165
MONGO_METHOD2(MongoCollection, ensureIndex, return_value, getThis(), index, options);
167166

@@ -427,6 +426,12 @@ PHP_METHOD(MongoGridFS, storeBytes)
427426
php_mongo_ensure_gridfs_index(&temp, chunks TSRMLS_CC);
428427
zval_dtor(&temp);
429428

429+
/* Abort if we could not create the unique index on fs.chunks */
430+
if (EG(exception)) {
431+
gridfs_rewrite_cursor_exception(TSRMLS_C);
432+
RETURN_FALSE;
433+
}
434+
430435
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|aa/", &bytes, &bytes_len, &extra, &options) == FAILURE) {
431436
return;
432437
}
@@ -654,6 +659,12 @@ PHP_METHOD(MongoGridFS, storeFile)
654659
php_mongo_ensure_gridfs_index(&temp, chunks TSRMLS_CC);
655660
zval_dtor(&temp);
656661

662+
/* Abort if we could not create the unique index on fs.chunks */
663+
if (EG(exception)) {
664+
gridfs_rewrite_cursor_exception(TSRMLS_C);
665+
RETURN_FALSE;
666+
}
667+
657668
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|aa/", &fh, &extra, &options) == FAILURE) {
658669
return;
659670
}
@@ -944,6 +955,12 @@ PHP_METHOD(MongoGridFS, remove)
944955
php_mongo_ensure_gridfs_index(&chunktemp, chunks TSRMLS_CC);
945956
zval_dtor(&chunktemp);
946957

958+
/* Abort if we could not create the unique index on fs.chunks */
959+
if (EG(exception)) {
960+
gridfs_rewrite_cursor_exception(TSRMLS_C);
961+
RETURN_FALSE;
962+
}
963+
947964
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|za/", &criteria, &options) == FAILURE) {
948965
return;
949966
}

tests/generic/bug01464.phpt

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
--TEST--
2+
Test for PHP-1464: GridFS should not drop dupes when creating index
3+
--SKIPIF--
4+
<?php require_once "tests/utils/standalone.inc" ?>
5+
--FILE--
6+
<?php
7+
require_once "tests/utils/server.inc";
8+
9+
$host = MongoShellServer::getStandaloneInfo();
10+
11+
$mc = new MongoClient($host);
12+
$db = $mc->selectDB(dbname());
13+
14+
$filesId = new MongoId('000000000000000000000002');
15+
$data = new MongoBinData('foo', MongoBinData::BYTE_ARRAY);
16+
17+
// Drop files collection
18+
$filesCollection = $db->selectCollection('fs.files');
19+
$filesCollection->drop();
20+
21+
// Drop chunks collection and insert duplicate, orphan chunks
22+
$chunksCollection = $db->selectCollection('fs.chunks');
23+
$chunksCollection->drop();
24+
$chunksCollection->insert(array(
25+
'_id' => new MongoId('000000000000000000000002'),
26+
'files_id' => new MongoId('000000000000000000000001'),
27+
'n' => 0,
28+
'data' => new MongoBinData('foo', MongoBinData::BYTE_ARRAY),
29+
));
30+
$chunksCollection->insert(array(
31+
'_id' => new MongoId('000000000000000000000003'),
32+
'files_id' => new MongoId('000000000000000000000001'),
33+
'n' => 0,
34+
'data' => new MongoBinData('bar', MongoBinData::BYTE_ARRAY),
35+
));
36+
37+
// Test three methods that start by ensuring the unique index
38+
echo "MongoGridFS::storeBytes():\n";
39+
40+
try {
41+
$db->getGridFS()->storeBytes('foo');
42+
} catch (MongoGridFSException $e) {
43+
echo $e->getMessage(), "\n";
44+
}
45+
46+
echo "\nMongoGridFS::storeFile():\n";
47+
48+
try {
49+
$db->getGridFS()->storeFile(__FILE__);
50+
} catch (MongoGridFSException $e) {
51+
echo $e->getMessage(), "\n";
52+
}
53+
54+
echo "\nMongoGridFS::remove():\n";
55+
56+
try {
57+
$db->getGridFS()->remove();
58+
} catch (MongoGridFSException $e) {
59+
echo $e->getMessage(), "\n";
60+
}
61+
62+
echo "\nDumping fs.files:\n";
63+
64+
foreach ($filesCollection->find() as $file) {
65+
var_dump($file);
66+
}
67+
68+
echo "\nDumping fs.chunks:\n";
69+
70+
foreach ($chunksCollection->find() as $chunk) {
71+
var_dump($chunk);
72+
}
73+
74+
?>
75+
==DONE==
76+
--CLEAN--
77+
<?php
78+
require_once "tests/utils/server.inc";
79+
80+
// Ensure our duplicate chunks are removed
81+
$host = MongoShellServer::getStandaloneInfo();
82+
$mc = new MongoClient($host);
83+
$mc->selectDB(dbname())->getGridFS()->drop();
84+
85+
?>
86+
--EXPECTF--
87+
MongoGridFS::storeBytes():
88+
Could not store file: %s:%d: %SE11000 duplicate key error index: %s.fs.chunks.$files_id_1_n_1%sdup key: { : ObjectId('000000000000000000000001'), : 0 }
89+
90+
MongoGridFS::storeFile():
91+
Could not store file: %s:%d: %SE11000 duplicate key error index: %s.fs.chunks.$files_id_1_n_1%sdup key: { : ObjectId('000000000000000000000001'), : 0 }
92+
93+
MongoGridFS::remove():
94+
Could not store file: %s:%d: %SE11000 duplicate key error index: %s.fs.chunks.$files_id_1_n_1%sdup key: { : ObjectId('000000000000000000000001'), : 0 }
95+
96+
Dumping fs.files:
97+
98+
Dumping fs.chunks:
99+
array(4) {
100+
["_id"]=>
101+
object(MongoId)#%d (1) {
102+
["$id"]=>
103+
string(24) "000000000000000000000002"
104+
}
105+
["files_id"]=>
106+
object(MongoId)#%d (1) {
107+
["$id"]=>
108+
string(24) "000000000000000000000001"
109+
}
110+
["n"]=>
111+
int(0)
112+
["data"]=>
113+
object(MongoBinData)#%d (2) {
114+
["bin"]=>
115+
string(3) "foo"
116+
["type"]=>
117+
int(2)
118+
}
119+
}
120+
array(4) {
121+
["_id"]=>
122+
object(MongoId)#%d (1) {
123+
["$id"]=>
124+
string(24) "000000000000000000000003"
125+
}
126+
["files_id"]=>
127+
object(MongoId)#%d (1) {
128+
["$id"]=>
129+
string(24) "000000000000000000000001"
130+
}
131+
["n"]=>
132+
int(0)
133+
["data"]=>
134+
object(MongoBinData)#%d (2) {
135+
["bin"]=>
136+
string(3) "bar"
137+
["type"]=>
138+
int(2)
139+
}
140+
}
141+
==DONE==

0 commit comments

Comments
 (0)