Skip to content

Commit 04d589b

Browse files
committed
PHPC-255: Cursors cannot rewind after starting iteration
1 parent 95d1ed8 commit 04d589b

File tree

3 files changed

+105
-7
lines changed

3 files changed

+105
-7
lines changed

php_phongo.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,11 @@ static void php_phongo_cursor_iterator_rewind(zend_object_iterator *iter TSRMLS_
16731673
php_phongo_cursor_t *cursor = cursor_it->cursor;
16741674
const bson_t *doc;
16751675

1676+
if (cursor_it->current > 0) {
1677+
phongo_throw_exception(PHONGO_ERROR_LOGIC TSRMLS_CC, "Cursors cannot rewind after starting iteration");
1678+
return;
1679+
}
1680+
16761681
php_phongo_cursor_free_current(cursor);
16771682

16781683
doc = mongoc_cursor_current(cursor->cursor);

tests/standalone/cursor-iterator_handlers-001.phpt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ echo "\nAfter advancing, next element is populated:\n";
5151
$a->next();
5252
$a->dump();
5353

54-
echo "\nRewinding only populates current element and does not alter position:\n";
55-
$a->rewind();
56-
$a->dump();
57-
5854
echo "\nAdvancing through remaining elements:\n";
5955
$a->next();
6056
$a->dump();
@@ -82,9 +78,6 @@ A: 0 => {_id: 0}
8278
After advancing, next element is populated:
8379
A: 1 => {_id: 1}
8480

85-
Rewinding only populates current element and does not alter position:
86-
A: 1 => {_id: 1}
87-
8881
Advancing through remaining elements:
8982
A: 2 => {_id: 2}
9083
A: 3 => {_id: 3}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
--TEST--
2+
MongoDB\Driver\Cursor cannot rewind after starting iteration
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; CLEANUP(STANDALONE) ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
class MyIteratorIterator extends IteratorIterator
10+
{
11+
private $name;
12+
13+
public function __construct(Traversable $iterator, $name)
14+
{
15+
parent::__construct($iterator);
16+
$this->name = (string) $name;
17+
}
18+
19+
public function dump()
20+
{
21+
$key = parent::key();
22+
$current = parent::current();
23+
$position = is_int($key) ? (string) $key : 'null';
24+
$document = is_array($current) ? sprintf("{_id: %d}", $current['_id']) : 'null';
25+
printf("%s: %s => %s\n", $this->name, $position, $document);
26+
}
27+
}
28+
29+
$manager = new MongoDB\Driver\Manager(STANDALONE);
30+
31+
$bulkWrite = new MongoDB\Driver\BulkWrite;
32+
33+
for ($i = 0; $i < 5; $i++) {
34+
$bulkWrite->insert(array('_id' => $i));
35+
}
36+
37+
$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
38+
printf("Inserted: %d\n", $writeResult->getInsertedCount());
39+
40+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query(array()));
41+
$a = new MyIteratorIterator($cursor, 'A');
42+
43+
echo "\nRewinding sets the current element:\n";
44+
$a->rewind();
45+
$a->dump();
46+
47+
echo "\nRewinding again is OK since we haven't advanced:\n";
48+
$a->rewind();
49+
$a->dump();
50+
51+
echo "\nAdvancing populates the next element:\n";
52+
$a->next();
53+
$a->dump();
54+
55+
echo "\nRewinding after advancing is not OK:\n";
56+
try {
57+
$a->rewind();
58+
echo "FAILED: rewind should throw if iteration has started\n";
59+
} catch (MongoDB\Driver\Exception\LogicException $e) {
60+
printf("LogicException: %s\n", $e->getMessage());
61+
}
62+
63+
echo "\nAdvancing through remaining elements:\n";
64+
$a->next();
65+
$a->dump();
66+
$a->next();
67+
$a->dump();
68+
$a->next();
69+
$a->dump();
70+
71+
echo "\nAdvancing beyond the last element:\n";
72+
$a->next();
73+
$a->dump();
74+
75+
?>
76+
===DONE===
77+
<?php exit(0); ?>
78+
--EXPECT--
79+
Inserted: 5
80+
81+
Rewinding sets the current element:
82+
A: 0 => {_id: 0}
83+
84+
Rewinding again is OK since we haven't advanced:
85+
A: 0 => {_id: 0}
86+
87+
Advancing populates the next element:
88+
A: 1 => {_id: 1}
89+
90+
Rewinding after advancing is not OK:
91+
LogicException: Cursors cannot rewind after starting iteration
92+
93+
Advancing through remaining elements:
94+
A: 2 => {_id: 2}
95+
A: 3 => {_id: 3}
96+
A: 4 => {_id: 4}
97+
98+
Advancing beyond the last element:
99+
A: null => null
100+
===DONE===

0 commit comments

Comments
 (0)