-
Notifications
You must be signed in to change notification settings - Fork 209
PHPC-1050: Command cursor should not invoke getMore at execution #730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,7 +96,15 @@ static void php_phongo_cursor_iterator_move_forward(zend_object_iterator *iter T | |
const bson_t *doc; | ||
|
||
php_phongo_cursor_free_current(cursor); | ||
cursor->current++; | ||
|
||
/* If the cursor has already advanced, increment its position. Otherwise, | ||
* the first call to mongoc_cursor_next() will be made below and we should | ||
* leave its position at zero. */ | ||
if (cursor->advanced) { | ||
cursor->current++; | ||
} else { | ||
cursor->advanced = true; | ||
} | ||
|
||
|
||
if (mongoc_cursor_next(cursor->cursor, &doc)) { | ||
php_phongo_bson_to_zval_ex(bson_get_data(doc), doc->len, &cursor->visitor_data); | ||
|
@@ -117,6 +125,16 @@ static void php_phongo_cursor_iterator_rewind(zend_object_iterator *iter TSRMLS_ | |
php_phongo_cursor_t *cursor = cursor_it->cursor; | ||
const bson_t *doc; | ||
|
||
/* If the cursor was never advanced (e.g. command cursor), do so now */ | ||
if (!cursor->advanced) { | ||
cursor->advanced = true; | ||
|
||
if (!phongo_cursor_advance_and_check_for_error(cursor->cursor TSRMLS_CC)) { | ||
/* Exception should already have been thrown */ | ||
|
||
return; | ||
} | ||
} | ||
|
||
if (cursor->current > 0) { | ||
phongo_throw_exception(PHONGO_ERROR_LOGIC TSRMLS_CC, "Cursors cannot rewind after starting iteration"); | ||
return; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
--TEST-- | ||
PHPC-1050: Command cursor should not invoke getMore at execution | ||
--SKIPIF-- | ||
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?> | ||
<?php NEEDS('REPLICASET'); CLEANUP(REPLICASET); ?> | ||
--FILE-- | ||
<?php | ||
require_once __DIR__ . "/../utils/basic.inc"; | ||
|
||
$manager = new MongoDB\Driver\Manager(REPLICASET); | ||
|
||
$cmd = new MongoDB\Driver\Command( | ||
[ | ||
'aggregate' => COLLECTION_NAME, | ||
'pipeline' => [ | ||
['$changeStream' => (object) []], | ||
], | ||
'cursor' => (object) [], | ||
], | ||
[ | ||
'maxAwaitTimeMS' => 1000, | ||
] | ||
); | ||
|
||
$start = microtime(true); | ||
$cursor = $manager->executeReadCommand(DATABASE_NAME, $cmd); | ||
printf("Executing command took %0.6f seconds\n", microtime(true) - $start); | ||
|
||
$it = new IteratorIterator($cursor); | ||
|
||
$start = microtime(true); | ||
$it->rewind(); | ||
printf("Rewinding cursor took %0.6f seconds\n", microtime(true) - $start); | ||
printf("Current position is valid: %s\n", $it->valid() ? 'yes' : 'no'); | ||
|
||
$bulk = new MongoDB\Driver\BulkWrite; | ||
$bulk->insert(['x' => 1]); | ||
$manager->executeBulkWrite(NS, $bulk); | ||
|
||
$start = microtime(true); | ||
$it->next(); | ||
printf("Advancing cursor took %0.6f seconds\n", microtime(true) - $start); | ||
printf("Current position is valid: %s\n", $it->valid() ? 'yes' : 'no'); | ||
|
||
$document = $it->current(); | ||
|
||
if (isset($document)) { | ||
printf("Operation type: %s\n", $document->operationType); | ||
var_dump($document->fullDocument); | ||
} | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECTF-- | ||
Executing command took 0.%d seconds | ||
Rewinding cursor took 1.%d seconds | ||
Current position is valid: no | ||
Advancing cursor took %d.%d seconds | ||
Current position is valid: yes | ||
Operation type: insert | ||
object(stdClass)#%d (%d) { | ||
["_id"]=> | ||
object(MongoDB\BSON\ObjectId)#%d (%d) { | ||
["oid"]=> | ||
string(24) "%x" | ||
} | ||
["x"]=> | ||
int(1) | ||
} | ||
===DONE=== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
--TEST-- | ||
PHPC-1050: Command cursor should not invoke getMore at execution (rewind omitted) | ||
--SKIPIF-- | ||
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?> | ||
<?php NEEDS('REPLICASET'); CLEANUP(REPLICASET); ?> | ||
--FILE-- | ||
<?php | ||
require_once __DIR__ . "/../utils/basic.inc"; | ||
|
||
$manager = new MongoDB\Driver\Manager(REPLICASET); | ||
|
||
$cmd = new MongoDB\Driver\Command( | ||
[ | ||
'aggregate' => COLLECTION_NAME, | ||
'pipeline' => [ | ||
['$changeStream' => (object) []], | ||
], | ||
'cursor' => (object) [], | ||
], | ||
[ | ||
'maxAwaitTimeMS' => 1000, | ||
] | ||
); | ||
|
||
$start = microtime(true); | ||
$cursor = $manager->executeReadCommand(DATABASE_NAME, $cmd); | ||
printf("Executing command took %0.6f seconds\n", microtime(true) - $start); | ||
|
||
$it = new IteratorIterator($cursor); | ||
|
||
printf("Current position is valid: %s\n", $it->valid() ? 'yes' : 'no'); | ||
|
||
$start = microtime(true); | ||
$it->next(); | ||
printf("Advancing cursor took %0.6f seconds\n", microtime(true) - $start); | ||
|
||
printf("Current position is valid: %s\n", $it->valid() ? 'yes' : 'no'); | ||
|
||
$bulk = new MongoDB\Driver\BulkWrite; | ||
$bulk->insert(['x' => 1]); | ||
$manager->executeBulkWrite(NS, $bulk); | ||
|
||
$start = microtime(true); | ||
$it->next(); | ||
printf("Advancing cursor took %0.6f seconds\n", microtime(true) - $start); | ||
printf("Current position is valid: %s\n", $it->valid() ? 'yes' : 'no'); | ||
|
||
$document = $it->current(); | ||
|
||
if (isset($document)) { | ||
printf("Operation type: %s\n", $document->operationType); | ||
var_dump($document->fullDocument); | ||
} | ||
|
||
?> | ||
===DONE=== | ||
<?php exit(0); ?> | ||
--EXPECTF-- | ||
Executing command took 0.%d seconds | ||
Current position is valid: no | ||
Advancing cursor took 1.%d seconds | ||
Current position is valid: no | ||
Advancing cursor took %d.%d seconds | ||
Current position is valid: yes | ||
Operation type: insert | ||
object(stdClass)#%d (%d) { | ||
["_id"]=> | ||
object(MongoDB\BSON\ObjectId)#%d (%d) { | ||
["oid"]=> | ||
string(24) "%x" | ||
} | ||
["x"]=> | ||
int(1) | ||
} | ||
===DONE=== |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should not destroy the cursor, as
phongo_cursor_advance_and_check_for_error
already does that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
phongo_cursor_advance_and_check_for_error()
no longer destroys the cursor. That change was made because we don't want to destroy it from within the iterator handlers.