Skip to content

Commit ba8378e

Browse files
committed
PHP-1319: Implement command cursors
1 parent 000bdee commit ba8378e

File tree

4 files changed

+96
-20
lines changed

4 files changed

+96
-20
lines changed

php_phongo.c

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
/* External libs */
3030
#include <bson.h>
3131
#include <mongoc.h>
32+
#include <mongoc-cursor-cursorid-private.h>
3233

3334

3435
/* PHP Core stuff */
@@ -221,7 +222,7 @@ void phongo_log_writer(mongoc_stream_t *stream, int32_t timeout_msec, ssize_t se
221222
/* }}} */
222223

223224
/* {{{ Init objects */
224-
void phongo_result_init(zval *return_value, zend_class_entry *result_class, mongoc_cursor_t *cursor, const bson_t *bson, int server_hint TSRMLS_DC) /* {{{ */
225+
void phongo_result_init(zval *return_value, zend_class_entry *result_class, mongoc_cursor_t *cursor, const bson_t *bson, int server_hint, zend_bool is_command_cursor TSRMLS_DC) /* {{{ */
225226
{
226227
php_phongo_result_t *result;
227228

@@ -234,6 +235,7 @@ void phongo_result_init(zval *return_value, zend_class_entry *result_class, mong
234235
} else {
235236
result->hint = server_hint;
236237
}
238+
result->is_command_cursor = is_command_cursor;
237239
result->firstBatch = bson ? bson_copy(bson) : NULL;
238240
} /* }}} */
239241

@@ -310,7 +312,7 @@ void phongo_writeresult_init(zval *return_value, const bson_t *bson, int server_
310312
bson_iter_t iter, ar;
311313
php_phongo_writeresult_t *writeresult;
312314

313-
phongo_result_init(return_value, php_phongo_writeresult_ce, NULL, bson, server_hint TSRMLS_CC);
315+
phongo_result_init(return_value, php_phongo_writeresult_ce, NULL, bson, server_hint, 0 TSRMLS_CC);
314316
writeresult = (php_phongo_writeresult_t *)zend_object_store_get_object(return_value TSRMLS_CC);
315317

316318
if (bson_iter_init_find(&iter, bson, "nUpserted") && BSON_ITER_HOLDS_INT32(&iter)) {
@@ -622,14 +624,16 @@ int phongo_execute_query(mongoc_client_t *client, char *namespace, php_phongo_qu
622624
return true;
623625
}
624626

625-
phongo_result_init(return_value, php_phongo_queryresult_ce, cursor, doc, 0 TSRMLS_CC);
627+
phongo_result_init(return_value, php_phongo_queryresult_ce, cursor, doc, 0, 0 TSRMLS_CC);
626628
return true;
627629
} /* }}} */
628630

629631
int phongo_execute_command(mongoc_client_t *client, char *db, bson_t *command, mongoc_read_prefs_t *read_preference, zval *return_value, int return_value_used TSRMLS_DC) /* {{{ */
630632
{
631633
mongoc_cursor_t *cursor;
632634
const bson_t *doc;
635+
bson_iter_t iter;
636+
bson_iter_t child;
633637

634638

635639
cursor = mongoc_client_command(client, db, MONGOC_QUERY_NONE, 0, 1, 0, command, NULL, read_preference);
@@ -649,7 +653,28 @@ int phongo_execute_command(mongoc_client_t *client, char *db, bson_t *command, m
649653
return true;
650654
}
651655

652-
phongo_result_init(return_value, php_phongo_commandresult_ce, cursor, doc, 0 TSRMLS_CC);
656+
/* Detect if its an command cursor */
657+
if (bson_iter_init_find (&iter, doc, "cursor") && BSON_ITER_HOLDS_DOCUMENT (&iter) && bson_iter_recurse (&iter, &child)) {
658+
while (bson_iter_next (&child)) {
659+
if (BSON_ITER_IS_KEY (&child, "firstBatch")) {
660+
if (BSON_ITER_HOLDS_ARRAY (&child)) {
661+
const uint8_t *data = NULL;
662+
uint32_t data_len = 0;
663+
bson_t first_batch;
664+
665+
bson_iter_array (&child, &data_len, &data);
666+
if (bson_init_static (&first_batch, data, data_len)) {
667+
_phongo_debug_bson(&first_batch);
668+
_mongoc_cursor_cursorid_init(cursor);
669+
phongo_result_init(return_value, php_phongo_commandresult_ce, cursor, &first_batch, mongoc_cursor_get_hint(cursor), 1 TSRMLS_CC);
670+
return true;
671+
}
672+
}
673+
}
674+
}
675+
}
676+
677+
phongo_result_init(return_value, php_phongo_commandresult_ce, cursor, doc, mongoc_cursor_get_hint(cursor), 0 TSRMLS_CC);
653678
return true;
654679
} /* }}} */
655680

@@ -999,6 +1024,7 @@ void php_phongo_cursor_new_from_result(zval *object, php_phongo_result_t *result
9991024

10001025
intern = (php_phongo_cursor_t *)zend_object_store_get_object(object TSRMLS_CC);
10011026
intern->cursor = result->cursor;
1027+
intern->is_command_cursor = result->is_command_cursor;
10021028
intern->firstBatch = result->firstBatch;
10031029
intern->hint = result->hint;
10041030
} /* }}} */
@@ -1110,9 +1136,11 @@ void php_phongo_result_free(php_phongo_result_t *result)
11101136
typedef struct {
11111137
zend_object_iterator iterator;
11121138
zval *current;
1113-
mongoc_cursor_t *cursor;
1114-
bson_t *firstBatch;
1115-
int hint;
1139+
mongoc_cursor_t *cursor;
1140+
bson_t *firstBatch;
1141+
bson_iter_t first_batch_iter;
1142+
int hint;
1143+
zend_bool is_command_cursor;
11161144
} phongo_cursor_it;
11171145

11181146
static void phongo_cursor_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
@@ -1147,6 +1175,17 @@ static void phongo_cursor_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
11471175
cursor_it->current = NULL;
11481176
}
11491177

1178+
if (bson_iter_next(&cursor_it->first_batch_iter)) {
1179+
if (BSON_ITER_HOLDS_DOCUMENT (&cursor_it->first_batch_iter)) {
1180+
const uint8_t *data = NULL;
1181+
uint32_t data_len = 0;
1182+
1183+
bson_iter_document(&cursor_it->first_batch_iter, &data_len, &data);
1184+
MAKE_STD_ZVAL(cursor_it->current);
1185+
bson_to_zval(data, data_len, cursor_it->current);
1186+
return;
1187+
}
1188+
}
11501189
if (mongoc_cursor_next(cursor_it->cursor, &doc)) {
11511190
MAKE_STD_ZVAL(cursor_it->current);
11521191
bson_to_zval(bson_get_data(doc), doc->len, cursor_it->current);
@@ -1162,8 +1201,22 @@ static void phongo_cursor_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{
11621201

11631202
/* firstBatch is empty when the query simply didn't return any results */
11641203
if (cursor_it->firstBatch) {
1165-
MAKE_STD_ZVAL(cursor_it->current);
1166-
bson_to_zval(bson_get_data(cursor_it->firstBatch), cursor_it->firstBatch->len, cursor_it->current);
1204+
if (cursor_it->is_command_cursor) {
1205+
bson_iter_init(&cursor_it->first_batch_iter, cursor_it->firstBatch);
1206+
if (bson_iter_next (&cursor_it->first_batch_iter)) {
1207+
if (BSON_ITER_HOLDS_DOCUMENT (&cursor_it->first_batch_iter)) {
1208+
const uint8_t *data = NULL;
1209+
uint32_t data_len = 0;
1210+
1211+
bson_iter_document(&cursor_it->first_batch_iter, &data_len, &data);
1212+
MAKE_STD_ZVAL(cursor_it->current);
1213+
bson_to_zval(data, data_len, cursor_it->current);
1214+
}
1215+
}
1216+
} else {
1217+
MAKE_STD_ZVAL(cursor_it->current);
1218+
bson_to_zval(bson_get_data(cursor_it->firstBatch), cursor_it->firstBatch->len, cursor_it->current);
1219+
}
11671220
}
11681221
} /* }}} */
11691222

@@ -1200,11 +1253,12 @@ zend_object_iterator *phongo_cursor_get_iterator(zend_class_entry *ce, zval *obj
12001253
cursor_it = ecalloc(1, sizeof(phongo_cursor_it));
12011254

12021255
Z_ADDREF_P(object);
1203-
cursor_it->iterator.data = (void*)object;
1256+
cursor_it->iterator.data = (void*)object;
12041257
cursor_it->iterator.funcs = &phongo_cursor_it_funcs;
1205-
cursor_it->cursor = intern->cursor;
1206-
cursor_it->firstBatch = intern->firstBatch;
1207-
cursor_it->hint = intern->hint;
1258+
cursor_it->cursor = intern->cursor;
1259+
cursor_it->is_command_cursor = intern->is_command_cursor;
1260+
cursor_it->firstBatch = intern->firstBatch;
1261+
cursor_it->hint = intern->hint;
12081262

12091263
return (zend_object_iterator*)cursor_it;
12101264
} /* }}} */
@@ -1237,11 +1291,12 @@ zend_object_iterator *phongo_result_get_iterator(zend_class_entry *ce, zval *obj
12371291
cursor_it = ecalloc(1, sizeof(phongo_cursor_it));
12381292

12391293
Z_ADDREF_P(object);
1240-
cursor_it->iterator.data = (void*)object;
1294+
cursor_it->iterator.data = (void*)object;
12411295
cursor_it->iterator.funcs = &phongo_cursor_it_funcs;
1242-
cursor_it->cursor = intern->cursor;
1243-
cursor_it->firstBatch = intern->firstBatch;
1244-
cursor_it->hint = intern->hint;
1296+
cursor_it->cursor = intern->cursor;
1297+
cursor_it->firstBatch = intern->firstBatch;
1298+
cursor_it->hint = intern->hint;
1299+
cursor_it->is_command_cursor = intern->is_command_cursor;
12451300

12461301
return (zend_object_iterator*)cursor_it;
12471302
}
@@ -1273,6 +1328,17 @@ static void php_phongo_free(void *mem) /* {{{ */
12731328

12741329
/* }}} */
12751330

1331+
#ifdef PHP_DEBUG
1332+
void _phongo_debug_bson(bson_t *bson)
1333+
{
1334+
char *str;
1335+
size_t str_len;
1336+
1337+
str = bson_as_json(bson, &str_len);
1338+
1339+
php_printf("JSON: %s\n", str);
1340+
}
1341+
#endif
12761342

12771343
/* {{{ M[INIT|SHUTDOWN] R[INIT|SHUTDOWN] G[INIT|SHUTDOWN] MINFO INI */
12781344

php_phongo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ void php_phongo_new_regex_from_regex_and_options(zval *object, const char *patte
131131

132132
void php_phongo_result_free(php_phongo_result_t *result);
133133

134+
#ifdef PHP_DEBUG
135+
void _phongo_debug_bson(bson_t *bson);
136+
#else
137+
#define _phongo_debug_bson(bson)
138+
#endif
139+
134140
PHP_MINIT_FUNCTION(bson);
135141

136142
#endif /* PHONGO_H */

php_phongo_classes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ typedef struct {
3232
mongoc_cursor_t *cursor;
3333
bson_t *firstBatch;
3434
int hint;
35+
zend_bool is_command_cursor;
3536
} php_phongo_result_t;
3637

3738
typedef struct {
@@ -43,6 +44,7 @@ typedef struct {
4344
mongoc_cursor_t *cursor;
4445
bson_t *firstBatch;
4546
int hint;
47+
zend_bool is_command_cursor;
4648
} php_phongo_cursor_t;
4749

4850
typedef struct {

src/MongoDB/CommandResult.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ PHP_METHOD(CommandResult, getIterator)
8282
}
8383
zend_restore_error_handling(&error_handling TSRMLS_CC);
8484

85+
php_phongo_cursor_new_from_result(return_value, &intern->result TSRMLS_CC);
86+
8587
if (intern->result.ce_get_iterator) {
8688
object_init_ex(return_value, intern->result.ce_get_iterator);
87-
} else {
88-
php_phongo_cursor_new_from_result(return_value, &intern->result TSRMLS_CC);
8989
}
9090

9191
}
@@ -149,7 +149,9 @@ PHP_METHOD(CommandResult, getResponseDocument)
149149
zend_restore_error_handling(&error_handling TSRMLS_CC);
150150

151151

152-
bson_to_zval(bson_get_data(intern->result.firstBatch), intern->result.firstBatch->len, return_value);
152+
if (intern->result.firstBatch) {
153+
bson_to_zval(bson_get_data(intern->result.firstBatch), intern->result.firstBatch->len, return_value);
154+
}
153155
}
154156
/* }}} */
155157
/* {{{ proto MongoDB\Server CommandResult::getServer()

0 commit comments

Comments
 (0)