Skip to content

Commit ec3e1cc

Browse files
bjorijmikola
authored andcommitted
PHPC-377: Eliminate object casting and whole lot of zend hash helpers
Use BSON for all this parsing as that is the target format anyway Conflicts: php_phongo.c php_phongo.h src/MongoDB/Query.c
1 parent 9c0b848 commit ec3e1cc

File tree

3 files changed

+92
-48
lines changed

3 files changed

+92
-48
lines changed

php_phongo.c

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -316,75 +316,106 @@ void phongo_writeconcern_init(zval *return_value, const mongoc_write_concern_t *
316316
}
317317
/* }}} */
318318

319-
bool phongo_query_init(php_phongo_query_t *query, zval *filter, zval *options TSRMLS_DC) /* {{{ */
319+
int32_t phongo_bson_find_as_int32(bson_t *bson, const char *key, int32_t fallback)
320320
{
321-
bson_t bfilter;
321+
bson_iter_t iter;
322322

323-
if (!(Z_TYPE_P(filter) == IS_ARRAY || Z_TYPE_P(filter) == IS_OBJECT)) {
324-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected filter to be array or object, %s given", zend_get_type_by_const(Z_TYPE_P(filter)));
325-
return false;
323+
if (bson_iter_init_find(&iter, bson, key) && BSON_ITER_HOLDS_INT32(&iter)) {
324+
return bson_iter_int32(&iter);
326325
}
327-
convert_to_object(filter);
328326

329-
if (options) {
330-
/* TODO: Ensure batchSize, limit, and skip are 32-bit */
331-
query->batch_size = php_array_fetchc_long(options, "batchSize");
332-
query->limit = php_array_fetchc_long(options, "limit");
333-
query->skip = php_array_fetchc_long(options, "skip");
327+
return fallback;
328+
}
334329

335-
query->flags = 0;
336-
query->flags |= php_array_fetchl_bool(options, ZEND_STRS("tailable")) ? MONGOC_QUERY_TAILABLE_CURSOR : 0;
337-
query->flags |= php_array_fetchl_bool(options, ZEND_STRS("slaveOk")) ? MONGOC_QUERY_SLAVE_OK : 0;
338-
query->flags |= php_array_fetchl_bool(options, ZEND_STRS("oplogReplay")) ? MONGOC_QUERY_OPLOG_REPLAY : 0;
339-
query->flags |= php_array_fetchl_bool(options, ZEND_STRS("noCursorTimeout")) ? MONGOC_QUERY_NO_CURSOR_TIMEOUT : 0;
340-
query->flags |= php_array_fetchl_bool(options, ZEND_STRS("awaitData")) ? MONGOC_QUERY_AWAIT_DATA : 0;
341-
query->flags |= php_array_fetchl_bool(options, ZEND_STRS("exhaust")) ? MONGOC_QUERY_EXHAUST : 0;
342-
query->flags |= php_array_fetchl_bool(options, ZEND_STRS("partial")) ? MONGOC_QUERY_PARTIAL : 0;
330+
bool phongo_bson_find_as_bool(bson_t *bson, const char *key, bool fallback)
331+
{
332+
bson_iter_t iter;
343333

334+
if (bson_iter_init_find(&iter, bson, key) && BSON_ITER_HOLDS_BOOL(&iter)) {
335+
return bson_iter_bool(&iter);
336+
}
344337

345-
if (php_array_existsc(options, "modifiers")) {
346-
zval *modifiers = php_array_fetchc(options, "modifiers");
338+
return fallback;
339+
}
347340

348-
if (modifiers && !(Z_TYPE_P(modifiers) == IS_ARRAY || Z_TYPE_P(modifiers) == IS_OBJECT)) {
349-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected modifiers to be array or object, %s given", zend_get_type_by_const(Z_TYPE_P(modifiers)));
341+
void phongo_bson_iter_as_document(const bson_iter_t *iter, uint32_t *document_len, const uint8_t **document)
342+
{
343+
*document = NULL;
344+
*document_len = 0;
345+
346+
if (BSON_ITER_HOLDS_DOCUMENT(iter) || BSON_ITER_HOLDS_ARRAY(iter)) {
347+
memcpy (document_len, (iter->raw + iter->d1), sizeof (*document_len));
348+
*document_len = BSON_UINT32_FROM_LE (*document_len);
349+
*document = (iter->raw + iter->d1);
350+
}
351+
}
352+
353+
bool phongo_query_init(php_phongo_query_t *query, bson_t *filter, bson_t *options TSRMLS_DC) /* {{{ */
354+
{
355+
bson_iter_t iter;
356+
357+
if (options) {
358+
query->batch_size = phongo_bson_find_as_int32(options, "batchSize", 0);
359+
query->limit = phongo_bson_find_as_int32(options, "limit", 0);
360+
query->skip = phongo_bson_find_as_int32(options, "skip", 0);
361+
362+
query->flags = 0;
363+
query->flags |= phongo_bson_find_as_bool(options, "tailable", false) ? MONGOC_QUERY_TAILABLE_CURSOR : 0;
364+
query->flags |= phongo_bson_find_as_bool(options, "slaveOk", false) ? MONGOC_QUERY_SLAVE_OK : 0;
365+
query->flags |= phongo_bson_find_as_bool(options, "oplogReplay", false) ? MONGOC_QUERY_OPLOG_REPLAY : 0;
366+
query->flags |= phongo_bson_find_as_bool(options, "noCursorTimeout", false) ? MONGOC_QUERY_NO_CURSOR_TIMEOUT : 0;
367+
query->flags |= phongo_bson_find_as_bool(options, "awaitData", false) ? MONGOC_QUERY_AWAIT_DATA : 0;
368+
query->flags |= phongo_bson_find_as_bool(options, "exhaust", false) ? MONGOC_QUERY_EXHAUST : 0;
369+
query->flags |= phongo_bson_find_as_bool(options, "partial", false) ? MONGOC_QUERY_PARTIAL : 0;
370+
371+
372+
if (bson_iter_init_find(&iter, options, "modifiers")) {
373+
bson_t tmp;
374+
uint32_t len = 0;
375+
const uint8_t *data = NULL;
376+
377+
if (! (BSON_ITER_HOLDS_DOCUMENT (&iter) || BSON_ITER_HOLDS_ARRAY (&iter))) {
378+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected modifiers to be array or object, %d given", bson_iter_type(&iter));
350379
return false;
351380
}
352381

353-
zval_to_bson(modifiers, PHONGO_BSON_NONE, query->query, NULL TSRMLS_CC);
382+
bson_iter_document(&iter, &len, &data);
383+
bson_init_static(&tmp, data, len);
384+
bson_copy_to_excluding_noinit(&tmp, query->query, "nadastrada", NULL);
385+
bson_destroy (&tmp);
354386
}
355387

356-
if (php_array_existsc(options, "projection")) {
357-
zval *projection = php_array_fetchc(options, "projection");
388+
if (bson_iter_init_find(&iter, options, "projection")) {
389+
uint32_t len = 0;
390+
const uint8_t *data = NULL;
358391

359-
if (projection && !(Z_TYPE_P(projection) == IS_ARRAY || Z_TYPE_P(projection) == IS_OBJECT)) {
360-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected projection to be array or object, %s given", zend_get_type_by_const(Z_TYPE_P(projection)));
392+
if (! (BSON_ITER_HOLDS_DOCUMENT (&iter) || BSON_ITER_HOLDS_ARRAY (&iter))) {
393+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected projection to be array or object, %d given", bson_iter_type(&iter));
361394
return false;
362395
}
363396

364-
query->selector = bson_new();
365-
zval_to_bson(projection, PHONGO_BSON_NONE, query->selector, NULL TSRMLS_CC);
397+
bson_iter_document(&iter, &len, &data);
398+
query->selector = bson_new_from_data(data, len);
366399
}
367400

368-
if (php_array_existsc(options, "sort")) {
369-
bson_t bsort = BSON_INITIALIZER;
370-
zval *sort = php_array_fetchc(options, "sort");
401+
if (bson_iter_init_find(&iter, options, "sort")) {
402+
bson_t tmp;
403+
uint32_t len = 0;
404+
const uint8_t *data = NULL;
371405

372-
if (sort && !(Z_TYPE_P(sort) == IS_ARRAY || Z_TYPE_P(sort) == IS_OBJECT)) {
373-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected sort to be array or object, %s given", zend_get_type_by_const(Z_TYPE_P(sort)));
406+
if (! (BSON_ITER_HOLDS_DOCUMENT (&iter) || BSON_ITER_HOLDS_ARRAY (&iter))) {
407+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected sort to be array or object, %d given", bson_iter_type(&iter));
374408
return false;
375409
}
376410

377-
convert_to_object_ex(&sort);
378-
zval_to_bson(sort, PHONGO_BSON_NONE, &bsort, NULL TSRMLS_CC);
379-
BSON_APPEND_DOCUMENT(query->query, "$orderby", &bsort);
380-
bson_destroy(&bsort);
411+
phongo_bson_iter_as_document(&iter, &len, &data);
412+
bson_init_static(&tmp, data, len);
413+
bson_append_document(query->query, "$orderby", -1, &tmp);
414+
bson_destroy(&tmp);
381415
}
382416
}
383417

384-
bson_init(&bfilter);
385-
zval_to_bson(filter, PHONGO_BSON_NONE, &bfilter, NULL TSRMLS_CC);
386-
BSON_APPEND_DOCUMENT(query->query, "$query", &bfilter);
387-
bson_destroy(&bfilter);
418+
BSON_APPEND_DOCUMENT(query->query, "$query", filter);
388419
return true;
389420
} /* }}} */
390421

php_phongo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ PHONGO_API zend_object_handlers *phongo_get_std_object_handlers(void);
114114
void phongo_server_init (zval *return_value, mongoc_client_t *client, int server_id TSRMLS_DC);
115115
void phongo_readpreference_init (zval *return_value, const mongoc_read_prefs_t *read_prefs TSRMLS_DC);
116116
void phongo_writeconcern_init (zval *return_value, const mongoc_write_concern_t *write_concern TSRMLS_DC);
117-
bool phongo_query_init (php_phongo_query_t *query, zval *filter, zval *options TSRMLS_DC);
117+
bool phongo_query_init (php_phongo_query_t *query, bson_t *filter, bson_t *options TSRMLS_DC);
118118
mongoc_bulk_operation_t* phongo_bulkwrite_init (zend_bool ordered);
119119
bool phongo_execute_write (mongoc_client_t *client, const char *namespace, mongoc_bulk_operation_t *bulk, const mongoc_write_concern_t *write_concern, int server_id, zval *return_value, int return_value_used TSRMLS_DC);
120120
int phongo_execute_command (mongoc_client_t *client, const char *db, const bson_t *command, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC);

src/MongoDB/Query.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,38 @@ PHP_METHOD(Query, __construct)
5252
{
5353
php_phongo_query_t *intern;
5454
zend_error_handling error_handling;
55-
zval *filter;
56-
zval *options = NULL;
55+
zval *zfilter;
56+
zval *zoptions = NULL;
57+
bson_t bfilter;
58+
bson_t boptions = BSON_INITIALIZER;
5759
(void)return_value_ptr; (void)return_value; (void)return_value_used;
5860

5961

6062
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
6163
intern = (php_phongo_query_t *)zend_object_store_get_object(getThis() TSRMLS_CC);
6264

63-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "A|a!", &filter, &options) == FAILURE) {
65+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "A|a!", &zfilter, &zoptions) == FAILURE) {
6466
zend_restore_error_handling(&error_handling TSRMLS_CC);
6567
return;
6668
}
6769
zend_restore_error_handling(&error_handling TSRMLS_CC);
6870

6971

7072
intern->query = bson_new();
71-
if (!phongo_query_init(intern, filter, options TSRMLS_CC)) {
73+
74+
convert_to_object(zfilter);
75+
bson_init(&bfilter);
76+
zval_to_bson(zfilter, PHONGO_BSON_NONE, &bfilter, NULL TSRMLS_CC);
77+
78+
if (zoptions) {
79+
bson_init(&boptions);
80+
zval_to_bson(zoptions, PHONGO_BSON_NONE, &boptions, NULL TSRMLS_CC);
81+
}
82+
if (!phongo_query_init(intern, &bfilter, &boptions TSRMLS_CC)) {
7283
bson_clear(&intern->query);
7384
}
85+
bson_destroy(&bfilter);
86+
bson_destroy(&boptions);
7487
}
7588
/* }}} */
7689

0 commit comments

Comments
 (0)